Installation:
composer require jenssegers/model
Add the namespace to your composer.json autoload:
"autoload": {
"psr-4": {
"App\\": "app/",
"Jenssegers\\Model\\": "vendor/jenssegers/model/src/"
}
}
Run composer dump-autoload.
First Model:
Extend Jenssegers\Model\Model in your model:
use Jenssegers\Model\Model;
class User extends Model
{
protected $fillable = ['name', 'email'];
protected $hidden = ['password'];
}
Basic Usage:
$user = new User(['name' => 'John', 'email' => 'john@example.com']);
$user->save(); // Override with custom logic (e.g., API call)
Replace Eloquent’s save() with a custom API call:
public function save(array $options = [])
{
$response = Http::post('https://api.example.com/users', $this->toArray());
$this->setAttributes($response->json());
return $this;
}
$user = new User(['name' => 'John', 'email' => 'invalid']); // Fails if 'email' not in $fillable
protected $casts = [
'is_admin' => 'boolean',
'created_at' => 'datetime:Y-m-d',
];
Usage:
$user->is_admin; // Returns boolean
$user->created_at->format('d/m/Y'); // DateTime object
public function getFullNameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
protected $appends = ['full_name', 'role'];
$user->toArray(); // Includes 'full_name' and 'role'
protected $hidden = ['password', 'api_token'];
$user->toJson(); // Excludes hidden fields
toArray() or toJson() for bespoke output:
public function toArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'metadata' => $this->getMetadata(),
];
}
While not as feature-rich as Eloquent, you can simulate relationships:
public function posts()
{
return collect($this->related('posts')->all());
}
protected function related($name)
{
return new static($this->{"{$name}_data"});
}
Leverage Laravel’s event system for model lifecycle hooks:
protected static function boot()
{
static::saving(function ($model) {
$model->updateTimestamps();
});
}
No Query Builder:
illuminate/database) for database operations.cycle/orm.Mass Assignment:
fill() is not automatically available. Use $model->setAttributes($data) or manually assign:
$user->setFillable(['name', 'email'])->fill(['name' => 'Jane']);
Timestamps:
created_at/updated_at. Manually set or override:
protected $dates = ['created_at', 'updated_at'];
public function updateTimestamps()
{
$this->updated_at = now();
if (!$this->exists) {
$this->created_at = now();
}
}
Relationships:
hasMany). Implement custom logic or use a separate package.Attribute Conflicts:
$fillable or use setRawAttributes() to bypass mutators:
$user->setRawAttributes(['password' => 'plaintext'], true);
Casting Issues:
if (isset($this->attributes['age'])) {
$this->age; // Now casted
}
Hidden Attributes in Arrays:
toArray()/toJson(). Use $model->getAttributes() to see all raw data.Custom Validation:
Override validate() or use Laravel’s validator:
public function validate(array $attributes)
{
return Validator::make($attributes, [
'email' => 'required|email',
]);
}
API Resource Integration:
Pair with laravel/framework's Illuminate\Http\Resources\JsonResource for API responses:
public function toJson()
{
return new UserResource($this);
}
Soft Deletes: Implement manually or use a trait:
trait SoftDeletes
{
protected $deletedAt = 'deleted_at';
public function delete()
{
$this->deleted_at = now();
}
}
Observers: Use Laravel’s observer pattern for model events:
class UserObserver {
public function saving(User $user) { /* ... */ }
}
Register in a service provider:
Model::observe(UserObserver::class);
Avoid Overloading: Heavy accessors/mutators can slow serialization. Cache computed properties:
private $cachedFullName;
public function getFullNameAttribute()
{
return $this->cachedFullName ??= "{$this->first_name} {$this->last_name}";
}
Lazy Loading: Defer expensive operations (e.g., API calls) until needed:
private $posts;
public function getPostsAttribute()
{
return $this->posts ??= $this->fetchPostsFromApi();
}
How can I help you explore Laravel packages today?