diff --git a/src/Eloquent/CustomRelations/Builders/CleverEloquentBuilder.php b/src/Eloquent/CustomRelations/Builders/CleverEloquentBuilder.php new file mode 100644 index 0000000..f5d69a4 --- /dev/null +++ b/src/Eloquent/CustomRelations/Builders/CleverEloquentBuilder.php @@ -0,0 +1,73 @@ +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; + } +} \ No newline at end of file diff --git a/src/Eloquent/CustomRelations/HasCleverRelationships.php b/src/Eloquent/CustomRelations/HasCleverRelationships.php new file mode 100644 index 0000000..59b0b05 --- /dev/null +++ b/src/Eloquent/CustomRelations/HasCleverRelationships.php @@ -0,0 +1,300 @@ +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 + ); + } + }; + } +} diff --git a/src/Eloquent/CustomRelations/RelationCleverTrait.php b/src/Eloquent/CustomRelations/RelationCleverTrait.php new file mode 100644 index 0000000..48b1e1c --- /dev/null +++ b/src/Eloquent/CustomRelations/RelationCleverTrait.php @@ -0,0 +1,71 @@ +nowEagerLoadingRelationNameWithNoConstraints + ) { + return; + } + + /** + * 1st execution is for ExampleModel $exampleModel on 'rel' relation + * with nowEagerLoadingRelationNameWithNoConstraints = 'rel' + * and with $noConstraintsForRelationName = 'rel' + */ + /* 2nd execution is for UserModel $userModel on 'categories' relation + with nowEagerLoadingRelationNameWithNoConstraints = null + and with $noConstraintsForRelationName = 'rel' */ + + + /* 1st execution is for ExampleModel $exampleModel on 'children' relation + with nowEagerLoadingRelationNameWithNoConstraints = null + and with $noConstraintsForRelationName = 'rel' */ + /** + * 2nd execution is for ExampleModel $exampleModel on 'rel' relation + * with nowEagerLoadingRelationNameWithNoConstraints = 'rel' + * and with $noConstraintsForRelationName = 'rel' + */ + /* 3rd execution is for UserModel $userModel on 'categories' relation + with nowEagerLoadingRelationNameWithNoConstraints = null + and with $noConstraintsForRelationName = 'rel' */ + static::$constraints = + static::$noConstraintsForRelationName !== $model->nowEagerLoadingRelationNameWithNoConstraints; + } +} \ No newline at end of file diff --git a/src/Models/BaseModel.php b/src/Models/BaseModel.php index 3360478..8fe52b1 100644 --- a/src/Models/BaseModel.php +++ b/src/Models/BaseModel.php @@ -8,6 +8,8 @@ use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; +use MacropaySolutions\LaravelCrudWizard\Eloquent\CustomRelations\Builders\CleverEloquentBuilder; +use MacropaySolutions\LaravelCrudWizard\Eloquent\CustomRelations\HasCleverRelationships; use MacropaySolutions\LaravelCrudWizard\Helpers\GeneralHelper; use MacropaySolutions\LaravelCrudWizard\Models\Attributes\BaseModelAttributes; @@ -16,6 +18,8 @@ */ abstract class BaseModel extends Model { + use HasCleverRelationships; + public const RESOURCE_NAME = null; public const WITH_RELATIONS = []; public const CREATED_AT_FORMAT = 'Y-m-d H:i:s'; @@ -50,6 +54,14 @@ public function __construct(array $attributes = []) $this->append('primary_key_identifier'); } + /** + * @inheritDoc + */ + public function newEloquentBuilder($query): CleverEloquentBuilder + { + return new CleverEloquentBuilder($query); + } + public function getColumns(bool $includingPrimary = true): array { $columns = $includingPrimary ?