* @link http://netmonsters.ru * @package Majestic * @subpackage db * @since 2010-02-19 */ /** * @property MySQLiDriver $driver * @property \MySQLi_Result $result */ class MySQLiStatement extends DbStatement { protected $map = null; public function bindParam($param, &$value) { if ($this->map === null) { $this->mapPlaceholders(); } if (is_array($this->map) && count($this->map) > 0) { if (!is_string($param) && !is_int($param)) { throw new \Majestic\Exception\GeneralException('Placeholder must be an integer or string'); } if (is_object($value) && ! ($value instanceof DbExpr)) { throw new \Majestic\Exception\GeneralException('Objects excepts DbExpr not allowed.'); } if (isset($this->map[$param])) { $this->params[$param] = &$value; return true; } } return false; } protected function mapPlaceholders() { $matches = array(); if(preg_match_all('/(\?|:[A-z][A-z0-9_]*+)/u', $this->request, $matches, PREG_OFFSET_CAPTURE)) { $noname = 0; foreach ($matches[0] as $id=>$match) { $match[2] = $matches[1][$id][0]; $name = ($match[2][0] === ':') ? ltrim($match[2], ':') : $noname++; $this->map[$name]['placeholder'] = $match[0]; $this->map[$name]['offset'][] = $match[1]; } } } protected function assemble() { if (empty($this->map)) { return $this->request; } $query = $this->request; $placeholders = array(); foreach($this->map as $name => $place) { $value = $this->driver->quote($this->params[$name]); foreach ($place['offset'] as $offset) { $placeholders[$offset] = array('placeholder' => $place['placeholder'], 'value' => $value); } } ksort($placeholders); $increment = 0; foreach($placeholders as $current_offset => $placeholder) { $offset = $current_offset + $increment; $length = mb_strlen($placeholder['placeholder']); $query = mb_substr($query, 0, $offset) . $placeholder['value'] . mb_substr($query, $offset + $length); $increment = (($increment - $length) + mb_strlen($placeholder['value'])); } return $query; } /** * Fetches single row * * @param mixed $style * @return mixed * @throws \Majestic\Exception\GeneralException */ public function fetch($style = Db::FETCH_OBJ) { if (!$this->result) { return false; } switch ($style) { case Db::FETCH_OBJ: $row = $this->result->fetch_object(); break; case Db::FETCH_NUM: $row = $this->result->fetch_array(MYSQLI_NUM); break; case Db::FETCH_ASSOC: $row = $this->result->fetch_assoc(); break; case Db::FETCH_BOTH: $row = $this->result->fetch_array(MYSQLI_BOTH); break; default: throw new \Majestic\Exception\GeneralException('Invalid fetch mode "' . $style . '" specified'); } return $row; } /** * @param string $class * @return object */ public function fetchObject($class = 'stdClass') { return $this->result->fetch_object($class); } /** * @return array */ public function fetchPairs() { $data = array(); while ($row = $this->fetch(Db::FETCH_NUM)) { $data[$row[0]] = $row[1]; } return $data; } public function close() { if ($this->result !== null) { $this->result->close(); $this->result = null; } } public function affectedRows() { return $this->driver->getConnection()->affected_rows; } public function numRows() { if ($this->result) { return $this->result->num_rows; } return false; } public function getMysqliResult() { return $this->result; } protected function driverExecute($request) { /** * @var \MySQLi */ $mysqli = $this->driver->getConnection(); if (\Majestic\Config::get('PROFILER_DETAILS')) { $profiler = \Majestic\Util\Profiler\Profiler::getInstance()->profilerCommand('MySQL', $request); $result = $mysqli->query($request); $profiler->end(); } else { $result = $mysqli->query($request); } if ($result === false) { $message = $mysqli->error . "\nQuery: \"" . $request . '"'; throw new \Majestic\Exception\GeneralException($message, $mysqli->errno); } if ($result instanceof \MySQLi_Result) { $this->result = $result; } return true; } }