暂存
This commit is contained in:
+157
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\RelationNotFoundException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait SupportsInverseRelations
|
||||
{
|
||||
/**
|
||||
* The name of the inverse relationship.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected ?string $inverseRelationship = null;
|
||||
|
||||
/**
|
||||
* Instruct Eloquent to link the related models back to the parent after the relationship query has run.
|
||||
*
|
||||
* Alias of "chaperone".
|
||||
*
|
||||
* @param string|null $relation
|
||||
* @return $this
|
||||
*/
|
||||
public function inverse(?string $relation = null)
|
||||
{
|
||||
return $this->chaperone($relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instruct Eloquent to link the related models back to the parent after the relationship query has run.
|
||||
*
|
||||
* @param string|null $relation
|
||||
* @return $this
|
||||
*/
|
||||
public function chaperone(?string $relation = null)
|
||||
{
|
||||
$relation ??= $this->guessInverseRelation();
|
||||
|
||||
if (! $relation || ! $this->getModel()->isRelation($relation)) {
|
||||
throw RelationNotFoundException::make($this->getModel(), $relation ?: 'null');
|
||||
}
|
||||
|
||||
if ($this->inverseRelationship === null && $relation) {
|
||||
$this->query->afterQuery(function ($result) {
|
||||
return $this->inverseRelationship
|
||||
? $this->applyInverseRelationToCollection($result, $this->getParent())
|
||||
: $result;
|
||||
});
|
||||
}
|
||||
|
||||
$this->inverseRelationship = $relation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the name of the inverse relationship.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function guessInverseRelation(): ?string
|
||||
{
|
||||
return Arr::first(
|
||||
$this->getPossibleInverseRelations(),
|
||||
fn ($relation) => $relation && $this->getModel()->isRelation($relation)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the possible inverse relations for the parent model.
|
||||
*
|
||||
* @return array<non-empty-string>
|
||||
*/
|
||||
protected function getPossibleInverseRelations(): array
|
||||
{
|
||||
return array_filter(array_unique([
|
||||
Str::camel(Str::beforeLast($this->getForeignKeyName(), $this->getParent()->getKeyName())),
|
||||
Str::camel(Str::beforeLast($this->getParent()->getForeignKey(), $this->getParent()->getKeyName())),
|
||||
Str::camel(class_basename($this->getParent())),
|
||||
'owner',
|
||||
get_class($this->getParent()) === get_class($this->getModel()) ? 'parent' : null,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the inverse relation on all models in a collection.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $models
|
||||
* @param \Illuminate\Database\Eloquent\Model|null $parent
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
protected function applyInverseRelationToCollection($models, ?Model $parent = null)
|
||||
{
|
||||
$parent ??= $this->getParent();
|
||||
|
||||
foreach ($models as $model) {
|
||||
$model instanceof Model && $this->applyInverseRelationToModel($model, $parent);
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the inverse relation on a model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param \Illuminate\Database\Eloquent\Model|null $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected function applyInverseRelationToModel(Model $model, ?Model $parent = null)
|
||||
{
|
||||
if ($inverse = $this->getInverseRelationship()) {
|
||||
$parent ??= $this->getParent();
|
||||
|
||||
$model->setRelation($inverse, $parent);
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the inverse relationship.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getInverseRelationship()
|
||||
{
|
||||
return $this->inverseRelationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the chaperone / inverse relationship for this query.
|
||||
*
|
||||
* Alias of "withoutChaperone".
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutInverse()
|
||||
{
|
||||
return $this->withoutChaperone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the chaperone / inverse relationship for this query.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutChaperone()
|
||||
{
|
||||
$this->inverseRelationship = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user