2017-10-13
This commit is contained in:
parent
9becae3750
commit
e3abb67d67
3 changed files with 60 additions and 67 deletions
|
@ -69,7 +69,7 @@ class DB extends PDO
|
|||
self::ATTR_DEFAULT_FETCH_MODE => self::FETCH_ASSOC,
|
||||
self::ATTR_EMULATE_PREPARES => false,
|
||||
self::ATTR_ERRMODE => self::ERRMODE_EXCEPTION,
|
||||
self::ATTR_STATEMENT_CLASS => array(DBStatement::class, [$this]),
|
||||
self::ATTR_STATEMENT_CLASS => [DBStatement::class, [$this]],
|
||||
];
|
||||
|
||||
parent::__construct($dsn, $username, $password, $options);
|
||||
|
@ -114,43 +114,28 @@ class DB extends PDO
|
|||
/**
|
||||
* Метод приводит запрос с типизированными плейсхолдерами к понятному для PDO виду
|
||||
*
|
||||
* @param string $query
|
||||
* @param string &$query
|
||||
* @param array $params
|
||||
*
|
||||
* @throws PDOException
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parse($query, array $params)
|
||||
protected function parse(&$query, array $params)
|
||||
{
|
||||
$idxIn = 0;
|
||||
$idxOut = 1;
|
||||
$map = [];
|
||||
$query = preg_replace_callback(
|
||||
'%(?=[?:])(?<![\w?])(\?(?![:?])(\w+)?)?(?:(::?)(\w+))?%i',
|
||||
'%(?=[?:])(?<![\w?:])(?:::(\w+)|\?(?![?:])(?:(\w+)(?::(\w+))?)?|:(\w+))%',
|
||||
function($matches) use ($params, &$idxIn, &$idxOut, &$map) {
|
||||
if (isset($matches[3]) && $matches[3] === '::') {
|
||||
return $this->dbPrefix . $matches[4];
|
||||
}
|
||||
|
||||
$type = $matches[2] ?: 's';
|
||||
|
||||
if (isset($matches[4])) {
|
||||
$key1 = ':' . $matches[4];
|
||||
$key2 = $matches[4];
|
||||
} else {
|
||||
$key1 = $idxIn;
|
||||
$key2 = $idxIn;
|
||||
++$idxIn;
|
||||
if (! empty($matches[1])) {
|
||||
return $this->dbPrefix . $matches[1];
|
||||
}
|
||||
|
||||
if (isset($params[$key1]) || array_key_exists($key1, $params)) {
|
||||
$value = $params[$key1];
|
||||
} elseif (isset($params[$key2]) || array_key_exists($key2, $params)) {
|
||||
$value = $params[$key2];
|
||||
} else {
|
||||
throw new PDOException("'$key1': No parameter for (?$type) placeholder");
|
||||
}
|
||||
$type = empty($matches[2]) ? 's' : $matches[2];
|
||||
$key = isset($matches[4]) ? $matches[4] : (isset($matches[3]) ? $matches[3] : $idxIn++);
|
||||
$value = $this->getValue($key, $params);
|
||||
|
||||
switch ($type) {
|
||||
case 'p':
|
||||
|
@ -160,50 +145,62 @@ class DB extends PDO
|
|||
case 'a':
|
||||
break;
|
||||
case 'i':
|
||||
$value = [$value];
|
||||
break;
|
||||
case 'b':
|
||||
$value = [$value];
|
||||
break;
|
||||
case 's':
|
||||
$value = [1];
|
||||
break;
|
||||
default:
|
||||
$value = [$value];
|
||||
$value = [1];
|
||||
$type = 's';
|
||||
break;
|
||||
}
|
||||
|
||||
if (! is_array($value)) {
|
||||
throw new PDOException("Expected array: key='{$key}', type='{$type}'");
|
||||
}
|
||||
|
||||
if (! isset($map[$key])) {
|
||||
$map[$key] = [$type];
|
||||
}
|
||||
|
||||
$res = [];
|
||||
foreach ($value as $val) {
|
||||
$name = ':' . $idxOut;
|
||||
++$idxOut;
|
||||
$name = ':' . $idxOut++;
|
||||
$res[] = $name;
|
||||
|
||||
if (empty($map[$key2])) {
|
||||
$map[$key2] = [$type, $name];
|
||||
} else {
|
||||
$map[$key2][] = $name;
|
||||
}
|
||||
$map[$key][] = $name;
|
||||
}
|
||||
return implode(',', $res);
|
||||
},
|
||||
$query
|
||||
);
|
||||
//var_dump($query);
|
||||
//var_dump($map);
|
||||
return [$query, $map];
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод связывает параметры запроса с соответвтующими значениями
|
||||
* Метод возвращает значение из массива параметров по ключу или исключение
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param array $params
|
||||
*
|
||||
* @throws PDOException
|
||||
*
|
||||
* @param PDOStatement $stmt
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
*/
|
||||
protected function bind(PDOStatement $stmt, array $bind)
|
||||
public function getValue($key, array $params)
|
||||
{
|
||||
foreach ($bind as $key => $val) {
|
||||
$stmt->bindValue($key, $val[0], $val[1]);
|
||||
if (
|
||||
is_string($key)
|
||||
&& (isset($params[':' . $key]) || array_key_exists(':' . $key, $params))
|
||||
) {
|
||||
return $params[':' . $key];
|
||||
} elseif (
|
||||
(is_string($key) || is_int($key))
|
||||
&& (isset($params[$key]) || array_key_exists($key, $params))
|
||||
) {
|
||||
return $params[$key];
|
||||
}
|
||||
|
||||
throw new PDOException("The '{$key}' key is not found in the parameters");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,7 +246,7 @@ class DB extends PDO
|
|||
*/
|
||||
public function exec($query, array $params = [])
|
||||
{
|
||||
list($query, $map) = $this->parse($query, $params);
|
||||
$map = $this->parse($query, $params);
|
||||
|
||||
if (empty($params)) {
|
||||
$start = microtime(true);
|
||||
|
@ -293,7 +290,8 @@ class DB extends PDO
|
|||
$options = [];
|
||||
}
|
||||
|
||||
list($query, $map) = $this->parse($query, $params);
|
||||
$map = $this->parse($query, $params);
|
||||
|
||||
$start = microtime(true);
|
||||
$stmt = parent::prepare($query, $options);
|
||||
$this->delta = microtime(true) - $start;
|
||||
|
@ -321,7 +319,7 @@ class DB extends PDO
|
|||
$params = [];
|
||||
}
|
||||
|
||||
list($query, $map) = $this->parse($query, $params);
|
||||
$map = $this->parse($query, $params);
|
||||
|
||||
if (empty($params)) {
|
||||
$start = microtime(true);
|
||||
|
|
|
@ -64,21 +64,16 @@ class DBStatement extends PDOStatement
|
|||
public function bindValueList(array $params)
|
||||
{
|
||||
foreach ($this->map as $key => $data) {
|
||||
if (isset($params[$key])) {
|
||||
$bValue = $params[$key];
|
||||
} elseif (isset($params[':' . $key])) {
|
||||
$bValue = $params[':' . $key];
|
||||
} else {
|
||||
throw new PDOException("The value for :{$key} placeholder isn't found");
|
||||
}
|
||||
|
||||
$type = array_shift($data);
|
||||
$bType = $this->types[$type];
|
||||
$bValue = $this->db->getValue($key, $params);
|
||||
|
||||
if ($type{0} === 'a') {
|
||||
if (! is_array($bValue)) {
|
||||
throw new PDOException("Expected array: key='{$key}'");
|
||||
}
|
||||
foreach ($data as $bParam) {
|
||||
$bVal = array_shift($bValue); //????
|
||||
parent::bindValue($bParam, $bVal, $bType); //????
|
||||
parent::bindValue($bParam, array_shift($bValue), $bType); //????
|
||||
}
|
||||
} else {
|
||||
foreach ($data as $bParam) {
|
||||
|
|
|
@ -524,16 +524,16 @@ class Topic extends Page
|
|||
}
|
||||
if ($flag) {
|
||||
if (empty($topic['mt_last_read']) && empty($topic['mt_last_visit'])) {
|
||||
$this->c->DB->exec('INSERT INTO ::mark_of_topic (uid, tid, mt_last_visit, mt_last_read)
|
||||
SELECT ?i:uid, ?i:tid, ?i:visit, ?i:read
|
||||
FROM ::groups
|
||||
WHERE NOT EXISTS (SELECT 1
|
||||
FROM ::mark_of_topic
|
||||
WHERE uid=?i:uid AND tid=?i:tid)
|
||||
$this->c->DB->exec('INSERT INTO ::mark_of_topic (uid, tid, mt_last_visit, mt_last_read)
|
||||
SELECT ?i:uid, ?i:tid, ?i:visit, ?i:read
|
||||
FROM ::groups
|
||||
WHERE NOT EXISTS (SELECT 1
|
||||
FROM ::mark_of_topic
|
||||
WHERE uid=?i:uid AND tid=?i:tid)
|
||||
LIMIT 1', $vars);
|
||||
} else {
|
||||
$this->c->DB->exec('UPDATE ::mark_of_topic
|
||||
SET mt_last_visit=?i:visit, mt_last_read=?i:read
|
||||
$this->c->DB->exec('UPDATE ::mark_of_topic
|
||||
SET mt_last_visit=?i:visit, mt_last_read=?i:read
|
||||
WHERE uid=?i:uid AND tid=?i:tid', $vars);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue