Skip to content

Commit

Permalink
fix eager loading retroactively laravel/framework#51825
Browse files Browse the repository at this point in the history
  • Loading branch information
Marius committed Nov 21, 2024
1 parent 1d3a509 commit e1a6899
Show file tree
Hide file tree
Showing 4 changed files with 456 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/Eloquent/CustomRelations/Builders/CleverEloquentBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace MacropaySolutions\LaravelCrudWizard\Eloquent\CustomRelations\Builders;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\RelationNotFoundException;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use MacropaySolutions\LaravelCrudWizard\Eloquent\CustomRelations\RelationCleverTrait;
use MacropaySolutions\LaravelCrudWizard\Models\BaseModel;

class CleverEloquentBuilder extends Builder
{
/**
* @inheritDoc
*/
public function getRelation($name): Relation
{
$relation = RelationCleverTrait::noConstraints(function () use ($name): Relation {
try {
$model = $this->getModel()->newInstance();
/** @var BaseModel $model */
$model->nowEagerLoadingRelationNameWithNoConstraints = $name;

return $model->$name();
} catch (\BadMethodCallException $e) {
throw RelationNotFoundException::make($this->getModel(), $name);
}
}, $name);

$nested = $this->relationsNestedUnder($name);

if (count($nested) > 0) {
$relation->getQuery()->with($nested);
}

return $relation;
}

/**
* @inheritDoc
*/
protected function getRelationWithoutConstraints($relation): Relation
{
return RelationCleverTrait::noConstraints(function () use ($relation): Relation {
$model = $this->getModel();
/** @var BaseModel $model */
$model->nowEagerLoadingRelationNameWithNoConstraints = $relation;

return $model->{$relation}();
}, $relation);
}

/**
* @inheritDoc
*/
protected function getBelongsToRelation(MorphTo $relation, $type): BelongsTo
{
/** this will work as before, the static property from Relation is overwritten in RelationCleverTrait */
$belongsTo = RelationCleverTrait::noConstraints(function () use ($relation, $type): Relation {
return $this->model->belongsTo(
$type,
$relation->getForeignKeyName(),
$relation->getOwnerKeyName()
);
});

$belongsTo->getQuery()->mergeConstraintsFrom($relation->getQuery());

return $belongsTo;
}
}
300 changes: 300 additions & 0 deletions src/Eloquent/CustomRelations/HasCleverRelationships.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
<?php

namespace MacropaySolutions\LaravelCrudWizard\Eloquent\CustomRelations;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Concerns\HasRelationships;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use MacropaySolutions\LaravelCrudWizard\Models\BaseModel as Model;

/**
* @see HasRelationships
* Fix for this issue https://github.com/laravel/framework/issues/51825
*/
trait HasCleverRelationships
{
public ?string $nowEagerLoadingRelationNameWithNoConstraints = null;

protected function newHasOne(Builder $query, Model $parent, string $foreignKey, string $localKey): HasOne
{
return new class($query, $parent, $foreignKey, $localKey) extends HasOne {
use RelationCleverTrait;

public function __construct(Builder $query, Model $parent, string $foreignKey, string $localKey)
{
$this->setConstraintsStaticFlag($parent);

return parent::__construct($query, $parent, $foreignKey, $localKey);
}
};
}

protected function newHasOneThrough(
Builder $query,
Model $farParent,
Model $throughParent,
string $firstKey,
string $secondKey,
string $localKey,
string $secondLocalKey
): HasOneThrough {
return new class(
$query,
$farParent,
$throughParent,
$firstKey,
$secondKey,
$localKey,
$secondLocalKey
) extends HasOneThrough {
use RelationCleverTrait;

public function __construct(
Builder $query,
Model $farParent,
Model $throughParent,
string $firstKey,
string $secondKey,
string $localKey,
string $secondLocalKey
) {
$this->setConstraintsStaticFlag($throughParent);

return parent::__construct(
$query,
$farParent,
$throughParent,
$firstKey,
$secondKey,
$localKey,
$secondLocalKey
);
}
};
}

protected function newMorphOne(Builder $query, Model $parent, string $type, string $id, string $localKey): MorphOne
{
return new class($query, $parent, $type, $id, $localKey) extends MorphOne {
use RelationCleverTrait;

public function __construct(Builder $query, Model $parent, string $type, string $id, string $localKey)
{
$this->setConstraintsStaticFlag($parent);

return parent::__construct($query, $parent, $type, $id, $localKey);
}
};
}

protected function newBelongsTo(
Builder $query,
Model $child,
string $foreignKey,
string $ownerKey,
string $relation
): BelongsTo {
return new class($query, $child, $foreignKey, $ownerKey, $relation) extends BelongsTo {
use RelationCleverTrait;

public function __construct(
Builder $query,
Model $child,
string $foreignKey,
string $ownerKey,
string $relation
) {
$this->setConstraintsStaticFlag($child);

return parent::__construct($query, $child, $foreignKey, $ownerKey, $relation);
}
};
}

protected function newMorphTo(
Builder $query,
Model $parent,
string $foreignKey,
string $ownerKey,
string $type,
string $relation
): MorphTo {
return new class($query, $parent, $foreignKey, $ownerKey, $type, $relation) extends MorphTo {
use RelationCleverTrait;

public function __construct(
Builder $query,
Model $parent,
string $foreignKey,
string $ownerKey,
string $type,
string $relation
) {
$this->setConstraintsStaticFlag($parent);

return parent::__construct($query, $parent, $foreignKey, $ownerKey, $type, $relation);
}
};
}

protected function newHasMany(Builder $query, Model $parent, string $foreignKey, string $localKey): HasMany
{
return new class($query, $parent, $foreignKey, $localKey) extends HasMany {
use RelationCleverTrait;

public function __construct(Builder $query, Model $parent, string $foreignKey, string $localKey)
{
$this->setConstraintsStaticFlag($parent);

return parent::__construct($query, $parent, $foreignKey, $localKey);
}
};
}

protected function newHasManyThrough(
Builder $query,
Model $farParent,
Model $throughParent,
string $firstKey,
string $secondKey,
string $localKey,
string $secondLocalKey
): HasManyThrough {
return new class($query, $farParent, $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey) extends
HasManyThrough {
use RelationCleverTrait;

public function __construct(
Builder $query,
Model $farParent,
Model $throughParent,
string $firstKey,
string $secondKey,
string $localKey,
string $secondLocalKey
) {
$this->setConstraintsStaticFlag($throughParent);

return parent::__construct(
$query,
$farParent,
$throughParent,
$firstKey,
$secondKey,
$localKey,
$secondLocalKey
);
}
};
}

protected function newMorphMany(Builder $query, Model $parent, $type, $id, $localKey): MorphMany
{
return new class($query, $parent, $type, $id, $localKey) extends MorphMany {
use RelationCleverTrait;

public function __construct(Builder $query, Model $parent, string $type, string $id, string $localKey)
{
$this->setConstraintsStaticFlag($parent);

return parent::__construct($query, $parent, $type, $id, $localKey);
}
};
}

protected function newBelongsToMany(
Builder $query,
Model $parent,
string $table,
string $foreignPivotKey,
string $relatedPivotKey,
string $parentKey,
string $relatedKey,
?string $relationName = null
): BelongsToMany {
return new class($query, $parent, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey, $relationName) extends
BelongsToMany {
use RelationCleverTrait;

public function __construct(
Builder $query,
Model $parent,
string $table,
string $foreignPivotKey,
string $relatedPivotKey,
string $parentKey,
string $relatedKey,
?string $relationName = null
) {
$this->setConstraintsStaticFlag($parent);

return parent::__construct(
$query,
$parent,
$table,
$foreignPivotKey,
$relatedPivotKey,
$parentKey,
$relatedKey,
$relationName
);
}
};
}

protected function newMorphToMany(
Builder $query,
Model $parent,
string $name,
string $table,
string $foreignPivotKey,
string $relatedPivotKey,
string $parentKey,
string $relatedKey,
?string $relationName = null,
bool $inverse = false
): MorphToMany {
return new class($query, $parent, $name, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey,
$relationName, $inverse
) extends MorphToMany {
use RelationCleverTrait;

public function __construct(
Builder $query,
Model $parent,
string $name,
string $table,
string $foreignPivotKey,
string $relatedPivotKey,
string $parentKey,
string $relatedKey,
?string $relationName,
bool $inverse
) {
$this->setConstraintsStaticFlag($parent);

return parent::__construct(
$query,
$parent,
$name,
$table,
$foreignPivotKey,
$relatedPivotKey,
$parentKey,
$relatedKey,
$relationName,
$inverse
);
}
};
}
}
Loading

0 comments on commit e1a6899

Please sign in to comment.