While looking through a codebase, I noticed a method that wasn’t being called anywhere:
<?php
namespace App\Models;
class Something extends BaseModel
{
public function getStuffAttribute()
{
return ...
}
}
I couldn’t tell where getStuffAttribute() was being called. There wasn’t any
call site in the codebase.
After consulting with Cursor and Google, I learned this is was a thing in
Laravel 8, where a DB column is accessed with a dynamic signature,
get{AttributeName}Attribute(). When a model property is accessed, Eloquent
(Laravel’s ORM) checks for a matching accessor method and uses its return value.
See the docs below:
- https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor
- https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor
- Version 9 replaced the dynamic naming pattern with the
Attributeclass but the accessor still has to be named after the attribute being exposed. - The new syntax improves static analysis and makes the accessor more explicit.
- Version 9 replaced the dynamic naming pattern with the
Discovering this hidden magic made me reflect on whether ORMs and heavy OOP help or hinder maintainability.
Takeaways
My key takeaways from this are:
- ORMs should be avoided.
- ORMs hide logic through convention magic.
- I’ve yet to work on a codebase where an ORM was a necessity.
- OOP should be avoided.
- OOP patterns in web apps often create unnecessary indirection.
- Structural programming plus explicit SQL keeps complexity low.