You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
10
10
### Added
11
11
12
+
-**Factory support.**`User::factory()->create()` and `->make()` now resolve to the model class. When a model uses the `HasFactory` trait with an explicit `@use HasFactory<UserFactory>` annotation, the generics system handles resolution. When the annotation is absent, the naming convention is used as a fallback: `App\Models\User` maps to `Database\Factories\UserFactory`, and subdirectories are preserved (`App\Models\Admin\SuperUser` maps to `Database\Factories\Admin\SuperUserFactory`). Factory chain methods that return `static` (e.g. `count()`, `state()`) continue the chain on the factory, while `create()` and `make()` return the model. The convention also works in reverse: a factory class extending `Factory` without `@extends Factory<Model>` resolves `TModel` from its own class name. Both directions are implemented as fallbacks that defer to explicit generics when present.
12
13
-**`newCollection()` override detection.** Eloquent models that override the `newCollection()` method now resolve to the custom collection class declared in the method's return type. This is the third detection mechanism alongside `#[CollectedBy]` and `@use HasCollection<X>`. Priority order: attribute, trait, method override. Works with short names resolved via `use` imports and fully-qualified return types. The standard `Collection` return type is correctly ignored. Custom collection methods appear after `->get()`, on relationship properties, and in builder chains.
13
14
-**Body-inferred relationship properties.** Eloquent relationship methods that lack `@return` annotations now produce virtual properties by scanning the method body for patterns like `$this->hasMany(Post::class)`. The relationship type is inferred from the method name (`hasMany` to `HasMany`, `belongsTo` to `BelongsTo`, etc.) and the related model class is extracted from the first `::class` argument. Supports all 10 relationship types including `HasOneThrough`. Fully-qualified class names, extra foreign key arguments, and chained builder calls (e.g. `->latest()`) are handled. When both a `@return` annotation and a body pattern are present, the annotation takes priority. Projects that don't use Larastan no longer need to add annotations for basic relationship completion.
14
15
-**Laravel accessor and mutator virtual properties.** Eloquent models with legacy accessors (`getFullNameAttribute()`) or modern Laravel 9+ accessors (methods returning `Illuminate\Database\Eloquent\Casts\Attribute`) now produce virtual properties. The property name is derived by converting the method name to snake_case: `getFullNameAttribute` produces `$full_name`, and `avatarUrl()` produces `$avatar_url`. Legacy accessors use the method's declared return type; modern accessors use `mixed`. Works alongside relationship properties, scope methods, and builder forwarding. `getAttribute()` (a real Eloquent method) is correctly excluded.
3. Resolving `create()` / `make()` on the factory to return the model.
39
-
40
-
This is medium complexity because it involves a naming convention
41
-
(model name → factory name) and cross-file resolution.
42
-
43
-
### 3. Closure parameter inference in collection pipelines
25
+
### 2. Closure parameter inference in collection pipelines
44
26
45
27
`$users->map(fn($u) => $u->...)` does not infer `$u` as the
46
28
collection's element type. This is a general generics/callable
47
29
inference problem, not Laravel-specific, but Laravel collection
48
30
pipelines are the most common place users encounter it.
31
+
Other cases:
32
+
- MyModel::whereIn()->chunk(self::CHUNK_SIZE, function (Collection $orders) {})
33
+
- MyModel::whereHas('order', function (Builder $q) {})
34
+
- MyModel::with(['translations' => function (Relation $query) {}]) // translations is the name of the relation on MyModel, Relation will become the return type of that relation
49
35
50
-
### 4. Query scope chaining on Builder instances
36
+
### 3. Query scope chaining on Builder instances
51
37
52
38
Inside a scope method body, `$query->verified()` (calling another
53
39
scope) does not offer scope method completions. Scope methods are
@@ -61,6 +47,11 @@ scope methods as instance methods on the resolved Builder. This
61
47
requires extending the virtual member system to also apply to
62
48
Builder instances, not just Model classes.
63
49
50
+
### 4. Scopes on queries
51
+
52
+
Copes are missing from complation of a query after other query
53
+
opertions for example Brand::where('id', $id)->isActive(); // Brand has a method called scopeIsActive()
54
+
64
55
---
65
56
66
57
## Out of scope (and why)
@@ -87,4 +78,4 @@ Builder instances, not just Model classes.
87
78
are best-effort.
88
79
-**Facades fall back to `@method`.** Facades whose `getFacadeAccessor()`
89
80
returns a string alias cannot be resolved. `@method` tags on facade
90
-
classes provide completion without template intelligence.
81
+
classes provide completion without template intelligence.
0 commit comments