php-これよりもクエリで変数を管理するためのより良い方法はありますか?
いくつかの変数に応じてデータベースから特定のデータをクエリする必要がある場合、これを行うよりも良い方法はありますか?
<?php
if($_POST['condition'] == '1'){
$sign = '<';
$number = '3';
} else if($_POST['condition'] == '2'){
$sign = '>';
$number = '10';
}
SELECT value1, value2 FROM table WHERE id $sign $number
?>
これは、このような単純なクエリがある場合に機能しますが、 ORDER BY
にも特定の条件が必要であり、別のANDを追加する必要があります
と他のいくつかの条件があり、すぐにクエリはクエリというよりも変数のように見えます。
クエリを変更するために変数を使用する別の方法はありますか?そのようなクエリに多くの変数がある場合、それは悪いことですか?
実際に使用されているすべてのクエリは適切にフォーマットされ(うまくいけば)、準備されたステートメントを使用します。これはほんの一例です。
答え :
解決策:
このレベルでは、SQLを完全に生成する一連のコードを作成する以外に良い方法はないと思います。すでに実行を開始しており、別の観点からは、このような「if x then this sql elsethatsqlend」シナリオではやり過ぎです。値を適切にパラメーター化するという提案がありましたが、SQLを完全に制御していて、ユーザーデータをSQLに連結しておらず、思考をさらに複雑にする可能性がある場合、それはやや議論の余地があります。
読みやすく明確にするという点では、クエリよりも可変的なSQLの作成にあまり関与する価値はないでしょう。選択肢/バリエーションが制限されている場合(例には2つの選択肢しか含まれていない場合)、変更された形式でクエリを再度書き出すだけの方が便利な場合があります。
答え :
解決策:
数人のSOの人々がコメントしているように、すべてのWebアプリのベストプラクティスは、パラメーター化されたステートメントを使用することです。これにより、SQLインジェクションから保護され、パフォーマンスが向上します。
ユースケースの具体性は次のとおりです:
-
比較演算子をパラメーターとして渡すことはできません(それを可能にするRDBMSは考えられません)
POSTされた値をクエリに直接渡していない。代わりに、それらを使用して、クエリで使用する値を決定します。これは、SQLインジェクションにさらされていないことを意味します
結論として、あなたのアプローチは問題ないように見えます(ただし、クエリに直接渡すのではなく、«$ number»パラメータのパラメータを使用する場合-あなたはそれを行うと言いましたが、その部分を表示しませんでしたコード)。
クエリがより複雑になる場合は、上記の原則に固執する必要があります(可能な場合は常にパラメーターを使用してください)。
複雑さの管理が困難になった場合は、オブジェクトリレーショナルマッパーである ORM に移行することを検討してください。これにより、コードと生のSQLの間に別のレベルの間接参照が作成され、より多くの管理が可能になります。実際のSQLをあまり気にせずに複雑な要件。 Doctrine 、 propel 、...
など、PHPで利用できるソリューションはたくさんあります。
答え :
解決策:
クエリは安全なので、インジェクション攻撃に関するすべての冗談は無視してください。
一連の条件が増え続けると予想される場合は、 if-elseif-else
やcase-switch
ではなくルックアップ配列をお勧めします。彼らはあなたのスクリプトを肥大化させることになります。このようなことを考えてください...
$conditions = [
1 => "< 3",
2 => "> 10",
];
if (empty($_POST['condition']) || !isset($conditions[$_POST['condition']])) {
// write default behavior
} else {
// use $conditions[$_POST['condition']] in your query
}
このデータ構造とプロセスにより、一連の条件をクリーン、簡潔、効率的に拡張できます。
答え :
解決策:
はい、もっと良い方法があります。プリペアドステートメントを使用してSQLインジェクションを防ぐだけでなく、同じデータを使用してフロントエンドで選択を生成したり、クエリを作成したりできます。たとえば、この関数を見てください。
public function getFilterOptions(): array
{
return [
['name' => 'Age >30', 'comparator' => '>', 'comparable' => 30],
['name' => 'Age until 21', 'comparator' => '<=', 'comparable' => 21],
];
}
次に、このメソッドを使用して、フロントエンドでフィルター選択を生成できます。
echo '<select name="query_filter">';
foreach (getFilterOptions() as $key => $option) {
echo '<option value="' . $key . '">' . $option['name'] . '</option>';
}
echo '</select>';
質問者が使用しているテンプレートシステムがわからないため、このコードについてはご容赦ください。例としてプレーンPHPを使用するのが理にかなっています。
また、フィルターコードでは、指定されたインデックスを使用してフィルターオプションに直接アクセスできます。
$optionIndex = $_POST['query_filter'];
// TODO: you should check first if this index exists and handle errors appropriately
$option = getFilterOptions()[$optionIndex];
// building the query will be easy then...
// note: it is not possible to dynamically bind operators of a query
$stmt = $pdo->prepare("SELECT * FROM persons WHERE age $option['comparator'] :comparable");
$stmt->execute($option);
// or explicit: $stmt->execute(['comparable' => $option['comparable']]);
// using PDO is actually not really necessary here as the options are hard coded
// and not user-given, but it is best practice anyway...
この方法の利点は、すべてのフィルターオプションを中央に配置できるため、変更がより簡単かつ安全に行えることです。また、ユーザー入力に基づいてフィルターを選択するコードは、複数の if
およびelseifを使用するifよりもはるかに少なくなります。
ステートメント。
もちろん、これは非常に基本的な例にすぎません。特に、より複雑なフィルターを使用すると、かなり改善できます。たとえば、データベース列をフィルターオプションの一部にすることもできます。しかし、私はあなたに何が可能になるかについてのヒントを与えたかっただけです。
同様の質問
私たちのウェブサイトで同様の質問で答えを見つけてください。