Permalink
Browse files

Work on "has" method passing along constraints.

  • Loading branch information...
taylorotwell committed Oct 31, 2013
1 parent e02bcae commit 7196279d1f6c5a9e067beb6f39fea5eaa50e7c19
@@ -587,15 +587,47 @@ protected function isNested($name, $relation)
*/
public function has($relation, $operator = '>=', $count = 1, $boolean = 'and')
{
$instance = $this->model->$relation();
$relation = $this->getHasRelationQuery($relation);
$query = $instance->getRelationCountQuery($instance->getRelated()->newQuery());
$query = $relation->getRelationCountQuery($relation->getRelated()->newQuery());
$this->query->mergeBindings($query->getQuery());
$this->mergeWheresToHas($query, $relation);
return $this->where(new Expression('('.$query->toSql().')'), $operator, $count, $boolean);
}
/**
* Merge the "wheres" from a relation query to a has query.
*
* @param \Illuminate\Database\Eloquent\Builder $hasQuery
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
* @return void
*/
protected function mergeWheresToHas(Builder $hasQuery, Relation $relation)
{
$relationQuery = $relation->getBaseQuery();
$hasQuery->mergeWheres($relationQuery->wheres, $relationQuery->getBindings());
$this->query->mergeBindings($relationQuery);
}
/**
* Get the "has relation" base query instance.
*
* @param string $relation
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function getHasRelationQuery($relation)
{
$me = $this;
return Relation::noConstraints(function() use ($me, $relation)
{
return $me->getModel()->$relation();
});
}
/**
* Add a relationship count condition to the query with an "or".
*
@@ -740,7 +740,7 @@ public function detach($ids = array(), $touch = true)
* @return void
*/
public function touchIfTouching()
{
{
if ($this->touchingParent()) $this->getParent()->touch();
if ($this->getParent()->touches($this->relationName)) $this->touch();
@@ -863,6 +863,16 @@ public function getRelatedFreshUpdate()
return array($this->related->getUpdatedAtColumn() => $this->related->freshTimestamp());
}
/**
* Get the key for comparing against the pareny key in "has" query.
*
* @return string
*/
public function getHasCompareKey()
{
return $this->getForeignKey();
}
/**
* Get the fully qualified foreign key for the relation.
*
@@ -883,6 +893,16 @@ public function getOtherKey()
return $this->table.'.'.$this->otherKey;
}
/**
* Get the fully qualified parent key naem.
*
* @return string
*/
protected function getQualifiedParentKeyName()
{
return $this->parent->getQualifiedKeyName();
}
/**
* Get the intermediate table for the relationship.
*
@@ -36,25 +36,42 @@ public function __construct(Builder $query, Model $farParent, Model $parent, $fi
*/
public function addConstraints()
{
$this->setJoin($parentTable = $this->parent->getTable());
$parentTable = $this->parent->getTable();
$this->setJoin();
if (static::$constraints)
{
$this->query->where($parentTable.'.'.$this->firstKey, '=', $this->farParent->getKey());
}
}
/**
* Add the constraints for a relationship count query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationCountQuery(Builder $query)
{
$this->setJoin($query);
return parent::getRelationCountQuery($query);
}
/**
* Set the join clause on the query.
*
* @param string $parentTable
* @param \Illuminate\Databaes\Eloquent\Builder|null $query
* @return void
*/
protected function setJoin($parentTable)
protected function setJoin(Builder $query = null)
{
$query = $query ?: $this->query;
$foreignKey = $this->related->getTable().'.'.$this->secondKey;
$this->query->join($parentTable, $this->getQualifiedParentKey(), '=', $foreignKey);
$query->join($this->parent->getTable(), $this->getQualifiedParentKeyName(), '=', $foreignKey);
}
/**
@@ -196,9 +213,19 @@ protected function getSelectColumns(array $columns = array('*'))
*
* @return string
*/
protected function getQualifiedParentKey()
protected function getQualifiedParentKeyName()
{
return $this->parent->getQualifiedKeyName();
}
/**
* Get the key for comparing against the pareny key in "has" query.
*
* @return string
*/
public function getHasCompareKey()
{
return $this->farParent->getQualifiedKeyName();
}
}
@@ -239,6 +239,16 @@ public function update(array $attributes)
return $this->query->update($attributes);
}
/**
* Get the key for comparing against the pareny key in "has" query.
*
* @return string
*/
public function getHasCompareKey()
{
return $this->getForeignKey();
}
/**
* Get the foreign key for the relationship.
*
@@ -271,4 +281,14 @@ protected function getParentKey()
return $this->parent->getAttribute($this->localKey);
}
/**
* Get the fully qualified parent key naem.
*
* @return string
*/
protected function getQualifiedParentKeyName()
{
return $this->parent->getTable().'.'.$this->localKey;
}
}
@@ -136,9 +136,9 @@ public function getRelationCountQuery(Builder $query)
{
$query->select(new Expression('count(*)'));
$key = $this->wrap($this->parent->getQualifiedKeyName());
$key = $this->wrap($this->getQualifiedParentKeyName());
return $query->where($this->getForeignKey(), '=', new Expression($key));
return $query->where($this->getHasCompareKey(), '=', new Expression($key));
}
/**
@@ -206,6 +206,16 @@ public function getParent()
return $this->parent;
}
/**
* Get the fully qualified parent key naem.
*
* @return string
*/
protected function getQualifiedParentKeyName()
{
return $this->parent->getQualifiedKeyName();
}
/**
* Get the related model of the relation.
*
@@ -1591,7 +1591,7 @@ public function newQuery()
*/
public function mergeWheres($wheres, $bindings)
{
$this->wheres = array_merge($this->wheres, (array) $wheres);
$this->wheres = array_merge((array) $this->wheres, (array) $wheres);
$this->bindings = array_values(array_merge($this->bindings, (array) $bindings));
}
@@ -100,11 +100,11 @@ public function testRelationCountQueryCanBeBuilt()
$relation = $this->getRelation();
$query = m::mock('Illuminate\Database\Eloquent\Builder');
$query->shouldReceive('select')->once()->with(m::type('Illuminate\Database\Query\Expression'));
$relation->getParent()->shouldReceive('getQualifiedKeyName')->andReturn('foo');
$relation->getParent()->shouldReceive('getTable')->andReturn('table');
$query->shouldReceive('where')->once()->with('table.foreign_key', '=', m::type('Illuminate\Database\Query\Expression'));
$relation->getParent()->shouldReceive('getQuery')->andReturn($parentQuery = m::mock('StdClass'));
$parentQuery->shouldReceive('getGrammar')->once()->andReturn($grammar = m::mock('StdClass'));
$grammar->shouldReceive('wrap')->once()->with('foo');
$grammar->shouldReceive('wrap')->once()->with('table.id');
$relation->getRelationCountQuery($query);
}

0 comments on commit 7196279

Please sign in to comment.