想要在 PHP 中传递值列表(如在 Perl 中),而不是引用数组

Posted

技术标签:

【中文标题】想要在 PHP 中传递值列表(如在 Perl 中),而不是引用数组【英文标题】:Want to pass a list of values in PHP (as in Perl), not reference to array 【发布时间】:2014-02-04 12:05:21 【问题描述】:

我的头撞到了墙上,因为我习惯在 Perl 中做事的方式在 php 中不起作用。这很可能是非常基本的事情,我不知道如何正确地提出这个问题。症结:我习惯于将列表上下文中的数组作为参数发送给 Perl 中的函数,但在 PHP 中我只传递对数组的引用。

我正在尝试使用 mysqli 在 PHP 中进行基本的 SQL 查询,例如,SELECT * FROM my_table WHERE first_name = 'Bob' AND last_name = 'Smith' AND city = 'Akron'。诀窍是,我的代码事先并不知道查询中将包含哪些术语。查询是根据用户想要使用的搜索词动态形成的。在 Perl 中,这很容易。在 PHP 中,我不确定该怎么做。换一种方式问:如何在 PHP 中动态形成和传递值列表?

我习惯用 Perl 做什么:

my %terms = (
    'first_name' => 'Bob',
    'last_name' => 'Smith',
    'city' => 'Akron'
);

my @keys = keys %terms;
my $where_string = join(' AND ', map("$_ = ?", @keys));
my @values = @terms@keys;

my $sql = "SELECT * FROM my_table WHERE $where_string";
# Should give me 'SELECT * FROM my_table WHERE first_name = ? AND last_name = ? AND city = ?'
my $sth = $dbh->prepare($sql);
$sth->execute(@values);

我在 PHP 中尝试做的事情不起作用:

foreach ($terms as $key => $value) 
    $keys[] = "$key = ?";
    $values[] = $value;
    $types .= (is_numeric($value) ? "i" : "s");

$where_string = implode(' AND ', $keys);
$sql = "SELECT * FROM my_table WHERE $where_string";
$sth = $dbh->prepare($sql);
$sth->bind_param($types, $values);  # Only I need to pass @values,
                                    #   the list of the elements of the array,
                                    #   not a reference to the array
$result = $sth->execute();

可能是我的大脑太沉迷于 Perl,以至于我忘记了所有常识

【问题讨论】:

总是想知道为什么 mysqli 需要类型,而 DBD::mysql 可以没有它们。 我也是。这整个磨难让我想知道为什么我要使用 PHP。 (答案:所以我知道该怎么做。) 我希望您知道您的代码容易受到 SQL 注入的影响,并且性能不够好。您可以通过使用占位符和传递要执行的变量来解决这两个问题。 【参考方案1】:

你可能想要的是call_user_func_array():

$args = array_merge( array( $types ), $refs_to_values );
call_user_func_array( array( $sth, 'bind_param' ), $args );

是的,有点丑;有时 Perl 的灵活性是一个优势。

【讨论】:

也许子类化 mysqli 来隐藏丑陋。 谢谢!这最终让我到了那里。它需要稍微调整一下,因为 mysqli_stmt::bind_param 非常具体地期望一个值,然后是一系列引用。这有效: $args[] = $types; for ($i = 0; $i @LonelyPilgrim:很高兴看到你成功了!附言。如果您想在 cmets 中发布代码,请将其包装在反引号 ( ` ) 中。它看起来仍然不会很好,但至少它更具可读性。 谢谢。从 iPad 发布代码特别棘手!下次会有帮助。

以上是关于想要在 PHP 中传递值列表(如在 Perl 中),而不是引用数组的主要内容,如果未能解决你的问题,请参考以下文章

在源代码中嵌入较长文本的技巧,如在 Perl 等语言中? [复制]

perl 子程序参数列表 - “通过别名传递”?

对所有变量执行相同的操作,但在Perl函数中传递第一个变量

将表单值传递给 PHP 包含在 HTML DOM innerHTML 中

将 perl 正则表达式中的键和值传递给哈希

在 PHP 和 Perl 之间传递大量数据