/** * Get pair of the keys from relation in order to join the table. * * @param \Illuminate\Database\Eloquent\Relations\Relation $relation * @return array * * @throws \LogicException */ protected function getJoinKeys(Relation $relation) { if ($relation instanceof MorphTo) { throw new LogicException("MorphTo relation cannot be joined."); } if ($relation instanceof HasOneOrMany) { return [$relation->getForeignKey(), $relation->getQualifiedParentKeyName()]; } if ($relation instanceof BelongsTo) { return [$relation->getQualifiedForeignKey(), $relation->getQualifiedOtherKeyName()]; } if ($relation instanceof BelongsToMany) { return [$relation->getOtherKey(), $relation->getRelated()->getQualifiedKeyName()]; } if ($relation instanceof HasManyThrough) { $fk = $relation->getRelated()->getTable() . '.' . $relation->getParent()->getForeignKey(); return [$fk, $relation->getParent()->getQualifiedKeyName()]; } }
/** * Get the keys from relation in order to join the table. * * @param \Illuminate\Database\Eloquent\Relations\Relation $relation * @return array * * @throws \LogicException */ protected function getJoinKeys(Relation $relation) { if ($relation instanceof HasOne || $relation instanceof MorphOne) { return [$relation->getForeignKey(), $relation->getQualifiedParentKeyName()]; } if ($relation instanceof BelongsTo && !$relation instanceof MorphTo) { return [$relation->getQualifiedForeignKey(), $relation->getQualifiedOtherKeyName()]; } $class = get_class($relation); throw new LogicException("Only HasOne, MorphOne and BelongsTo mappings can be queried. {$class} given."); }
/** * Update counter cache column. * * @author Morten Rugaard <*****@*****.**> * * @param \Illuminate\Database\Eloquent\Model $model * @param \Illuminate\Database\Eloquent\Relations\Relation $relation * @param array|null $counterCacheConditions * @param string $foreignKey * @param string $counterCacheColumnName * @return bool */ protected function updateCount(IlluminateModel $model, IlluminateRelation $relation, $counterCacheConditions, $foreignKey, $counterCacheColumnName) { // Retrieve table name of relation $relationTableName = $relation->getModel()->getTable(); // Generate query builder for counting entries // on our model. Result will be used as value when // we're updating the counter cache column on the relation $countQuery = $model->newQuery()->select(DB::raw(sprintf('COUNT(%s.id)', $model->getTable())))->join(DB::raw(sprintf('(SELECT %s.%s FROM %s) as relation', $relationTableName, $relation->getOtherKey(), $relationTableName)), $relation->getQualifiedForeignKey(), '=', sprintf('relation.%s', $relation->getOtherKey()))->where($relation->getQualifiedForeignKey(), '=', $this->prepareValue($foreignKey)); // If our relation has additional conditions, we'll need // to add them to our query builder that counts the entries if (is_array($counterCacheConditions)) { foreach ($counterCacheConditions as $conditionType => $conditionParameters) { foreach ($conditionParameters as $parameters) { call_user_func_array([$countQuery, $conditionType], $parameters); } } } // Retrieve countQuery SQL // and prepare for binding replacements $countQuerySql = str_replace(['%', '?'], ['%%', '%s'], $countQuery->toSql()); // Fire the update query // to update counter cache column return (bool) $relation->getBaseQuery()->update([sprintf('%s.%s', $relationTableName, $counterCacheColumnName) => DB::raw(sprintf('(%s)', vsprintf($countQuerySql, $countQuery->getBindings())))]); }