From b3c1e341a1aad2e6772d782f49750b7af8ccc001 Mon Sep 17 00:00:00 2001 From: Eduard Lupacescu Date: Mon, 26 May 2025 20:35:25 +0300 Subject: [PATCH 1/2] fix: adding relationship support within the fields method --- docs-v2/content/en/api/relations.md | 41 ++++++++++++++++++++++- src/Repositories/Repository.php | 8 ++++- src/Traits/InteractWithSearch.php | 18 ++++++++++- src/helpers.php | 50 +++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/docs-v2/content/en/api/relations.md b/docs-v2/content/en/api/relations.md index 050e498d..c644a623 100644 --- a/docs-v2/content/en/api/relations.md +++ b/docs-v2/content/en/api/relations.md @@ -13,7 +13,46 @@ Restify handles all relationships and gives you an expressive way to list resour ## Definition -The list of relationships should be defined into a repository method called `related`: +### Option 1: Using the `fields` method (Recommended) + +You can define relationships directly within your `fields` method alongside regular fields. Restify will automatically detect eager fields and handle them as relationships: + +```php +public function fields(RestifyRequest $request): array +{ + return [ + field('id')->readonly(), + field('name')->storingRules('required'), + field('email')->storingRules('required', 'unique:users'), + + // Relationships - automatically detected and handled + belongsToMany('roles', RoleRepository::class), + hasMany('posts', PostRepository::class), + belongsTo('company', CompanyRepository::class), + + field('created_at')->readonly(), + ]; +} +``` + +Using the helper functions: + +```php +belongsTo('relationship', RepositoryClass::class) +belongsToMany('relationship', RepositoryClass::class) +hasOne('relationship', RepositoryClass::class) +hasMany('relationship', RepositoryClass::class) +morphTo('relationship') +morphOne('relationship', RepositoryClass::class) +morphMany('relationship', RepositoryClass::class) +morphToMany('relationship', RepositoryClass::class) +morphedByMany('relationship', RepositoryClass::class) +``` + + +### Option 2: Using the `related` method + +Alternatively, you can define relationships using the traditional `related` method: ```php public static function related(): array diff --git a/src/Repositories/Repository.php b/src/Repositories/Repository.php index dcec17bb..1a4ca767 100644 --- a/src/Repositories/Repository.php +++ b/src/Repositories/Repository.php @@ -248,8 +248,14 @@ public function collectFields(RestifyRequest $request): FieldCollection $method = 'fieldsForUpdateBulk'; } + $allFields = $this->filter($this->{$method}($request)); + + $regularFields = array_filter($allFields, function($field) { + return !($field instanceof EagerField); + }); + return FieldCollection::make( - array_values($this->filter($this->{$method}($request))) + array_values($regularFields) )->merge( $this->extraFields($request) )->setRepository($this); diff --git a/src/Traits/InteractWithSearch.php b/src/Traits/InteractWithSearch.php index dd5ab2f8..62840c31 100644 --- a/src/Traits/InteractWithSearch.php +++ b/src/Traits/InteractWithSearch.php @@ -3,6 +3,7 @@ namespace Binaryk\LaravelRestify\Traits; use Binaryk\LaravelRestify\Eager\RelatedCollection; +use Binaryk\LaravelRestify\Fields\EagerField; use Binaryk\LaravelRestify\Filters\AdvancedFiltersCollection; use Binaryk\LaravelRestify\Filters\Filter; use Binaryk\LaravelRestify\Filters\MatchesCollection; @@ -46,7 +47,22 @@ public static function include(): array public static function collectRelated(): RelatedCollection { - return RelatedCollection::make(static::include()); + $related = static::include(); + + if (empty($related)) { + $instance = new static(); + $request = app(RestifyRequest::class); + $fields = $instance->fields($request); + + $eagerFields = collect($fields) + ->filter(fn($field) => $field instanceof EagerField) + ->mapWithKeys(fn($field) => [$field->attribute => $field]) + ->toArray(); + + $related = $eagerFields; + } + + return RelatedCollection::make($related); } public static function matches(): array diff --git a/src/helpers.php b/src/helpers.php index f6e7298f..614fd170 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -73,3 +73,53 @@ function currentRepository(): Repository return app(RepositoryInstance::class)->current(); } } + + +if (! function_exists('belongsTo')) { + function belongsTo(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\BelongsTo + { + return Binaryk\LaravelRestify\Fields\BelongsTo::make($attribute, $repository); + } +} + +if (! function_exists('belongsToMany')) { + function belongsToMany(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\BelongsToMany + { + return Binaryk\LaravelRestify\Fields\BelongsToMany::make($attribute, $repository); + } +} + +if (! function_exists('hasOne')) { + function hasOne(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\HasOne + { + return Binaryk\LaravelRestify\Fields\HasOne::make($attribute, $repository); + } +} + +if (! function_exists('hasMany')) { + function hasMany(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\HasMany + { + return Binaryk\LaravelRestify\Fields\HasMany::make($attribute, $repository); + } +} + +if (! function_exists('morphOne')) { + function morphOne(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\MorphOne + { + return Binaryk\LaravelRestify\Fields\MorphOne::make($attribute, $repository); + } +} + +if (! function_exists('morphMany')) { + function morphMany(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\MorphMany + { + return Binaryk\LaravelRestify\Fields\MorphMany::make($attribute, $repository); + } +} + +if (! function_exists('morphToMany')) { + function morphToMany(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\MorphToMany + { + return Binaryk\LaravelRestify\Fields\MorphToMany::make($attribute, $repository); + } +} From 49ea36296323a31ce747db209ea6129def1ab52d Mon Sep 17 00:00:00 2001 From: binaryk Date: Mon, 26 May 2025 17:35:48 +0000 Subject: [PATCH 2/2] Fix styling --- src/Exceptions/Solutions/OpenAiSolution.php | 17 ++++++++--------- src/Repositories/Repository.php | 4 ++-- src/Traits/InteractWithSearch.php | 6 +++--- src/helpers.php | 1 - 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Exceptions/Solutions/OpenAiSolution.php b/src/Exceptions/Solutions/OpenAiSolution.php index 0b913c72..24af2986 100644 --- a/src/Exceptions/Solutions/OpenAiSolution.php +++ b/src/Exceptions/Solutions/OpenAiSolution.php @@ -18,17 +18,16 @@ public function __construct(protected Throwable $throwable) now()->addHour(), fn () => OpenAI::chat()->create([ 'model' => config('restify.ai_solutions.model', 'gpt-4.1-mini'), - 'messages' => + 'messages' => [ [ - [ - 'role' => 'user', - 'content' => $this->generatePrompt($this->throwable), - ], - [ - 'role' => 'system', - 'content' => 'Provide a concise solution to the problem described, tailored for a Laravel application using the Restify framework. Avoid explanations, examples, or code snippets. Respond with only the direct answer.', - ], + 'role' => 'user', + 'content' => $this->generatePrompt($this->throwable), ], + [ + 'role' => 'system', + 'content' => 'Provide a concise solution to the problem described, tailored for a Laravel application using the Restify framework. Avoid explanations, examples, or code snippets. Respond with only the direct answer.', + ], + ], 'max_tokens' => config('restify.ai_solutions.max_tokens', 1000), 'temperature' => 0, ])->choices[0]->message->content diff --git a/src/Repositories/Repository.php b/src/Repositories/Repository.php index 1a4ca767..d01b0a37 100644 --- a/src/Repositories/Repository.php +++ b/src/Repositories/Repository.php @@ -250,8 +250,8 @@ public function collectFields(RestifyRequest $request): FieldCollection $allFields = $this->filter($this->{$method}($request)); - $regularFields = array_filter($allFields, function($field) { - return !($field instanceof EagerField); + $regularFields = array_filter($allFields, function ($field) { + return ! ($field instanceof EagerField); }); return FieldCollection::make( diff --git a/src/Traits/InteractWithSearch.php b/src/Traits/InteractWithSearch.php index 62840c31..a4eca859 100644 --- a/src/Traits/InteractWithSearch.php +++ b/src/Traits/InteractWithSearch.php @@ -50,13 +50,13 @@ public static function collectRelated(): RelatedCollection $related = static::include(); if (empty($related)) { - $instance = new static(); + $instance = new static; $request = app(RestifyRequest::class); $fields = $instance->fields($request); $eagerFields = collect($fields) - ->filter(fn($field) => $field instanceof EagerField) - ->mapWithKeys(fn($field) => [$field->attribute => $field]) + ->filter(fn ($field) => $field instanceof EagerField) + ->mapWithKeys(fn ($field) => [$field->attribute => $field]) ->toArray(); $related = $eagerFields; diff --git a/src/helpers.php b/src/helpers.php index 614fd170..515ebb1e 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -74,7 +74,6 @@ function currentRepository(): Repository } } - if (! function_exists('belongsTo')) { function belongsTo(string $attribute, string $repository): Binaryk\LaravelRestify\Fields\BelongsTo {