Skip to content

Commit 3c6a91d

Browse files
committed
Add another Eloquent Virtual property source
1 parent adb22eb commit 3c6a91d

8 files changed

Lines changed: 298 additions & 1104 deletions

File tree

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4242
- **Nested key completion for literal arrays.** When a variable is assigned a literal array with nested associative arrays (e.g. `$cfg = ['db' => ['host' => 'x', 'port' => 3306]]`), completing `$cfg['db']['` now offers the nested keys. Previously only a `@var array{...}` docblock produced nested completions. Works at arbitrary nesting depth, inside class methods, and at the top level.
4343
- **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.
4444
- **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+
- **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.
4546

4647
### Changed
4748

docs/todo-laravel.md

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ today and what is still missing.
5353
|--------|-----------|-------|
5454
| `$casts` / `casts()` | Rich (built-in map, custom cast `get()` return type, enum, `Castable`, `CastsAttributes<TGet>` generics fallback) | |
5555
| `$attributes` defaults | Literal type inference (string, bool, int, float, null, array) | Fallback when no `$casts` entry |
56-
| `$fillable`, `$guarded`, `$hidden` | `mixed` | Last-resort column name fallback |
56+
| `$fillable`, `$guarded`, `$hidden`, `$visible` | `mixed` | Last-resort column name fallback |
5757
| Legacy accessors (`getXAttribute()`) | Method's return type | |
5858
| Modern accessors (returns `Attribute`) | First generic arg of `Attribute<TGet>`, or `mixed` when unparameterised | |
5959
| Relationship methods | Generic params or body inference | |
@@ -73,21 +73,7 @@ benefit) and an **Effort** estimate (implementation complexity):
7373

7474
---
7575

76-
#### 1. `$visible` array not included in column name extraction
77-
78-
| | |
79-
|---|---|
80-
| **Impact** | ★★ — Only affects models that use `$visible` without also declaring the same columns in `$fillable`/`$hidden`/`$casts`. |
81-
| **Effort** | ★ — Add one string (`"visible"`) to the `targets` array in `extract_column_names`. |
82-
83-
The `$visible` property lists attribute names that should appear in
84-
serialized output. It functions identically to `$fillable`/`$guarded`/
85-
`$hidden` as a source of column names.
86-
87-
**Where to change:** Add `"visible"` to the `targets` array in
88-
`extract_column_names` in `parser/classes.rs`.
89-
90-
#### 2. `$this` in inferred callable parameter types resolves to wrong class
76+
#### 1. `$this` in inferred callable parameter types resolves to wrong class
9177

9278
| | |
9379
|---|---|
@@ -123,7 +109,7 @@ any literal `$this` or `static` tokens with the FQN of the receiver
123109
class before returning them. This ensures the inferred types
124110
reference the declaring class rather than the calling class.
125111

126-
#### 3. `*_count` relationship count properties
112+
#### 2. `*_count` relationship count properties
127113

128114
| | |
129115
|---|---|
@@ -149,7 +135,7 @@ again and push a `{snake_name}_count` property typed as `int` for
149135
each one. The property should have lower priority than explicit
150136
`@property` tags.
151137

152-
#### 4. `#[Scope]` attribute (Laravel 11+)
138+
#### 3. `#[Scope]` attribute (Laravel 11+)
153139

154140
| | |
155141
|---|---|
@@ -179,7 +165,7 @@ methods with the `#[Scope]` attribute the same as `scopeX` methods
179165
(strip the first `$query` parameter, expose as both static and
180166
instance virtual methods).
181167

182-
#### 5. `$dates` array (deprecated)
168+
#### 4. `$dates` array (deprecated)
183169

184170
| | |
185171
|---|---|
@@ -198,7 +184,7 @@ Merge these into `casts_definitions` at a lower priority than explicit
198184
`$casts` entries, or add a separate field on `ClassInfo` and handle
199185
priority in the provider.
200186

201-
#### 6. Custom Eloquent builders (`HasBuilder` / `#[UseEloquentBuilder]`)
187+
#### 5. Custom Eloquent builders (`HasBuilder` / `#[UseEloquentBuilder]`)
202188

203189
| | |
204190
|---|---|
@@ -236,7 +222,7 @@ declares a custom builder via `@use HasBuilder<X>` in `use_generics`
236222
or a `newEloquentBuilder()` method with a non-default return type.
237223
If found, load and resolve that builder class instead.
238224

239-
#### 7. `abort_if`/`abort_unless` type narrowing
225+
#### 6. `abort_if`/`abort_unless` type narrowing
240226

241227
| | |
242228
|---|---|
@@ -280,7 +266,7 @@ to subsequent code:
280266
This is similar to the existing guard clause narrowing but triggered
281267
by specific function names rather than `if` + early return.
282268

283-
#### 8. `collect()` and other helper functions lose generic type info
269+
#### 7. `collect()` and other helper functions lose generic type info
284270

285271
| | |
286272
|---|---|
@@ -328,7 +314,7 @@ before passing it to `type_hint_to_classes`. See the general TODO
328314
item (§ PHP Language Feature Gaps, "Function-level `@template`
329315
generic resolution") for the full implementation plan.
330316

331-
#### 9. Factory `has*`/`for*` relationship methods
317+
#### 8. Factory `has*`/`for*` relationship methods
332318

333319
| | |
334320
|---|---|
@@ -366,7 +352,7 @@ The `has*` variant should accept optional `int $count` and
366352
`array|callable $state` parameters; `for*` should accept
367353
`array|callable $state`.
368354

369-
#### 10. `$pivot` property on BelongsToMany related models
355+
#### 9. `$pivot` property on BelongsToMany related models
370356

371357
| | |
372358
|---|---|
@@ -412,7 +398,7 @@ the `BelongsToMany` relationship stubs. If the user's stub set
412398
includes these annotations, it already works through our PHPDoc
413399
provider.
414400

415-
#### 11. `withSum()` / `withAvg()` / `withMin()` / `withMax()` aggregate properties
401+
#### 10. `withSum()` / `withAvg()` / `withMin()` / `withMax()` aggregate properties
416402

417403
| | |
418404
|---|---|
@@ -428,7 +414,7 @@ aggregate function (`withSum`/`withAvg` → `float`,
428414

429415
The `@property` workaround applies here too.
430416

431-
#### 12. Higher-order collection proxies
417+
#### 11. Higher-order collection proxies
432418

433419
| | |
434420
|---|---|
@@ -451,7 +437,7 @@ and `HigherOrderCollectionProxyExtension`, which resolve the proxy's
451437
template types and delegate property/method lookups to the collection's
452438
value type.
453439

454-
#### 13. `SoftDeletes` trait methods on Builder
440+
#### 12. `SoftDeletes` trait methods on Builder
455441

456442
| | |
457443
|---|---|
@@ -479,7 +465,7 @@ type — e.g. `Builder<static>` instead of `Builder<User>`. This is
479465
a minor gap but not worth a dedicated fix until custom builder
480466
support (gap §7) is implemented.
481467

482-
#### 14. `View::withX()` and `RedirectResponse::withX()` dynamic methods
468+
#### 13. `View::withX()` and `RedirectResponse::withX()` dynamic methods
483469

484470
| | |
485471
|---|---|
@@ -511,7 +497,7 @@ hard-coding the two known classes. A simpler approach: add
511497
`@method` tags to bundled stubs for the most common dynamic `with*`
512498
methods, or document this as a known limitation.
513499

514-
#### 15. `$appends` array
500+
#### 14. `$appends` array
515501

516502
| | |
517503
|---|---|

0 commit comments

Comments
 (0)