Commit 9718d5cd authored by Taylor Otwell's avatar Taylor Otwell

fix nested queries.

parent 97761f08
...@@ -38,7 +38,7 @@ class Query { ...@@ -38,7 +38,7 @@ class Query {
); );
/** /**
* Create a new query instance for a model. * Creat a new query instance for a model.
* *
* @param Model $model * @param Model $model
* @return void * @return void
...@@ -118,7 +118,7 @@ class Query { ...@@ -118,7 +118,7 @@ class Query {
$new = new $class(array(), true); $new = new $class(array(), true);
// We need to set the attributes manually in case the accessible property is // We need to set the attributes manually in case the accessible property is
// set on the array which will prevent the mass assignment of attributes if // set on the array which will prevent the mass assignemnt of attributes if
// we were to pass them in using the constructor or fill methods. // we were to pass them in using the constructor or fill methods.
$new->fill_raw($result); $new->fill_raw($result);
...@@ -141,7 +141,7 @@ class Query { ...@@ -141,7 +141,7 @@ class Query {
} }
} }
// The many to many relationships may have pivot table columns on them // The many to many relationships may have pivot table column on them
// so we will call the "clean" method on the relationship to remove // so we will call the "clean" method on the relationship to remove
// any pivot columns that are on the model. // any pivot columns that are on the model.
if ($this instanceof Relationships\Has_Many_And_Belongs_To) if ($this instanceof Relationships\Has_Many_And_Belongs_To)
...@@ -199,7 +199,7 @@ class Query { ...@@ -199,7 +199,7 @@ class Query {
foreach ($this->model_includes() as $include => $constraints) foreach ($this->model_includes() as $include => $constraints)
{ {
// To get the nested includes, we want to find any includes that begin // To get the nested includes, we want to find any includes that begin
// the relationship with a dot, then we will strip off the leading // the relationship and a dot, then we will strip off the leading
// nesting indicator and set the include in the array. // nesting indicator and set the include in the array.
if (starts_with($include, $relationship.'.')) if (starts_with($include, $relationship.'.'))
{ {
...@@ -217,23 +217,22 @@ class Query { ...@@ -217,23 +217,22 @@ class Query {
*/ */
protected function model_includes() protected function model_includes()
{ {
$relationships = array_keys($this->model->includes); $includes = array();
$implicits = array();
foreach ($relationships as $relationship) foreach ($this->model->includes as $relationship => $constraints)
{ {
$parts = explode('.', $relationship); // When eager loading relationships, constraints may be set on the eager
// load definition; however, is none are set, we need to swap the key
$prefix = ''; // and the value of the array since there are no constraints.
foreach ($parts as $part) if (is_numeric($relationship))
{ {
$implicits[$prefix.$part] = NULL; list($relationship, $constraints) = array($constraints, null);
$prefix .= $part.'.';
} }
$includes[$relationship] = $constraints;
} }
// Add all implicit includes to the explicit ones return $includes;
return $this->model->includes + $implicits;
} }
/** /**
...@@ -278,4 +277,4 @@ class Query { ...@@ -278,4 +277,4 @@ class Query {
return $this; return $this;
} }
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
use Closure; use Closure;
use Laravel\Database; use Laravel\Database;
use Paginator; use Laravel\Paginator;
use Laravel\Database\Query\Grammars\Postgres; use Laravel\Database\Query\Grammars\Postgres;
use Laravel\Database\Query\Grammars\SQLServer; use Laravel\Database\Query\Grammars\SQLServer;
...@@ -140,7 +140,7 @@ class Query { ...@@ -140,7 +140,7 @@ class Query {
*/ */
public function select($columns = array('*')) public function select($columns = array('*'))
{ {
$this->selects = is_array($columns) ? $columns : array($columns); $this->selects = (array) $columns;
return $this; return $this;
} }
...@@ -158,7 +158,7 @@ class Query { ...@@ -158,7 +158,7 @@ class Query {
{ {
// If the "column" is really an instance of a Closure, the developer is // If the "column" is really an instance of a Closure, the developer is
// trying to create a join with a complex "ON" clause. So, we will add // trying to create a join with a complex "ON" clause. So, we will add
// the join, and then call the Closure with the join. // the join, and then call the Closure with the join/
if ($column1 instanceof Closure) if ($column1 instanceof Closure)
{ {
$this->joins[] = new Query\Join($type, $table); $this->joins[] = new Query\Join($type, $table);
...@@ -168,7 +168,7 @@ class Query { ...@@ -168,7 +168,7 @@ class Query {
// If the column is just a string, we can assume that the join just // If the column is just a string, we can assume that the join just
// has a simple on clause, and we'll create the join instance and // has a simple on clause, and we'll create the join instance and
// add the clause automatically for the developer. // add the clause automatically for the develoepr.
else else
{ {
$join = new Query\Join($type, $table); $join = new Query\Join($type, $table);
...@@ -283,7 +283,7 @@ class Query { ...@@ -283,7 +283,7 @@ class Query {
*/ */
public function or_where_id($value) public function or_where_id($value)
{ {
return $this->or_where('id', '=', $value); return $this->or_where('id', '=', $value);
} }
/** /**
...@@ -395,7 +395,7 @@ class Query { ...@@ -395,7 +395,7 @@ class Query {
} }
/** /**
* Add nested constraints to the query. * Add a nested where condition to the query.
* *
* @param Closure $callback * @param Closure $callback
* @param string $connector * @param string $connector
...@@ -403,7 +403,24 @@ class Query { ...@@ -403,7 +403,24 @@ class Query {
*/ */
public function where_nested($callback, $connector = 'AND') public function where_nested($callback, $connector = 'AND')
{ {
call_user_func($callback, $this); $type = 'where_nested';
// To handle a nested where statement, we will actually instantiate a new
// Query instance and run the callback over that instance, which will
// allow the developer to have a fresh query instance
$query = new Query($this->connection, $this->grammar, $this->from);
call_user_func($callback, $query);
// Once the callback has been run on the query, we will store the nested
// query instance on the where clause array so that it's passed to the
// query's query grammar instance when building.
if ($query->wheres !== null)
{
$this->wheres[] = compact('type', 'query', 'connector');
}
$this->bindings = array_merge($this->bindings, $query->bindings);
return $this; return $this;
} }
...@@ -436,7 +453,7 @@ class Query { ...@@ -436,7 +453,7 @@ class Query {
foreach ($segments as $segment) foreach ($segments as $segment)
{ {
// If the segment is not a boolean connector, we can assume it is // If the segment is not a boolean connector, we can assume it it is
// a column name, and we'll add it to the query as a new constraint // a column name, and we'll add it to the query as a new constraint
// of the query's where clause and keep iterating the segments. // of the query's where clause and keep iterating the segments.
if ($segment != '_and_' and $segment != '_or_') if ($segment != '_and_' and $segment != '_or_')
...@@ -475,7 +492,6 @@ class Query { ...@@ -475,7 +492,6 @@ class Query {
* @param string $column * @param string $column
* @param string $operator * @param string $operator
* @param mixed $value * @param mixed $value
* @return Query
*/ */
public function having($column, $operator, $value) public function having($column, $operator, $value)
{ {
...@@ -660,7 +676,7 @@ class Query { ...@@ -660,7 +676,7 @@ class Query {
public function aggregate($aggregator, $columns) public function aggregate($aggregator, $columns)
{ {
// We'll set the aggregate value so the grammar does not try to compile // We'll set the aggregate value so the grammar does not try to compile
// a SELECT clause on the query. If an aggregator is present, its own // a SELECT clause on the query. If an aggregator is present, it's own
// grammar function will be used to build the SQL syntax. // grammar function will be used to build the SQL syntax.
$this->aggregate = compact('aggregator', 'columns'); $this->aggregate = compact('aggregator', 'columns');
...@@ -687,7 +703,7 @@ class Query { ...@@ -687,7 +703,7 @@ class Query {
{ {
// Because some database engines may throw errors if we leave orderings // Because some database engines may throw errors if we leave orderings
// on the query when retrieving the total number of records, we'll drop // on the query when retrieving the total number of records, we'll drop
// all of the orderings and put them back on the query. // all of the ordreings and put them back on the query.
list($orderings, $this->orderings) = array($this->orderings, null); list($orderings, $this->orderings) = array($this->orderings, null);
$total = $this->count(reset($columns)); $total = $this->count(reset($columns));
...@@ -714,12 +730,12 @@ class Query { ...@@ -714,12 +730,12 @@ class Query {
{ {
// Force every insert to be treated like a batch insert to make creating // Force every insert to be treated like a batch insert to make creating
// the binding array simpler since we can just spin through the inserted // the binding array simpler since we can just spin through the inserted
// rows as if there was more than one every time. // rows as if there/ was more than one every time.
if ( ! is_array(reset($values))) $values = array($values); if ( ! is_array(reset($values))) $values = array($values);
$bindings = array(); $bindings = array();
// We need to merge the insert values into the array of the query // We need to merge the the insert values into the array of the query
// bindings so that they will be bound to the PDO statement when it // bindings so that they will be bound to the PDO statement when it
// is executed by the database connection. // is executed by the database connection.
foreach ($values as $value) foreach ($values as $value)
...@@ -820,7 +836,7 @@ class Query { ...@@ -820,7 +836,7 @@ class Query {
/** /**
* Execute the query as a DELETE statement. * Execute the query as a DELETE statement.
* *
* Optionally, an ID may be passed to the method to delete a specific row. * Optionally, an ID may be passed to the method do delete a specific row.
* *
* @param int $id * @param int $id
* @return int * @return int
...@@ -837,7 +853,7 @@ class Query { ...@@ -837,7 +853,7 @@ class Query {
$sql = $this->grammar->delete($this); $sql = $this->grammar->delete($this);
return $this->connection->query($sql, $this->bindings); return $this->connection->query($sql, $this->bindings);
} }
/** /**
...@@ -853,7 +869,7 @@ class Query { ...@@ -853,7 +869,7 @@ class Query {
} }
// All of the aggregate methods are handled by a single method, so we'll // All of the aggregate methods are handled by a single method, so we'll
// catch them all here and then pass them off to the aggregate method // catch them all here and then pass them off to the agregate method
// instead of creating methods for each one of them. // instead of creating methods for each one of them.
if (in_array($method, array('count', 'min', 'max', 'avg', 'sum'))) if (in_array($method, array('count', 'min', 'max', 'avg', 'sum')))
{ {
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
## Contents ## Contents
- [Develop](#develop) - [Laravel 3.2.5](#3.2.5)
- [Upgrading From 3.2.4](#upgrade-3.2.5)
- [Laravel 3.2.4](#3.2.4) - [Laravel 3.2.4](#3.2.4)
- [Upgrading From 3.2.3](#upgrade-3.2.4) - [Upgrading From 3.2.3](#upgrade-3.2.4)
- [Laravel 3.2.3](#3.2.3) - [Laravel 3.2.3](#3.2.3)
...@@ -34,11 +35,14 @@ ...@@ -34,11 +35,14 @@
- [Laravel 3.1](#3.1) - [Laravel 3.1](#3.1)
- [Upgrading From 3.0](#upgrade-3.1) - [Upgrading From 3.0](#upgrade-3.1)
<a name="develop"></a> <a name="3.2.5"></a>
## Develop
- Added Turkish language files. - Revert nested where code back to 3.2.3 tag.
- Changed jQuery '$' to 'jQuery' in the Profiler.
<a name="upgrade-3.2.5"></a>
## Upgrading From 3.2.4
- Replace the **laravel** folder.
<a name="3.2.4"></a> <a name="3.2.4"></a>
## Laravel 3.2.4 ## Laravel 3.2.4
......
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