/** * @param $joinTableAlias * @param $currentTableAlias * @param BelongsTo|Relation $relation * @param string $columnsPrefix */ protected function addJoinToQuery($joinTableAlias, $currentTableAlias, Relation $relation, $columnsPrefix = '') { $joinTableName = $relation->getRelated()->getTable(); $joinTable = implode(' as ', [$joinTableName, $joinTableAlias]); $joinLeftCondition = implode('.', [$joinTableAlias, $relation->getOtherKey()]); $joinRightCondition = implode('.', [$currentTableAlias, $relation->getForeignKey()]); $this->query->leftJoin($joinTable, $joinLeftCondition, '=', $joinRightCondition); $columns = $this->getColumns($joinTableName); $prefix = static::$prefix . $columnsPrefix . $joinTableAlias . '---'; foreach ($columns as $column) { $this->selectFromQuery($joinTableAlias, $column, $prefix . $column); } }
/** * Parse the fixture data for belongsToManyRecord. * The current syntax allows for pivot data to be provided * via a pipe delimiter with colon separated key values. * <code> * 'Travis' => [ * 'first_name' => 'Travis', * 'last_name' => 'Bennett', * 'roles' => 'endUser|foo:bar, root' * ] * </code> * * @param string $recordName The name of the relation the fixture is defined on (e.g Travis). * @param Relation $relation The relationship oject (should be of type belongsToMany). * @param string $relatedRecord The related record data (e.g endUser|foo:bar or root). * @return array */ protected function buildBelongsToManyRecord($recordName, Relation $relation, $relatedRecord) { $pivotColumns = explode('|', $relatedRecord); $relatedRecordName = array_shift($pivotColumns); $foreignKeyPieces = explode('.', $relation->getForeignKey()); $foreignKeyName = $foreignKeyPieces[1]; $foreignKeyValue = $this->generateKey($recordName); $otherKeyPieces = explode('.', $relation->getOtherKey()); $otherKeyName = $otherKeyPieces[1]; $otherKeyValue = $this->generateKey($relatedRecordName); $fields = "{$foreignKeyName}, {$otherKeyName}"; $values = array($foreignKeyValue, $otherKeyValue); foreach ($pivotColumns as $pivotColumn) { list($columnName, $columnValue) = explode(':', $pivotColumn); $fields .= ", {$columnName}"; $values[] = $columnValue; } return array($fields, $values); }
/** * 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()]; } }
/** * 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())))]); }