繁体   English   中英

有没有比这更好的方法来管理查询中的变量?

[英]Is there a better way of managing variables in query than this?

如果我需要根据某些变量从数据库中查询某些数据,还有没有比这更好的方法了?

<?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的代码外,没有更好的方法。从一个角度来看,您实际上已经开始这样做了,而从另一个角度来看,这对于像这样的“如果x那么此sql则该sql结束”。 有人建议正确地设置值的参数,但是如果您完全控制sql并且不将用户数据连接到其中,并且可能使思考更加复杂,那么这有点无济于事。

就保持事物的可读性和清晰性而言,过多地编写比查询更可变的sql可能不值得。 如果选择/变量受到限制(您的示例仅包含2个选择),则可以以更改后的形式再次写出查询,这可能会有更多的实用程序

是的,有更好的方法。 除了使用准备好的语句防止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...

这样做的好处是,您可以将所有过滤器选项放在一个中央位置,从而使更改既简单又安全。 同样,基于用户输入选择过滤器的代码比使用多个ifelse if语句要少得多。

当然,这只是一个非常基本的示例,您可以对其进行很多改进,尤其是使用更复杂的过滤器时。 例如,您也可以将数据库列作为过滤器选项的一部分。 但我只是想给您提示可能的事。

正如一些SO人士所说,在每个Web应用程序中,最佳实践是使用参数化语句。 这样可以防止SQL注入,并提高性能。

您的用例的特殊性是:

  • 比较运算符不能作为参数传递(我想不到任何RDBMS都可以这样做)

  • 您没有将POSTed值直接传递给查询。 而是使用它们来决定在查询中应使用哪些值。 这意味着您不会将自己暴露于SQL注入

得出的结论是,您的方法看起来不错(假设您确实对«$ number»参数使用了参数,而不是直接将其传递给查询-您说过做到了,但是没有显示代码的那部分)。

当查询变得更加复杂时,您希望遵守上述原则(尽可能使用参数)。

如果复杂性变得难以管理,那么您可以考虑使用ORM (对象关系映射器),它在代码和原始SQL之间创建了另一层间接访问,从而使您可以管理更复杂的需求,而不必太担心实际的SQL。 PHP提供了许多解决方案,例如Doctrinepropel ,...

您的查询是安全的,因此请忽略有关注入攻击的所有玩笑。

如果您希望情况持续增长,那么我建议您使用查找数组而不是if-elseif-elsecase-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
}

这种数据结构和过程使清洁,简明和高效的条件电池扩展成为可能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM