php传参字段名冒号,PDO准备语句 - 用于参数名称的冒号是什么?

不,你没有遗漏任何东西。您必须使用冒号(:),在SQL字符串指定的占位符,但执行该语句或绑定参数时,它们不是必需的。PHP将推断出:是否在该上下文中将其保留(请参阅下面的第二部分,以获取PHP解释器本身的源代码的解释和证明)。

什么工作(你可以用PHP做什么)

换句话说,这是可以接受的:

$insertRecord = $conn->prepare('INSERT INTO Table1 (column1, column2)

VALUES(:column1, :column2)');

//         ^         ^  note the colons

但事实并非如此,因为占位符名称不明确,看起来像列(或其他)名称:

$insertRecord = $conn->prepare('INSERT INTO Table1 (column1, column2)

VALUES(column1, column2)');

//         ^        ^  no colons

相比之下,使用PDOStatement::bindParam()或时,冒号是可选的PDOStatement::execute()。这两项工作基本相同:*

$insertRecord->execute(array(

':column1' => $column1,

':column2' => $column2

));

// or

$insertRecord->execute(array(

'column1' => $column1,

'column2' => $column2

));

为什么会这样(探索PHP源代码)

为什么这样工作?那么,为此我们必须进入PHP本身的c语言源代码。为了保持最新,我使用了github(PHP 7)的最新源代码,但同样的基本分析适用于早期版本。

PHP语言期望命名占位符在SQL中具有冒号,如文档中所述。并且文档用于PDOStatement::bindParam()指示将参数:name绑定到占位符时参数必须是表单。但由于接下来的原因,这并不是真的。

当绑定参数或执行语句时,不存在歧义的风险,因为SQL占位符必须只有一个冒号。这意味着PHP解释器可以做出一个关键的假设并安全地这样做。如果您查看pdo_sql_parser.cPHP源代码,特别是第90行,您可以在占位符中看到有效的字符列表,即字母数字(数字和字母),下划线和冒号。继该文件中的代码的逻辑是有点棘手,很难在这里说明一下-我伤心地说,它涉及到很多的goto报表,但短期的版本是,只有第一个字符可以是一个冒号。

简单地说,:name就是在SQL的有效占位,但name并::name没有。

这意味着解析器可以安全地假设到达bindParam()或者execute()指定的参数name应该是真的:name。也就是说,它可以:在参数名称的其余部分之前添加一个。事实上,pdo_stmt.c从第362行开始,这正是它的作用:

if (param->name) {

if (is_param && param->name[0] != ':') {

char *temp = emalloc(++param->namelen + 1);

temp[0] = ':';

memmove(temp+1, param->name, param->namelen);

param->name = temp;

} else {

param->name = estrndup(param->name, param->namelen);

}

}

它的作用是略微简化的伪代码:

if the parameter has a name then

if the parameter name does not start with ':' then

allocate a new string, 1 character larger than the current name

add ':' at the start of that string

copy over the rest of the name to the new string

replace the old string with the new string

else

call estrndup, which basically just copies the string as-is (see https://github.com/php/php-src/blob/1c295d4a9ac78fcc2f77d6695987598bb7abcb83/Zend/zend_alloc.h#L173)

因此,name(在bindParam()或的上下文中execute())变得:name与我们的SQL匹配,PDO非常高兴。

最佳实践

从技术上讲,无论哪种方式都有效,所以你可以说这是一个偏好问题。但是,如果不是很明显,那就没有详细记录。我不得不深入研究源代码来解决这个问题,理论上它可以在任何时候改变。为了在IDE中保持一致性,可读性和更轻松的搜索,请使用冒号。

*我说他们的工作“基本上”相同,因为上面的c代码对于放弃冒号施加了极小的惩罚。它必须分配更多内存,构建一个新字符串,并替换旧字符串。也就是说,这个名字的惩罚在纳秒范围内:name。如果你很容易给你的参数很长(比如64 Kb)并且你有很多它们,那么它可能会变得可测量,在这种情况下你会遇到其他问题......无论如何,当冒号添加时,这些都不重要读取和解析文件的时间极短,因此这两个极小的惩罚甚至可能会被抵消。如果你担心这个级别的表现,那么你在晚上保持清醒时会遇到比我们其他人更冷的问题。此外,您应该在纯汇编程序中构建Web应用程序。 sarcasm>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值