MorphOne.php
TLDR
This file is a part of the Illuminate\Database\Eloquent\Relations namespace and contains the MorphOne
class. This class is used for defining a one-to-one polymorphic relationship in Eloquent. It extends the MorphOneOrMany
class and implements the SupportsPartialRelations
interface. The MorphOne
class has several methods that define the behavior of the relationship.
Methods
getResults
This method retrieves the results of the relationship. If the parent key is null, it returns the default value for the parent. Otherwise, it retrieves the first result from the query or returns the default value for the parent.
initRelation
This method initializes the relationship on a set of models. It sets the relation on each model to the default value for that model.
match
This method matches the eagerly loaded results to their parents. It calls the matchOne
method from the MorphOneOrMany
class.
getRelationExistenceQuery
This method retrieves the relationship query. If the relationship is a one-of-many relationship, it merges the necessary join clauses into the query. It then calls the getRelationExistenceQuery
method of the parent class.
addOneOfManySubQueryConstraints
This method adds constraints for inner join subselect for one of many relationships. It adds the foreign key and morph type columns to the select statement of the query.
getOneOfManySubQuerySelectColumns
This method retrieves the columns that should be selected by the one of many subquery. It returns an array containing the foreign key and morph type columns.
addOneOfManyJoinSubQueryConstraints
This method adds join query constraints for one of many relationships. It joins the subselect column for the morph type and foreign key with the related columns.
newRelatedInstanceFor
This method creates a new related instance for the given model. It creates a new instance of the related model and sets the foreign key and morph type attributes.
getRelatedKeyFrom
This method retrieves the value of the model's foreign key. It retrieves the attribute value for the foreign key name.
<?php
namespace Illuminate\Database\Eloquent\Relations;
use Illuminate\Contracts\Database\Eloquent\SupportsPartialRelations;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Concerns\CanBeOneOfMany;
use Illuminate\Database\Eloquent\Relations\Concerns\ComparesRelatedModels;
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
use Illuminate\Database\Query\JoinClause;
class MorphOne extends MorphOneOrMany implements SupportsPartialRelations
{
use CanBeOneOfMany, ComparesRelatedModels, SupportsDefaultModels;
/**
* Get the results of the relationship.
*
* @return mixed
*/
public function getResults()
{
if (is_null($this->getParentKey())) {
return $this->getDefaultFor($this->parent);
}
return $this->query->first() ?: $this->getDefaultFor($this->parent);
}
/**
* Initialize the relation on a set of models.
*
* @param array $models
* @param string $relation
* @return array
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, $this->getDefaultFor($model));
}
return $models;
}
/**
* Match the eagerly loaded results to their parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, Collection $results, $relation)
{
return $this->matchOne($models, $results, $relation);
}
/**
* Get the relationship query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
* @param array|mixed $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
{
if ($this->isOneOfMany()) {
$this->mergeOneOfManyJoinsTo($query);
}
return parent::getRelationExistenceQuery($query, $parentQuery, $columns);
}
/**
* Add constraints for inner join subselect for one of many relationships.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string|null $column
* @param string|null $aggregate
* @return void
*/
public function addOneOfManySubQueryConstraints(Builder $query, $column = null, $aggregate = null)
{
$query->addSelect($this->foreignKey, $this->morphType);
}
/**
* Get the columns that should be selected by the one of many subquery.
*
* @return array|string
*/
public function getOneOfManySubQuerySelectColumns()
{
return [$this->foreignKey, $this->morphType];
}
/**
* Add join query constraints for one of many relationships.
*
* @param \Illuminate\Database\Query\JoinClause $join
* @return void
*/
public function addOneOfManyJoinSubQueryConstraints(JoinClause $join)
{
$join
->on($this->qualifySubSelectColumn($this->morphType), '=', $this->qualifyRelatedColumn($this->morphType))
->on($this->qualifySubSelectColumn($this->foreignKey), '=', $this->qualifyRelatedColumn($this->foreignKey));
}
/**
* Make a new related instance for the given model.
*
* @param \Illuminate\Database\Eloquent\Model $parent
* @return \Illuminate\Database\Eloquent\Model
*/
public function newRelatedInstanceFor(Model $parent)
{
return $this->related->newInstance()
->setAttribute($this->getForeignKeyName(), $parent->{$this->localKey})
->setAttribute($this->getMorphType(), $this->morphClass);
}
/**
* Get the value of the model's foreign key.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return mixed
*/
protected function getRelatedKeyFrom(Model $model)
{
return $model->getAttribute($this->getForeignKeyName());
}
}