added support for database expressions.
This commit is contained in:
parent
76400967d9
commit
68455378cc
|
@ -109,6 +109,13 @@ public function first($sql, $bindings = array())
|
|||
*/
|
||||
public function query($sql, $bindings = array())
|
||||
{
|
||||
// First we need to remove all expressions from the bindings since
|
||||
// they will be placed into the query as raw strings.
|
||||
foreach ($bindings as $key => $value)
|
||||
{
|
||||
if ($value instanceof Expression) unset($bindings[$key]);
|
||||
}
|
||||
|
||||
$sql = $this->transform($sql, $bindings);
|
||||
|
||||
$this->queries[] = compact('sql', 'bindings');
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php namespace Laravel\Database;
|
||||
|
||||
class Expression {
|
||||
|
||||
/**
|
||||
* The value of the database expression.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Create a new database expression instance.
|
||||
*
|
||||
* @param string $value
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string value of the database expression.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string value of the database expression.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
<?php namespace Laravel\Database\Grammars; use Laravel\Arr, Laravel\Database\Query;
|
||||
<?php namespace Laravel\Database\Grammars;
|
||||
|
||||
use Laravel\Arr;
|
||||
use Laravel\Database\Query;
|
||||
use Laravel\Database\Expression;
|
||||
|
||||
class Grammar {
|
||||
|
||||
|
@ -105,10 +109,6 @@ protected function joins(Query $query)
|
|||
|
||||
foreach ($query->joins as $join)
|
||||
{
|
||||
// To save some space, we'll go ahead and wrap all of the elements
|
||||
// that should wrapped in keyword identifiers. Each join clause will
|
||||
// be added to an array of clauses and will be imploded after all
|
||||
// of the clauses have been processed and compiled.
|
||||
$table = $this->wrap($join['table']);
|
||||
|
||||
$column1 = $this->wrap($join['column1']);
|
||||
|
@ -147,12 +147,15 @@ final protected function wheres(Query $query)
|
|||
* This method handles the compilation of the structures created by the
|
||||
* "where" and "or_where" methods on the query builder.
|
||||
*
|
||||
* This method also handles database expressions, so care must be taken
|
||||
* to implement this functionality in any derived database grammars.
|
||||
*
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function where($where)
|
||||
{
|
||||
return $this->wrap($where['column']).' '.$where['operator'].' ?';
|
||||
return $this->wrap($where['column']).' '.$where['operator'].' '.$this->parameter($where['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,7 +294,10 @@ public function insert(Query $query, $values)
|
|||
*/
|
||||
public function update(Query $query, $values)
|
||||
{
|
||||
$columns = $this->columnize(array_keys($values), ' = ?');
|
||||
foreach ($values as $column => $value)
|
||||
{
|
||||
$columns = $this->wrap($column).' = '.$this->parameter($value);
|
||||
}
|
||||
|
||||
return trim('UPDATE '.$this->wrap($query->from).' SET '.$columns.' '.$this->wheres($query));
|
||||
}
|
||||
|
@ -316,21 +322,12 @@ public function delete(Query $query)
|
|||
/**
|
||||
* Create a comma-delimited list of wrapped column names.
|
||||
*
|
||||
* Optionally, an "append" value may be passed to the method.
|
||||
* This value will be appended to every wrapped column name.
|
||||
*
|
||||
* @param array $columns
|
||||
* @param string $append
|
||||
* @return string
|
||||
*/
|
||||
protected function columnize($columns, $append = '')
|
||||
protected function columnize($columns)
|
||||
{
|
||||
foreach ($columns as $column)
|
||||
{
|
||||
$sql[] = $this->wrap($column).$append;
|
||||
}
|
||||
|
||||
return implode(', ', $sql);
|
||||
return implode(', ', array_map(array($this, 'wrap'), $columns));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,6 +344,11 @@ protected function wrap($value)
|
|||
{
|
||||
if (strpos(strtolower($value), ' as ') !== false) return $this->alias($value);
|
||||
|
||||
// Expressions should be injected into the query as raw strings, so we
|
||||
// do not want to wrap them in any way. We will just return the string
|
||||
// value from the expression.
|
||||
if ($value instanceof Expression) return $value->get();
|
||||
|
||||
foreach (explode('.', $value) as $segment)
|
||||
{
|
||||
$wrapped[] = ($segment !== '*') ? $this->wrapper.$segment.$this->wrapper : $segment;
|
||||
|
@ -376,7 +378,22 @@ protected function alias($value)
|
|||
*/
|
||||
protected function parameterize($values)
|
||||
{
|
||||
return implode(', ', array_fill(0, count($values), '?'));
|
||||
return implode(', ', array_map(array($this, 'parameter'), $values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate query parameter string for a value.
|
||||
*
|
||||
* If the value is an expression, the raw expression string should
|
||||
* will be returned, otherwise, the parameter place-holder will be
|
||||
* returned by the method.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function parameter($value)
|
||||
{
|
||||
return ($value instanceof Expression) ? $value->get() : '?';
|
||||
}
|
||||
|
||||
}
|
|
@ -91,6 +91,19 @@ public static function table($table, $connection = null)
|
|||
return static::connection($connection)->table($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new database expression instance.
|
||||
*
|
||||
* Database expressions are used to inject raw SQL into a fluent query.
|
||||
*
|
||||
* @param string $value
|
||||
* @return Expression
|
||||
*/
|
||||
public static function raw($value)
|
||||
{
|
||||
return new Expression($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for calling methods on the default database connection.
|
||||
*
|
||||
|
|
|
@ -45,6 +45,26 @@ class Router {
|
|||
*/
|
||||
protected $controllers;
|
||||
|
||||
/**
|
||||
* The wildcard patterns supported by the router.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $patterns = array(
|
||||
'(:num)' => '[0-9]+',
|
||||
'(:any)' => '[a-zA-Z0-9\.\-_]+',
|
||||
);
|
||||
|
||||
/**
|
||||
* The optional wildcard patterns supported by the router.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $optional = array(
|
||||
'/(:num?)' => '(?:/([0-9]+)',
|
||||
'/(:any?)' => '(?:/([a-zA-Z0-9\.\-_]+)',
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a new router for a request method and URI.
|
||||
*
|
||||
|
@ -215,11 +235,13 @@ protected function translate_wildcards($key)
|
|||
// For optional parameters, first translate the wildcards to their
|
||||
// regex equivalent, sans the ")?" ending. We will add the endings
|
||||
// back on after we know how many replacements we made.
|
||||
$key = str_replace(array('/(:num?)', '/(:any?)'), array('(?:/([0-9]+)', '(?:/([a-zA-Z0-9\.\-_]+)'), $key, $replacements);
|
||||
$key = str_replace(array_keys($this->optional), array_values($this->optional), $key, $replacements);
|
||||
|
||||
$key .= ($replacements > 0) ? str_repeat(')?', $replacements) : '';
|
||||
|
||||
return str_replace(array(':num', ':any'), array('[0-9]+', '[a-zA-Z0-9\.\-_]+'), $key);
|
||||
// After replacing all of the optional wildcards, we can replace all
|
||||
// of the "regular" wildcards and return the fully regexed string.
|
||||
return str_replace(array_keys($this->patterns), array_values($this->patterns), $key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue