Skip to content

Commit 091a0bd

Browse files
committed
fix: docs
1 parent 93f29c1 commit 091a0bd

17 files changed

+711
-100
lines changed

UPGRADING.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,173 @@
11
# Upgrading
22

3+
## From 9.x to 10.x
4+
5+
### New Features
6+
7+
#### Modern Model Definition with PHP Attributes
8+
9+
Laravel Restify v10 introduces a modern way to define models using PHP 8+ attributes. While your existing static property approach will continue to work, we recommend migrating to the new attribute-based syntax for better developer experience.
10+
11+
**Before (v9 and earlier):**
12+
```php
13+
class UserRepository extends Repository
14+
{
15+
public static string $model = User::class;
16+
17+
public function fields(RestifyRequest $request): array
18+
{
19+
return [
20+
field('name'),
21+
field('email'),
22+
];
23+
}
24+
}
25+
```
26+
27+
**After (v10 - Recommended):**
28+
```php
29+
use Binaryk\LaravelRestify\Attributes\Model;
30+
31+
#[Model(User::class)]
32+
class UserRepository extends Repository
33+
{
34+
public function fields(RestifyRequest $request): array
35+
{
36+
return [
37+
field('name'),
38+
field('email'),
39+
];
40+
}
41+
}
42+
```
43+
44+
**Benefits of migrating to attributes:**
45+
- 🎯 **Modern, declarative approach** - More intuitive and cleaner code
46+
- 🔍 **Better IDE support** - Enhanced autocompletion and static analysis
47+
- 📦 **Type-safe** - Use `::class` syntax for better refactoring support
48+
- 🔧 **More discoverable** - Attributes are easier to find with reflection tools
49+
- 🚀 **Future-proof** - Follows modern PHP practices
50+
51+
**Migration Strategy:**
52+
53+
1. **No immediate action required** - All existing repositories continue to work as-is
54+
2. **Gradual migration** - Update repositories one at a time when convenient
55+
3. **Mixed approach** - You can use both attributes and static properties in the same codebase
56+
57+
**Priority order for model resolution:**
58+
1. `#[Model]` attribute (highest priority)
59+
2. `public static string $model` property
60+
3. Auto-guessing from repository class name (lowest priority)
61+
62+
This change is **100% backward compatible** - no existing code will break.
63+
64+
#### Improved Field-Level Search and Sorting
65+
66+
Laravel Restify v10 introduces a more intuitive way to define searchable and sortable fields directly on the field definitions. While the static array approach continues to work, the new field-level methods provide better organization and discoverability.
67+
68+
**Before (v9 and earlier):**
69+
```php
70+
class UserRepository extends Repository
71+
{
72+
public static array $search = ['name', 'email'];
73+
public static array $sort = ['name', 'email', 'created_at'];
74+
75+
public function fields(RestifyRequest $request): array
76+
{
77+
return [
78+
field('name'),
79+
field('email'),
80+
field('created_at'),
81+
];
82+
}
83+
}
84+
```
85+
86+
**After (v10 - Recommended):**
87+
```php
88+
#[Model(User::class)]
89+
class UserRepository extends Repository
90+
{
91+
public function fields(RestifyRequest $request): array
92+
{
93+
return [
94+
field('name')->searchable()->sortable(),
95+
field('email')->searchable()->sortable(),
96+
field('created_at')->sortable(),
97+
];
98+
}
99+
}
100+
```
101+
102+
**Benefits of field-level configuration:**
103+
- 📍 **Co-located configuration** - Search/sort behavior defined alongside the field
104+
- 🔍 **Better discoverability** - Easy to see which fields are searchable/sortable at a glance
105+
- 🎛️ **More granular control** - Configure search and sort behavior per field
106+
- 🧹 **Cleaner repositories** - Reduces static array properties
107+
- 💡 **IDE-friendly** - Better autocompletion and method chaining
108+
109+
**Migration Strategy:**
110+
111+
1. **Static arrays still work** - No need to change existing repositories immediately
112+
2. **Field-level takes precedence** - If both are defined, field-level configuration wins
113+
3. **Gradual migration** - Update fields one at a time or per repository
114+
4. **Mixed approach** - You can use both approaches in the same codebase during transition
115+
116+
**Priority order for search/sort resolution:**
117+
1. Field-level `->searchable()`/`->sortable()` methods (highest priority)
118+
2. Static `$search`/`$sort` arrays (fallback)
119+
120+
This change is also **100% backward compatible** - existing static arrays continue to work perfectly.
121+
122+
### Configuration File Updates
123+
124+
When upgrading to v10, it's important to ensure your local `config/restify.php` file includes all the new configuration options that have been added.
125+
126+
**Recommended Steps:**
127+
128+
1. **Compare configuration files** - Check your local `config/restify.php` against the latest version
129+
2. **Review new sections** - Look for new configuration options that may have been added
130+
3. **Merge changes** - Add any missing configuration sections to your local file
131+
132+
**New configuration sections in v10 may include:**
133+
134+
```php
135+
// Example new sections (check the actual config file for current options)
136+
'mcp' => [
137+
'tools' => [
138+
'exclude' => [],
139+
'include' => [],
140+
],
141+
'resources' => [
142+
'exclude' => [],
143+
'include' => [],
144+
],
145+
'prompts' => [
146+
'exclude' => [],
147+
'include' => [],
148+
],
149+
],
150+
151+
'ai_solutions' => [
152+
'model' => 'gpt-4.1-mini',
153+
'max_tokens' => 1000,
154+
],
155+
```
156+
157+
**How to update your config:**
158+
159+
1. **Backup your current config** - Copy your existing `config/restify.php`
160+
2. **Republish the config** (optional):
161+
```bash
162+
php artisan vendor:publish --provider="Binaryk\LaravelRestify\LaravelRestifyServiceProvider" --tag="config" --force
163+
```
164+
3. **Merge your custom settings** - Copy your custom values back into the new config file
165+
4. **Test your application** - Ensure all functionality works as expected
166+
167+
<alert type="warning">
168+
Always backup your existing configuration before making changes, especially if you have custom settings.
169+
</alert>
170+
3171
## From 7.3.1 to 7.4.0
4172

5173
## Breaking

docs-v2/content/en/api/repositories.md

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,26 @@ instruct Restify to generate the migrations, policy, and model (in `app/Models`)
2323

2424
## Defining Repositories
2525

26-
The basic repository form looks like this:
26+
The basic repository form looks like this using the modern attribute approach:
27+
28+
```php
29+
namespace App\Restify;
30+
31+
use App\Models\Post;
32+
use App\Restify\Repository;
33+
use Binaryk\LaravelRestify\Attributes\Model;
34+
35+
#[Model(Post::class)]
36+
class PostRepository extends Repository
37+
{
38+
public function fields(RestifyRequest $request): array
39+
{
40+
return [];
41+
}
42+
}
43+
```
44+
45+
Or using the traditional static property approach:
2746

2847
```php
2948
namespace App\Restify;
@@ -35,15 +54,15 @@ class PostRepository extends Repository
3554
{
3655
public static string $model = Post::class;
3756

38-
public function fields(RestifyRequest $request)
57+
public function fields(RestifyRequest $request): array
3958
{
4059
return [];
4160
}
4261
}
4362
```
4463

4564
<alert type="info">
46-
If you don't specify the $model property, Restify will try to guess the model automatically.
65+
If you don't specify the model using an attribute or the $model property, Restify will try to guess the model automatically based on the repository class name.
4766
</alert>
4867

4968

@@ -54,8 +73,12 @@ The `fields` method returns the default set of attributes definitions that shoul
5473
Restify will discover recursively all classes from the `app\Restify\*` directory that extend
5574
the `Binaryk\LaravelRestify\Repositories\Repository` class.
5675

57-
If the `$model` property is not defined, Restify will guess the model class by using the prefix of the Repository name.
58-
For example, `UserPostRepository` class has the model `UserPost`.
76+
For model resolution, Restify follows this priority order:
77+
1. **`#[Model]` attribute** (highest priority)
78+
2. **`$model` static property**
79+
3. **Auto-guessing** from repository class name (lowest priority)
80+
81+
When auto-guessing, Restify uses the prefix of the Repository name. For example, `UserPostRepository` class will try to find the `UserPost` model.
5982

6083
### Actions handled by the Repository
6184

@@ -90,16 +113,77 @@ for full model update, and respectively partial update.
90113

91114
</alert>
92115

93-
## Model name
116+
## Model Definition
94117

95118
As we already noticed, each repository basically works as a wrapper over a specific resource. The fancy
96119
naming `resource` is nothing more than a database entity (posts, users etc.). To make the repository aware of the
97-
entity it should handle, we need to define the model property associated with this resource:
120+
entity it should handle, we need to define the model associated with this resource.
121+
122+
Laravel Restify provides three ways to define the model, with the following priority order:
123+
124+
### 1. Modern Approach: PHP Attributes (Recommended)
125+
126+
The most modern and clean approach uses PHP 8+ attributes:
127+
128+
```php
129+
use Binaryk\LaravelRestify\Attributes\Model;
130+
131+
#[Model(Post::class)]
132+
class PostRepository extends Repository
133+
{
134+
// Clean - no static property needed
135+
public function fields(RestifyRequest $request): array
136+
{
137+
return [
138+
field('title'),
139+
field('content'),
140+
];
141+
}
142+
}
143+
```
144+
145+
You can also use string class names:
146+
147+
```php
148+
#[Model('App\Models\Post')]
149+
class PostRepository extends Repository
150+
{
151+
// Fields...
152+
}
153+
```
154+
155+
**Benefits of using attributes:**
156+
- Modern, declarative approach
157+
- Better IDE support and static analysis
158+
- Cleaner code (no need for static properties)
159+
- More discoverable with reflection tools
160+
- Type-safe when using `::class` syntax
161+
162+
### 2. Traditional Approach: Static Property
163+
164+
The classic approach using static properties (still fully supported):
98165

99166
```php
100-
public static string $model = 'App\\Models\\Post';
167+
class PostRepository extends Repository
168+
{
169+
public static string $model = Post::class;
170+
171+
// Or with string
172+
public static string $model = 'App\\Models\\Post';
173+
}
101174
```
102175

176+
### 3. Auto-Guessing (Fallback)
177+
178+
If neither attribute nor static property is defined, Restify will automatically guess the model from the repository class name:
179+
180+
- `UserRepository` → tries `App\Models\User`
181+
- `BlogPostRepository` → tries `App\Models\BlogPost`
182+
183+
<alert type="info">
184+
The attribute approach takes the highest priority, followed by the static property, and finally auto-guessing as a fallback.
185+
</alert>
186+
103187
## Public repository
104188

105189
Sometimes, you might find yourself facing the risk of exposing public information (allowing unauthenticated users to access it).

src/Attributes/Model.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Attributes;
4+
5+
use Attribute;
6+
use InvalidArgumentException;
7+
8+
#[Attribute(Attribute::TARGET_CLASS)]
9+
class Model
10+
{
11+
public readonly string $modelClass;
12+
13+
public function __construct(string $modelClass)
14+
{
15+
if (empty($modelClass)) {
16+
throw new InvalidArgumentException('Model class cannot be empty');
17+
}
18+
19+
$this->modelClass = $modelClass;
20+
}
21+
22+
public function getModelClass(): string
23+
{
24+
return $this->modelClass;
25+
}
26+
}

src/Fields/BelongsTo.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,19 @@ public function searchable(...$attributes): self
5151
if (count($attributes) === 1 && is_array($attributes[0])) {
5252
$this->searchablesAttributes = collect($attributes[0])->flatten()->all();
5353
// Also call parent with the first attribute for consistency
54-
if (!empty($this->searchablesAttributes)) {
54+
if (! empty($this->searchablesAttributes)) {
5555
parent::searchable($this->searchablesAttributes[0]);
5656
}
57+
5758
return $this;
5859
}
5960

6061
// If it's relationship-specific multiple attributes (all strings), use BelongsTo behavior
61-
if (count($attributes) > 1 && collect($attributes)->every(fn($attr) => is_string($attr))) {
62+
if (count($attributes) > 1 && collect($attributes)->every(fn ($attr) => is_string($attr))) {
6263
$this->searchablesAttributes = collect($attributes)->flatten()->all();
6364
// Also call parent to maintain consistency with CanSearch trait
6465
parent::searchable($attributes[0]);
66+
6567
return $this;
6668
}
6769

@@ -98,7 +100,7 @@ public function getSearchables(): array
98100
public function getSearchColumn(?RestifyRequest $request = null): mixed
99101
{
100102
// If we have BelongsTo-specific attributes, return the first one for compatibility
101-
if (!empty($this->searchablesAttributes)) {
103+
if (! empty($this->searchablesAttributes)) {
102104
return $this->searchablesAttributes[0];
103105
}
104106

src/Fields/Concerns/CanSearch.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ public function searchable(...$attributes): self
5959
if (is_string($firstAttribute)) {
6060
$this->searchableColumn = $firstAttribute;
6161
// Check if second parameter is a type
62-
$this->searchableType = (count($attributes) > 1 && is_string($attributes[1]))
63-
? $attributes[1]
62+
$this->searchableType = (count($attributes) > 1 && is_string($attributes[1]))
63+
? $attributes[1]
6464
: 'text';
6565

6666
return $this;

0 commit comments

Comments
 (0)