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
@@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43
43
-**Generator yield type inference inside generator bodies.** When a function or method declares `@return Generator<TKey, TValue, TSend, TReturn>`, variables inside the generator body are now typed from the annotation. Variables that appear as the operand of a `yield` statement are inferred as TValue (the 2nd generic parameter), and variables assigned from a yield expression (`$var = yield $expr`) are inferred as TSend (the 3rd generic parameter). Works in class methods, top-level functions, key-value yields (`yield $k => $v`), cross-file resolution via PSR-4, and all four Generator type parameter arities. Explicit assignments still take priority over yield inference.
44
44
-**Custom Eloquent collections.** Models that declare a custom collection via `#[CollectedBy(CustomCollection::class)]` or `/** @use HasCollection<CustomCollection> */ use HasCollection;` now resolve to the custom collection class instead of the standard `Illuminate\Database\Eloquent\Collection`. Custom collection methods appear in completions after `Model::where(...)->get()->`, after `Model::get()->`, and on relationship properties that return a collection of the model. The attribute takes priority over the trait when both are present. Works with short names, fully-qualified names, cross-file PSR-4 resolution, and same-file definitions. Models without a custom collection continue to use the standard Collection.
45
45
-**Eloquent `$visible` array extraction.** The `$visible` property on Eloquent models is now recognised as a source of column names, matching the existing handling of `$fillable`, `$guarded`, and `$hidden`. Columns listed in `$visible` that are not already covered by `$casts` or `$attributes` produce `mixed`-typed virtual properties.
46
+
-**Relationship count properties.** Eloquent models now get `*_count` virtual properties for each relationship method. A `posts()` method returning `HasMany<Post>` produces a `$posts_count` property typed as `int`, matching the runtime behaviour of `withCount`/`loadCount`. CamelCase method names are converted to snake_case (`headBaker()` produces `$head_baker_count`). Works with all relationship types, body-inferred relationships, `$this->` access, and cross-file PSR-4 resolution. Existing properties from `$casts`, `$attributes`, or `@property` tags take priority.
Copy file name to clipboardExpand all lines: docs/todo-laravel.md
+13-38Lines changed: 13 additions & 38 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,6 +57,7 @@ today and what is still missing.
57
57
| Legacy accessors (`getXAttribute()`) | Method's return type ||
58
58
| Modern accessors (returns `Attribute`) | First generic arg of `Attribute<TGet>`, or `mixed` when unparameterised ||
59
59
| Relationship methods | Generic params or body inference ||
60
+
| Relationship `*_count` properties |`int`|`{snake_name}_count` for each relationship method |
60
61
61
62
### Gaps (ranked by impact ÷ effort)
62
63
@@ -73,33 +74,7 @@ benefit) and an **Effort** estimate (implementation complexity):
73
74
74
75
---
75
76
76
-
#### 1. `*_count` relationship count properties
77
-
78
-
|||
79
-
|---|---|
80
-
|**Impact**| ★★★★ — `withCount`/`loadCount` is one of the most common Eloquent patterns; `$model->posts_count` appears in nearly every non-trivial app. |
81
-
|**Effort**| ★★ — After synthesizing relationship properties, iterate relationships again and push `{snake_name}_count` typed as `int`. |
82
-
83
-
Accessing `$user->posts_count` is a very common Laravel pattern
84
-
(`withCount`, `loadCount`, or eager-loaded counts). We don't
85
-
synthesize these today.
86
-
87
-
```php
88
-
$user->posts_count; // int, but we know nothing about it
89
-
```
90
-
91
-
Larastan handles this **declaratively** — no call-site tracking
92
-
required. When a property name ends with `_count`, it strips the
93
-
suffix, checks whether the remainder (converted to camelCase) is a
94
-
relationship method, and if so types the property as `int`.
95
-
96
-
**Where to change:** In `LaravelModelProvider::provide`, after
97
-
synthesizing relationship properties, iterate the relationship methods
98
-
again and push a `{snake_name}_count` property typed as `int` for
99
-
each one. The property should have lower priority than explicit
100
-
`@property` tags.
101
-
102
-
#### 2. `#[Scope]` attribute (Laravel 11+)
77
+
#### 1. `#[Scope]` attribute (Laravel 11+)
103
78
104
79
|||
105
80
|---|---|
@@ -129,7 +104,7 @@ methods with the `#[Scope]` attribute the same as `scopeX` methods
129
104
(strip the first `$query` parameter, expose as both static and
130
105
instance virtual methods).
131
106
132
-
#### 3. `$dates` array (deprecated)
107
+
#### 2. `$dates` array (deprecated)
133
108
134
109
|||
135
110
|---|---|
@@ -148,7 +123,7 @@ Merge these into `casts_definitions` at a lower priority than explicit
148
123
`$casts` entries, or add a separate field on `ClassInfo` and handle
0 commit comments