added support for complex joins on query builder.
This commit is contained in:
parent
326b5929e9
commit
e88d2213ab
|
@ -147,9 +147,28 @@ public function select($columns = array('*'))
|
|||
* @param string $type
|
||||
* @return Query
|
||||
*/
|
||||
public function join($table, $column1, $operator, $column2, $type = 'INNER')
|
||||
public function join($table, $column1, $operator = null, $column2 = null, $type = 'INNER')
|
||||
{
|
||||
$this->joins[] = compact('type', 'table', 'column1', 'operator', 'column2');
|
||||
// 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
|
||||
// the join, and then call the Closure with the join.
|
||||
if ($column1 instanceof Closure)
|
||||
{
|
||||
$this->joins[] = new Query\Join($type, $table);
|
||||
|
||||
call_user_func($column1, end($this->joins));
|
||||
}
|
||||
// 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
|
||||
// add the clause automatically for the develoepr.
|
||||
else
|
||||
{
|
||||
$join = new Query\Join($type, $table);
|
||||
|
||||
$join->on($column1, $operator, $column2);
|
||||
|
||||
$this->joins[] = $join;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class Grammar extends \Laravel\Database\Grammar {
|
|||
*/
|
||||
public function select(Query $query)
|
||||
{
|
||||
return $this->concatenate($this->components($query));
|
||||
die(var_dump($this->concatenate($this->components($query))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,12 +36,11 @@ final protected function components($query)
|
|||
{
|
||||
// Each portion of the statement is compiled by a function corresponding
|
||||
// to an item in the components array. This lets us to keep the creation
|
||||
// of the query very granular, and allows for the flexible customization
|
||||
// of the query building process by each database system's grammar.
|
||||
// of the query very granular and very flexible.
|
||||
//
|
||||
// Note that each component also corresponds to a public property on the
|
||||
// query instance, allowing us to pass the appropriate data into each of
|
||||
// the compiler functions.
|
||||
// Note that each component also connects to a public property on the
|
||||
// query instance, allowing us to pass the correct data into each
|
||||
// of the compiler functions.
|
||||
foreach ($this->components as $component)
|
||||
{
|
||||
if ( ! is_null($query->$component))
|
||||
|
@ -75,10 +74,6 @@ final protected function concatenate($components)
|
|||
*/
|
||||
protected function selects(Query $query)
|
||||
{
|
||||
// Sometimes developers may set a "select" clause on the same query
|
||||
// that is performing in aggregate look-up, like during pagination.
|
||||
// So we will not generate the select clause if an aggregate is
|
||||
// present so the aggregates work.
|
||||
if ( ! is_null($query->aggregate)) return;
|
||||
|
||||
$select = ($query->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
|
@ -129,15 +124,40 @@ protected function joins(Query $query)
|
|||
// set of joins in valid SQL that can appended to the query.
|
||||
foreach ($query->joins as $join)
|
||||
{
|
||||
$table = $this->wrap_table($join['table']);
|
||||
$table = $this->wrap_table($join->table);
|
||||
|
||||
$column1 = $this->wrap($join['column1']);
|
||||
$clauses = array();
|
||||
|
||||
$column2 = $this->wrap($join['column2']);
|
||||
// Each JOIN statement may have multiple clauses, so we will
|
||||
// iterate through each clause creating the conditions then
|
||||
// we will concatenate them all together.
|
||||
foreach ($join->clauses as $clause)
|
||||
{
|
||||
extract($clause);
|
||||
|
||||
$sql[] = "{$join['type']} JOIN {$table} ON {$column1} {$join['operator']} {$column2}";
|
||||
$column1 = $this->wrap($column1);
|
||||
|
||||
$column2 = $this->wrap($column2);
|
||||
|
||||
$clauses[] = "{$connector} {$column1} {$operator} {$column2}";
|
||||
}
|
||||
|
||||
// The first clause will have a connector on the front,
|
||||
// but it is not needed on the first condition, so we
|
||||
// will strip it off of the condition before adding
|
||||
// it to the array of joins.
|
||||
$search = array('AND ', 'OR ');
|
||||
|
||||
$clauses[0] = str_replace($search, '', $clauses[0]);
|
||||
|
||||
$clauses = implode(' ', $clauses);
|
||||
|
||||
$sql[] = "{$join->type} JOIN {$table} ON {$clauses}";
|
||||
}
|
||||
|
||||
// Finally, we should have an array of JOIN clauses
|
||||
// that we can implode together and return as the
|
||||
// complete SQL for the JOIN of the query.
|
||||
return implode(' ', $sql);
|
||||
}
|
||||
|
||||
|
@ -180,10 +200,6 @@ final protected function wheres(Query $query)
|
|||
*/
|
||||
protected function where_nested($where)
|
||||
{
|
||||
// To generate a nested WHERE clause, we'll just feed the query
|
||||
// back into the "wheres" method. Once we have the clause, we
|
||||
// will strip off the first six characters to get rid of the
|
||||
// leading WHERE keyword.
|
||||
return '('.substr($this->wheres($where['query']), 6).')';
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<?php namespace Laravel\Database\Query;
|
||||
|
||||
class Join {
|
||||
|
||||
/**
|
||||
* The type of join being performed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* The table the join clause is joining to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $table;
|
||||
|
||||
/**
|
||||
* The ON clauses for the join.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $clauses = array();
|
||||
|
||||
/**
|
||||
* Create a new query join instance.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $table
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($type, $table)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an ON clause to the join.
|
||||
*
|
||||
* @param string $column1
|
||||
* @param string $operator
|
||||
* @param string $column2
|
||||
* @param string $connector
|
||||
* @return Join
|
||||
*/
|
||||
public function on($column1, $operator, $column2, $connector = 'AND')
|
||||
{
|
||||
$this->clauses[] = compact('column1', 'operator', 'column2', 'connector');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an OR ON clause to the join.
|
||||
*
|
||||
* @param string $column1
|
||||
* @param string $operator
|
||||
* @param string $column2
|
||||
* @return Join
|
||||
*/
|
||||
public function or_on($column1, $operator, $column2)
|
||||
{
|
||||
return $this->on($column1, $operator, $column2, 'OR');
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue