

Aravind Putrevu
November 18, 2024
20 min read
November 18, 2024
20 min read

PHPは簡潔で柔軟性があり、豊富なライブラリ、フレームワーク、ツールに支えられているため、今も最も人気のあるサーバーサイドスクリプト言語の一つです。しかし、広く使われているからこそ、セキュリティ脆弱性、保守性の問題、性能低下、コード品質の悪化につながる共通の課題もあります。
PHP開発者、チームリード、ソフトウェアエンジニアは、SQLインジェクション脆弱性、非効率なクエリ、不十分なエラー処理、コードの重複などを繰り返し目にします。適切に対処しなければ、開発を遅らせ、バグを入れ、アプリケーションをセキュリティリスクにさらします。
近年、AIはソフトウェア開発ライフサイクルを変革しました。CodeRabbitのようなAIコードレビューツールは、問題の特定と解決を自動化し、よりクリーンで効率的、安全なPHPコードを書きやすくします。コード品質を確認し、エラーの特定、修正提案、高い品質基準の維持を効率化します。
本稿では、PHPコードに共通する20の問題と、PR 1およびPR 2で示したCodeRabbitによる実践的な解決方法を紹介します。AIが特定のエラー修正を支援し、コード品質、セキュリティ、開発生産性をどう改善するかを理解できます。
できるだけ包括的な一覧にしたので、すでに対処済みの項目は読み飛ばしてください。
要約:PHPに共通する問題の一覧
頻度、影響、PHP開発との関連性に基づき、次のように分類します。
重大だが見落とされがちな問題: 影響が大きいにもかかわらず過小評価されやすく、安全で効率的なアプリケーションのために対応が不可欠です。
重要で関連性が高いが見逃されがちな問題: 明白でなくても、性能、セキュリティ、保守性へ大きく影響します。
コード品質全体のために対処すべき問題: 解決すると、コード品質とアーキテクチャが改善します。
手作業で修正することも、AIツールを使うこともできます。AIの修正提案を利用するにはCodeRabbitへ登録し、GitHubリポジトリへのアクセスを許可します。CodeRabbitがリポジトリ内のすべてのプルリクエストを自動的にレビューします。
信頼できないデータを適切に検証せずデシリアライズすると、攻撃者が悪意のあるデータ構造を挿入したり、アプリケーションのロジックを操作したりできます。ユーザーが制御するデータへunserialize()などを使うと、コード実行、データ操作、権限昇格につながる可能性があります。
// Deserialization with unserialize function
$data = $_POST['data'];
$object = unserialize($data);
次の画像のように、AIコードレビューツールを使えば、信頼できない入力のデシリアライズによる脆弱性を避けるため、PHPのシリアライズではなくJSONのシリアライズ機能を利用できます。

セッション管理は、問題が起きるまで意識しにくいものです。安全なセッション処理がなければ、セッションハイジャックや不正アクセスに対して脆弱になります。
// Insecure session setup
session_start();
経験豊富な開発者は通常、安全なセッション設定用のテンプレートを持っています。自動化ツールは弱い設定を見つけ、安全なCookieの設定、セッションIDの再生成、タイムアウトの実装などを提案します。これによりユーザーセッションを安全に保てます。

次の対策も行えます。
これらの改善によりユーザーセッションを保護し、アカウント侵害の可能性を減らします。
キャッシュがなければ、同じデータベース呼び出しを繰り返し、特にクエリやAPI呼び出しのような反復処理で速度が低下し、リソースを消費します。
// No caching, querying the database on every page load
$query = "SELECT * FROM posts";
$result = mysqli_query($connection, $query);
AIコードレビューツールは、キャッシュで性能を改善できる場所を特定し、次の画像のように最適な方法を提案します。データ取得を速め、不要なサーバー負荷を減らします。

この例でCodeRabbitが提案するのは、あらゆる言語に共通する標準的なキャッシュ手法です。
キャッシュ機会の特定を自動化すると、性能が向上し、読み込み時間が短くなります。
大きなファイルを一度に読み書きすると、性能問題やクラッシュが起きる可能性があります。全体をメモリへ読み込むと、使用量が増え、利用可能なメモリを使い切る場合もあります。
// loading a large file into memory
$data = file_get_contents('largefile.json');
非効率なファイルI/Oは手作業では見逃しがちですが、CodeRabbitのようなAIコードレビューツールが特定できます。次の画像は、大きなJSONファイルの非効率な処理についての指摘です。

ツールは次の改善を提案します。
ファイル処理が速まり、メモリ消費が減り、品質と性能が向上します。
PHPの動的配列は強力ですが、効率的に使わないと、特に大規模なデータセットで性能問題を起こします。
// Iterate over users array and extract name field into another array
$names = [];
foreach ($users as $user) {
$names[] = $user['name'];
}
自動化ツールは見逃された最適化の機会を特定し、次のように効率的な代替方法を提案します。

array_column()、array_map()、array_filter()などの組み込み関数は、ループより効率的な場合があります。配列処理の最適化は、大量のデータを扱うPHPアプリケーションの性能を大きく高めます。
PHPアプリケーションはSQLインジェクション、クロスサイトスクリプティング(XSS)、クロスサイトリクエストフォージェリ(CSRF)などの脆弱性に直面します。入力を適切に検証・無害化しなかったり、ユーザーデータを誤って扱ったりすると、攻撃者が悪意のあるコードを挿入し、データベース全体を侵害できます。安全でないセッション処理やパスワードのハッシュ化不足も、機密情報の漏えいにつながります。
現代のアプリケーションでは以前ほど一般的でなくても、データベースを直接操作したり、ユーザー生成コンテンツを扱ったりする場合、SQLインジェクションは依然として重大です。
// Retrieve the 'username' parameter and use it to construct a SQL query to select all columns from users
$user_input = $_GET['username'];
$query = "SELECT * FROM users WHERE username = '$user_input'";
$result = mysqli_query($connection, $query);
ユーザー入力をSQLクエリへ直接含めるのは安全ではなく、クエリ構築にSQLインジェクション脆弱性を生みます。



標準的な推奨事項は次のとおりです。
CSRFは、Webアプリケーションがユーザーのブラウザーを信頼することを悪用します。認証済みユーザーのブラウザーは、リクエストへセッションCookieなどの資格情報を自動的に含めます。攻撃者は悪意のあるリクエストを作り、メールのリンクや悪意のあるWebサイトなどのソーシャルエンジニアリングでユーザーに実行させます。アプリケーションは認証済みユーザーの正当な操作として処理します。
// start a session and process a post request to transfer amount to a recipient (vulnerable to CSRF)
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$amount = $_POST['amount'];
$recipient = $_POST['recipient'];
// Process the transfer (vulnerable to CSRF)
echo "Transferred $amount to $recipient";
}

自動化ツールは次の問題を検出し、改善を提案しました。
echo文における潜在的なXSS脆弱性これらのチェックを自動化すると、セキュリティリスクを大幅に減らし、一般的な攻撃からアプリケーションを保護できます。
exec()、shell_exec()、system()、passthru()はシステムコマンドを実行します。ユーザー入力を直接取り込むと危険で、入力の検証や無害化がなければ、攻撃者が悪意のあるコマンドを挿入してサーバーに実行させる可能性があります。
// Running system commands with input data
$filename = $_GET['filename'];
system("rm $filename");
AIコードレビューツールは、この危険なコマンドインジェクション脆弱性を検出し、unlink()関数などの安全な代替方法を提案できます。

パスワードを平文で保存したり、弱いハッシュアルゴリズムを使ったりすると、重大なセキュリティリスクになります。
// Insecure password storage
$password = md5('password123');
AIコードレビューツールは安全でない保存方法を検出し、機密データを守るためbcryptやArgon2のような強力なハッシュアルゴリズムを提案します。

PHPで静的メソッドを使いすぎると、コードの柔軟性が下がり、テストが難しくなります。
// Static method overuse
class User {
public static function getName() {
return "John";
}
}
自動化ツールは、次のように静的メソッドの過剰使用を特定します。

次の提案に沿ってリファクタリングすると品質を改善できます。
Cross-Origin Resource Sharing(CORS)は、Webページが異なるドメイン(オリジン)へリクエストする方法をブラウザーが制御するセキュリティ機能です。同一オリジンポリシー(SOP)を適用し、ページを提供したオリジンとは異なるオリジンへのリクエストを制限します。
悪意のあるWebサイトがユーザーに代わって不正なリクエストを送り、データ窃取や不正操作を行うことを防ぎます。ただし、設定を誤ると簡単にエラーが生じます。
// Configuration that allows Cross-Origin access
header("Access-Control-Allow-Origin: *"); // Allows any domain to access the resource
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE"); // Allows all HTTP methods
header("Access-Control-Allow-Headers: *"); // Allows all headers
header("Access-Control-Allow-Credentials: true"); // Allows credentials (cookies, authorization headers, etc.)
CORSの正しい設定は難しく、サーバー上で精密な設定を行い、安全性と機能性のバランスを取る必要があります。開発環境から異なるドメインの本番環境へ移す際に問題が生じがちです。
自動化ツールはリスクのある誤設定ヘッダーを特定し、次のように状況に合う設定を提案します。

コードがクラッシュしても、原因を追うための有用な情報が残らないことがあります。不十分なエラー処理では、コードベース内の見えない問題を追いかけるようになり、デバッグが複雑になって生産性が下がります。
// File handling without any error handling
$data = file_get_contents('data.txt');
try-catchブロックや、ファイル処理の状況を扱う適切なテストがないと、エラーや警告につながります。ファイルが存在しない、またはアクセスできない場合があります。

次のベストプラクティスも適用できます。
アプリケーションのコード品質と堅牢性が向上し、未処理の例外が性能やユーザー体験へ影響する可能性を減らします。
非推奨関数の使用は薄い氷の上を歩くようなものです。今は動いても、将来のPHPで壊れる可能性があります。
// Use of deprecated function split() for splitting string
$var = split(',', $string);
自動レビューツールは非推奨関数を指摘し、現代的な代替手段を提案して、将来の互換性問題を減らします。

データベースの資格情報やAPIキーなどをPHPファイルへハードコードすると、特にコードの共有・デプロイ時にセキュリティリスクがあります。既知のセキュリティ・保守性問題があるアンチパターンです。
$API_KEY = 'ThisISsomeRandomAPIKey';
AWS Secrets Manager、Azure Key Vault、HashiCorp Vaultなどの現代的なシークレット管理ツールにより以前ほど一般的ではありませんが、単純に見えるため、経験の浅い開発者が設定をソースへ直接書くことがあります。主な例は次のとおりです。
自動化ツールはPHPコード内のハードコード値を検出し、環境変数やシークレット管理システムなどの安全な方法を提案します。

推奨される方法は次のとおりです。
関数やクラスの欠落などによる致命的エラーが捕捉されないと、PHPアプリケーション全体がクラッシュします。解決までシステムが利用不能になり、ユーザー体験を損ないます。
// Fatal error due to undefined function
$result = getUserDetails;
AIツールは致命的エラーが起き得る場所を走査し、より適切な処理を提案します。

この場合の推奨事項は次のとおりです。
重大なエラーが起きても、アプリケーションの稼働と使いやすさを維持できます。
非効率なデータベースクエリは、アプリケーション性能の一般的なボトルネックです。過剰なデータ取得、不要なjoin、重要なインデックスの欠落により、非常に遅くなる場合があります。特に大規模なデータセットでは、最適化されていないクエリが性能と拡張性の問題を引き起こします。
// Inefficient database query: selecting all
$query = "SELECT * FROM users";
$result = mysqli_query($connection, $query);
非効率なクエリの特定は難しいものの、インデックスの追加や必要な列だけの取得によって最適化できます。高負荷でもアプリケーションを高速かつ滑らかに保てます。

コードレビューツールは、次のような非効率性を解析できます。
SELECTクエリ。適切なインデックスの追加、テーブルjoin数の削減、必要な列だけの選択などを提案します。
テストはコーディングで最も刺激的な作業ではないかもしれませんが、信頼性の確保には不可欠です。省略するとバグが本番環境へ入り込み、コード品質の維持が難しくなります。
// function to add two numbers
function add($a, $b) {
return $a + $b;
}
CodeRabbitなどの自動化ツールは、テストカバレッジが不足する場所を示せます。

通常は次を推奨します。
テストされていないコードの特定を自動化すると、信頼性と保守性が高まります。
データベース接続を閉じなかったり、リソースを解放しなかったりすると、メモリリークが気づかないうちにサーバーリソースを消費します。
// Memory leak due to unclosed connection
$connection = new mysqli($host, $user, $pass, $db);
自動レビューツールは、解放されない大きなオブジェクト割り当てなど、非効率なリソース使用を解析して潜在的なメモリリークを検出します。

次の解決策を提案します。
特に高負荷時に、アプリケーションの性能と拡張性を維持できます。
コードをコピー&ペーストし、意図せずプロジェクト全体へ事業ロジックを重複させたことがあるかもしれません。重複したブロックは保守コストを高め、変更時のバグ発生率を上げます。
次のコードでは、データベースへの接続、クエリ実行、結果処理が、ユーザーと製品データの取得で繰り返されています。
// Fetch user data
$conn = connectDatabase();
$sql = "SELECT * FROM users";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "User: " . $row["username"] . "<br>";
}
}
$conn->close();
// Fetch product data
$conn = connectDatabase();
$sql = "SELECT * FROM products";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "Product: " . $row["product_name"] . "<br>";
}
}
$conn->close();
重複ロジックはバグのリスクと保守作業を増やします。冗長な箇所を再利用可能な関数やクラスへまとめると、品質を改善し、コードベースをDRY(Don’t Repeat Yourself)でエラーの少ない状態に保てます。

CodeRabbitのようなAIコードレビューツールは、次の方法でDRY原則を促進します。
冗長性が減り、将来の保守が簡単になって、エラーも起きにくくなります。
深く入れ子になったループや条件分岐により、コードが過度に複雑になることがあります。読み取り、デバッグ、保守が難しくなり、プロジェクトの進化に伴って問題を起こす可能性があります。
// Complex nested conditionals
if ($a == 1) {
if ($b == 2) {
if ($c == 3) {
echo "Success";
}
}
}
複雑さを手作業で評価するには時間がかかります。CodeRabbitのようなAIコードレビューツールが役立ちます。

次の方法で改善できます。
単純なコードは保守しやすく、将来のバグを減らし、拡張性を高めます。
コーディングスタイルが一貫しないと、チームのプロジェクトが乱雑になり、共同作業が難しくなります。インデント、命名規則、フォーマットが異なると、コードベースはすぐに整理されていない状態になります。
// Non-conventional function naming style
function get_user_Data() {
return "User data";
}
PHP_CodeSnifferやPHPStanなどの代表的なPHP向けlintツールと同様、自動化ツールもPSR-2やPSR-12などの規約に基づく自動フォーマットと一貫性チェックを提供します。

一貫したコーディング・開発手法を適用すると、次の効果があります。
本稿ではPHPに共通する20の問題と、CodeRabbitのようなAIツールによる対処方法を取り上げました。ほかにも次の課題があります。
これらの戦略によりPHPプロジェクトの品質をさらに高め、長期的な成功に備えられます。
堅牢なPHPアプリケーションの開発では、性能最適化からコード品質とセキュリティの確保まで、さまざまな点へ対処する必要があります。手作業では時間がかかり、特にアプリケーションの規模と複雑さが増すとエラーも起きやすくなります。CodeRabbitのようなAIツールは、共通するPHP問題の検出と解決を自動化し、時間を節約して開発効率を高めます。
本稿では、SQLインジェクションなどの脆弱性を除いて安全性を高めることから、コード品質の改善まで、CodeRabbitが開発工程を大幅に簡素化できる20の場面を紹介しました。リポジトリと統合すると、プルリクエストのコードレビューを自動化し、潜在的な問題を特定し、徹底したテストとデバッグを支援します。
CodeRabbitの無料トライアルへ登録し、アプリケーション品質を高めながら、チームがより速く、より良く働ける自動レビューを体験してください。Discordチャンネルでは、開発者コミュニティとつながり、知見や取り組んでいるプロジェクトを共有できます。