OpenXE/classes/Components/Database/Parser/MysqliNamedParameterParser.php
2021-05-21 08:49:41 +02:00

80 lines
2.2 KiB
PHP

<?php
namespace Xentral\Components\Database\Parser;
use Xentral\Components\Database\Exception\MissingParameterException;
/**
* Responsibility of this class is to make sql statement and bind values compatible with mysqli
*
* (Mysqli does not support named parameters)
*
* It does this by:
* - Replacing named parameters (:param) by ?-Placeholder (in statement)
* - Rearranging bind values in order of appearance of named parameters
*/
final class MysqliNamedParameterParser implements ParserInterface
{
/**
* @param string $statement
* @param array $values
*
* @return array
*/
public function rebuild($statement, array $values = [])
{
return $this->replaceNamedParameters($statement, $values);
}
/**
* @param string $statement
* @param array $values
*
* @throws MissingParameterException
*
* @return array
*/
private function replaceNamedParameters($statement, array $values = [])
{
$result = [
'statement' => $statement,
'values' => [],
'params' => [],
];
if (empty($values)) {
return $result;
}
// Split statement on named parameters
$parts = preg_split('/(:[a-zA-Z0-9_]+)/um', $statement, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($parts as &$part) {
if (strpos($part, ':') !== 0) {
continue; // SQL part does not contain named parameter
}
$parameterName = substr_replace($part, '', 0, 1);
if (!array_key_exists($parameterName, $values)) {
throw new MissingParameterException(sprintf(
'Parameter "%s" is missing from the bound values',
$parameterName
));
}
// Push values in same order of parameters for binding
$result['values'][] = $values[$parameterName];
$result['params'][] = $parameterName; // For debugging only
// Replace named parameter by ?-Placeholder
$part = '?';
}
unset($part);
// Rebuild statement from (changed) parts
$result['statement'] = implode('', $parts);
return $result;
}
}