Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kokoshneta's avatar

Allowing custom data in collections in PHP 8.2+

As of PHP 8.2, dynamic properties are deprecated. This is, in my view, generally a bad decision, but it’s been taken, so we’ll just have to deal with it.

To me, probably the most aggravating thing about the change is collections (basic and Eloquent). I very frequently store custom data, such as aggregate calculations, directly on collection objects by doing things like this (obviously simplified to illustrate):

$productGroups = Product::all()->groupBy('type');

foreach ($productGroups as $group) {
	$group->count = $group->count();
	$group->sumTotal = $group->sum(fn ($item) => ($item->unitPrice + ($item->unitPrice * $item->vatRate)) * $item->quantity);
}

This worked flawlessly prior to PHP 8.2, but now throws a deprecation warning and will probably throw a fatal error from PHP 9 onwards.

The only real way I can see of getting around this is quite a faff:

  • create custom Collection and EloquentCollection classes that either allow dynamic properties (via the #[AllowDynamicProperties] attribute) or use magic methods to get and set custom data
  • for base collections, use new MyCustomCollection() everywhere instead of collect()
  • for Eloquent collections, either define newCollection() on every single model you have (or define it in a trait and then use that trait on every single model); or create a custom base model that has newCollection() defined, and then change all your models to extend that model instead of the standard model

Regardless of what precise implementation you go for, you need to manually change code in every single model you’ve defined, and in every place you’ve collected data manually. For existing projects, that’s quite a lot.

It would be so much easier if there were some way, à la container binding, to let Laravel know that any requested instance of Illuminate\Support\Collection should always use App\Support\MyCustomCollection instead – but of course, binding won’t work, since nearly all collection instances are not resolved through the container, just directly instantiated with a hard-coded reference to Illuminate\Support\Collection.

Is there some easier way to get custom data in collections than what I described above?

1 like
0 replies

Please or to participate in this conversation.