Commit 68455378 authored by Taylor Otwell's avatar Taylor Otwell

added support for database expressions.

parent 76400967
......@@ -109,6 +109,13 @@ class Connection {
*/
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');
......
<?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();
}
}
\ No newline at end of file
<?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 @@ class Grammar {
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 @@ class Grammar {
* 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 @@ class Grammar {
*/
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 @@ class Grammar {
/**
* 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 @@ class Grammar {
{
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 @@ class Grammar {
*/
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() : '?';
}
}
\ No newline at end of file
......@@ -91,6 +91,19 @@ class Manager {
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 @@ class Router {
// 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);
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment