Source of file AbstractBuilder.php
Size: 8,017 Bytes - Last Modified: 2017-11-08T13:54:24+00:00
/home/travis/build/bluzphp/framework/src/Db/Query/AbstractBuilder.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 | <?php /** * Bluz Framework Component * * @copyright Bluz PHP Team * @link https://github.com/bluzphp/framework */ declare(strict_types=1); namespace Bluz\Db\Query; use Bluz\Proxy\Db; /** * Query Builders classes is responsible to dynamically create SQL queries * Based on Doctrine QueryBuilder code * * @package Bluz\Db\Query * @link https://github.com/bluzphp/framework/wiki/Db-Query * @link https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Query/QueryBuilder.php */ abstract class AbstractBuilder { /** * @var array list of table aliases */ protected $aliases = []; /** * @var string the complete SQL string for this query */ protected $sql; /** * @var array the array of SQL parts collected */ protected $sqlParts = [ 'select' => [], 'from' => [], 'join' => [], 'set' => [], 'where' => null, 'groupBy' => [], 'having' => null, 'orderBy' => [] ]; /** * @var array the query parameters */ protected $params = []; /** * @var array the parameter type map of this query */ protected $types = []; /** * Execute this query using the bound parameters and their types * * @return integer|string|array */ public function execute() { return Db::query($this->getSql(), $this->params, $this->types); } /** * Return the complete SQL string formed by the current specifications * * Example * <code> * $sb = new SelectBuilder(); * $sb * ->select('u') * ->from('User', 'u'); * echo $qb->getSql(); // SELECT u FROM User u * </code> * * @return string The SQL query string */ abstract public function getSql() : string; /** * Return the complete SQL string formed for use * * Example * <code> * $sb = new SelectBuilder(); * $sb * ->select('u') * ->from('User', 'u') * ->where('id = ?', 42); * echo $qb->getQuery(); // SELECT u FROM User u WHERE id = "42" * </code> * * @return string */ public function getQuery() : string { $sql = $this->getSql(); $sql = str_replace(['%', '?'], ['%%', '"%s"'], $sql); // replace mask by data return vsprintf($sql, $this->getParameters()); } /** * Sets a query parameter for the query being constructed * * Example * <code> * $sb = new SelectBuilder(); * $sb * ->select('u') * ->from('users', 'u') * ->where('u.id = :user_id') * ->setParameter(':user_id', 1); * </code> * * @param string|int|null $key The parameter position or name * @param mixed $value The parameter value * @param integer $type PDO::PARAM_* * * @return $this */ public function setParameter($key, $value, $type = \PDO::PARAM_STR) { if (null === $key) { $key = count($this->params); } $this->params[$key] = $value; $this->types[$key] = $type; return $this; } /** * Sets a collection of query parameters for the query being constructed * * Example * <code> * $sb = new SelectBuilder(); * $sb * ->select('u') * ->from('users', 'u') * ->where('u.id = :user_id1 OR u.id = :user_id2') * ->setParameters([ * ':user_id1' => 1, * ':user_id2' => 2 * ]); * </code> * * @param array $params The query parameters to set * @param array $types The query parameters types to set * * @return $this */ public function setParameters(array $params, array $types = []) { $this->types = $types; $this->params = $params; return $this; } /** * Gets a (previously set) query parameter of the query being constructed * * @param mixed $key The key (index or name) of the bound parameter * * @return mixed The value of the bound parameter. */ public function getParameter($key) { return $this->params[$key] ?? null; } /** * Gets all defined query parameters for the query being constructed * * @return array The currently defined query parameters */ public function getParameters() : array { return $this->params; } /** * Either appends to or replaces a single, generic query part * * The available parts are: 'select', 'from', 'set', 'where', * 'groupBy', 'having' and 'orderBy' * * @param string $sqlPartName * @param string|array $sqlPart * @param bool $append * * @return $this */ protected function addQueryPart($sqlPartName, $sqlPart, $append = false) { $isArray = is_array($sqlPart); $isMultiple = is_array($this->sqlParts[$sqlPartName]); if ($isMultiple && !$isArray) { $sqlPart = [$sqlPart]; } if ($append) { if ($sqlPartName === 'orderBy' || $sqlPartName === 'groupBy' || $sqlPartName === 'select' || $sqlPartName === 'set' ) { foreach ((array)$sqlPart as $part) { $this->sqlParts[$sqlPartName][] = $part; } } elseif ($isArray && is_array($sqlPart[key($sqlPart)])) { $key = key($sqlPart); $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key]; } elseif ($isMultiple) { $this->sqlParts[$sqlPartName][] = $sqlPart; } else { $this->sqlParts[$sqlPartName] = $sqlPart; } } else { $this->sqlParts[$sqlPartName] = $sqlPart; } return $this; } /** * Get a query part by its name * * @param string $queryPartName * * @return mixed */ public function getQueryPart($queryPartName) { return $this->sqlParts[$queryPartName]; } /** * Reset single SQL part * * @param string $queryPartName * * @return $this */ protected function resetQueryPart($queryPartName) { $this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName]) ? [] : null; return $this; } /** * setFromQueryPart * * @param string $table * * @return $this */ protected function setFromQueryPart($table) { $table = Db::quoteIdentifier($table); return $this->addQueryPart('from', ['table' => $table], false); } /** * Prepare condition * * <code> * $builder->prepareCondition("WHERE id IN (?)", [..,..]); * </code> * * @param array $args * * @return string */ protected function prepareCondition($args = []) { $condition = array_shift($args); foreach ($args as &$value) { if (is_array($value)) { $replace = implode(',', array_fill(0, count($value), ':REPLACE:')); $condition = preg_replace('/\?/', $replace, $condition, 1); foreach ($value as $part) { $this->setParameter(null, $part); } } else { $this->setParameter(null, $value); } } $condition = preg_replace('/(\:REPLACE\:)/', '?', $condition); return $condition; } /** * Gets a string representation of this QueryBuilder which corresponds to * the final SQL query being constructed. * * @return string The string representation of this QueryBuilder. */ public function __toString() { return $this->getSql(); } } |