[Solar-talk] Disturbing Solar_Sql_Select problem
Paul M Jones
pmjones at ciaweb.net
Mon Feb 26 06:47:07 PST 2007
Hi all,
Just committed the fix for the new PDO behavior in PHP 5.2.1; here's
the change note:
> With PDO in PHP 5.2.1 and later, we can no longer just throw an array
> of data at the statement; we need to bind values specifically to their
> respective placeholders.
>
> In addition, we can't bind one value to multiple identical named
> placeholders; we need to bind that same value multiple times. So if
> :foo is used three times, PDO uses :foo the first time, :foo2 the
> second time, and :foo3 the third time.
>
> This query() method examins the statement for all :name placeholders
> and attempts to bind data from the $data array. The regular-
> expression
> it uses is a little braindead; it cannot tell if the :name placeholder
> is literal text or really a place holder.
>
> As such, you should *either* use the $data array for named-placeholder
> value binding at query() time, *or* bind-as-you-go when building the
> statement, not both. If you do, you are on your own to make sure
> that nothing looking like a :name placeholder exists as literal text.
>
> Question-mark placeholders are no longer supported for automatic
> value binding at query() time.
The new logic in Solar_Sql_Adapter::query() looks like this:
// prepare the statment
$obj = $this->_pdo->prepare($stmt);
// was data passed for binding?
if ($data) {
// find all :placeholder matches. note that this is a little
// brain-dead; it will find placeholders in literal text, which
// will cause errors later. so in general, you should *either*
// bind at query time *or* bind as you go, not both.
preg_match_all(
"/\W(:[a-zA-Z_][a-zA-Z0-9_]+?)\W/m",
$stmt . "\n",
$matches
);
// bind values to placeholders, repeating as needed
$repeat = array();
foreach ($matches[1] as $key) {
// only attempt to bind if the data key exists.
// this allows for nulls and empty strings.
if (! array_key_exists($key, $data)) {
// skip it
continue;
}
// what does PDO expect as the placeholder name?
if (empty($repeat[$key])) {
// first time is ":foo"
$repeat[$key] = 1;
$name = $key;
} else {
// repeated times of ":foo" are treated by PDO as
// ":foo2", ":foo3", etc.
$repeat[$key] ++;
$name = $key . $repeat[$key];
}
// bind the value to the placeholder name
$stmt->bindValue($name, $data[$key]);
}
}
// now try to execute
try {
$obj->execute();
--
Paul M. Jones <http://paul-m-jones.com>
Solar: Simple Object Library and Application Repository
for PHP5. <http://solarphp.com>
Join the Solar community wiki! <http://solarphp.org>
Savant: The simple, elegant, and powerful solution for
templates in PHP. <http://phpsavant.com>
More information about the solar-talk
mailing list