Table of Contents
Key Takeaways
Our Test Application
Installing Ardent
Data Validation
Model Auto-Hydrate
Model Hooks
Defining Relationships (the Ardent way)
Conclusion
Frequently Asked Questions (FAQs) about Laravel Models
What are the key differences between Laravel 4.2, 5.0, 7.x, and 10.x Eloquent?
How does Ardent enhance Laravel models?
How do I use multiple connections in Laravel Eloquent?
What is eager loading in Laravel Eloquent?
How do I use soft deletes in Laravel Eloquent?
What are model factories in Laravel Eloquent?
How does Ardent handle nested transaction-safe saves?
How do I use API resources in Laravel Eloquent?
How does Ardent handle validation?
What is the purpose of the boot() method in Laravel Eloquent?
Home Backend Development PHP Tutorial Ardent: Laravel Models on Steroids

Ardent: Laravel Models on Steroids

Feb 19, 2025 am 09:07 AM

Ardent: Laravel Models on Steroids

Ardent: Laravel Models on Steroids

One of the (few) things I don’t like about Laravel is that you cannot move the validation code from your controller to your models easily. When I write software I like to apply the “fat models, skinny controllers” principle. So, for me, writing the validation code in the controller is not a good thing.

To solve this, I’d like to introduce Ardent, a great package for Laravel 4. To be more precise, Ardent presents itself as “Self-validating smart models for Laravel Framework 4’s Eloquent ORM.” In other words: exactly what we need!

As you can imagine, it’s an extension of the Eloquent Model class, basically. This package comes with some new functionality, utilities and methods dedicated to input validation and other little things.

Key Takeaways

  • Enhanced Validation: Ardent simplifies the validation process by allowing rules to be defined directly within the model, enhancing code organization and maintainability, especially in larger projects.
  • Model Auto-Hydrate: This feature automatically fills model attributes from form input, reducing boilerplate code in controllers and making the codebase cleaner and more efficient.
  • Model Hooks: Ardent introduces model hooks which are methods that execute at specific lifecycle moments, such as before and after save, update, or delete, providing greater control over data handling.
  • Simplified Relationships: Defining model relationships is more streamlined with Ardent, using a simple array structure (`$relationsData`), which reduces the complexity of relationship management in Laravel models.
  • Auto Purging Redundant Data: Ardent can automatically discard unnecessary data from inputs, such as confirmation fields or CSRF tokens, ensuring that only relevant data is processed and stored.

Our Test Application

For a better understanding of the advantages you can enjoy while using Ardent, we will set up a little test application. Nothing complicated: a simple To-Do List app.

Of course, I’m not going to implement a complete application: I just want to explain some principles, so I will make some controllers and models – no views. After that, I will “translate” the code using Ardent.

Our To-Do List will count two different entities:

  • User

    • id
    • first_name
    • last_name
    • email
    • password
  • Task

    • id
    • name
    • status (done / not done)

A really basic project. However, if you don’t want to write code, don’t worry: I have already prepared a migration that you can use to generate the database. Use it!

Create the migration file with the command

php artisan migrate:make todo_setup
Copy after login
Copy after login
Copy after login
Copy after login

and then, fill the file with this code:

php artisan migrate:make todo_setup
Copy after login
Copy after login
Copy after login
Copy after login

Now we have our tables. It’s time to create our models. Even here we have very few lines to write. Here’s the User model (that is also the default one).

<span><span><?php
</span></span><span>
</span><span>    <span>use Illuminate<span>\Database\Schema\Blueprint</span>;
</span></span><span>    <span>use Illuminate<span>\Database\Migrations\Migration</span>;
</span></span><span>
</span><span>    <span>class TodoSetup extends Migration {
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * Run the migrations.
</span></span><span><span>         *
</span></span><span><span>         * <span>@return <span>void</span>
</span></span></span><span><span>         */
</span></span><span>        <span>public function up()
</span></span><span>        <span>{
</span></span><span>            <span>Schema<span>::</span>create('users', function(Blueprint $table)
</span></span><span>            <span>{
</span></span><span>                <span>$table->increments('id')->unsigned();
</span></span><span>
</span><span>                <span>$table->string('first_name');
</span></span><span>                <span>$table->string('last_name');
</span></span><span>                <span>$table->string('email');
</span></span><span>                <span>$table->string('password', 60);
</span></span><span>
</span><span>                <span>$table->timestamps();
</span></span><span>            <span>});
</span></span><span>
</span><span>            <span>Schema<span>::</span>create('tasks', function(Blueprint $table)
</span></span><span>            <span>{
</span></span><span>                <span>$table->increments('id');
</span></span><span>
</span><span>                <span>$table->string('name');
</span></span><span>                <span>$table->boolean('status');
</span></span><span>
</span><span>                <span>$table->integer('user_id')->unsigned();
</span></span><span>
</span><span>                <span>$table->timestamps();
</span></span><span>
</span><span>                <span>$table->index('user_id');
</span></span><span>            <span>});
</span></span><span>        <span>}
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * Reverse the migrations.
</span></span><span><span>         *
</span></span><span><span>         * <span>@return <span>void</span>
</span></span></span><span><span>         */
</span></span><span>        <span>public function down()
</span></span><span>        <span>{
</span></span><span>            <span>Schema<span>::</span>dropIfExists('users');
</span></span><span>            <span>Schema<span>::</span>dropIfExists('tasks');
</span></span><span>        <span>}
</span></span><span>
</span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

I just added the tasks method to describe the relationship with the Task model.

<span><span><?php
</span></span><span>
</span><span>    <span>use Illuminate<span>\Auth\UserTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\UserInterface</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableInterface</span>;
</span></span><span>
</span><span>    <span>class User extends Eloquent implements UserInterface, RemindableInterface {
</span></span><span>
</span><span>        <span>use UserTrait, RemindableTrait;
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The database table used by the model.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>string</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $table = 'users';
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The attributes excluded from the model's JSON form.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>array</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $hidden = array('password', 'remember_token');
</span></span><span>
</span><span>        <span>public function tasks()
</span></span><span>        <span>{
</span></span><span>            <span>return $this->hasMany('Task');
</span></span><span>        <span>}
</span></span><span>
</span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

We just made our starting point. From now on, right after the installation, we will see two different situations: first, the “normal” version of the code without Ardent. Right after that, we will make a comparison with the “improved” version. You will notice the difference, trust me.

Let’s start!

Installing Ardent

Installing Ardent is very easy with Composer. Just add the dependency to the composer.json file of your project.

<span><span><?php
</span></span><span>
</span><span>    <span>class Task extends <span>\Eloquent</span> {
</span></span><span>        <span>protected $fillable = [];
</span></span><span>
</span><span>        <span>public function user()
</span></span><span>        <span>{
</span></span><span>            <span>return $this->belongsTo('User');
</span></span><span>        <span>}
</span></span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

Then, after the update, you just have to extend the Ardent class in your models like so:

<span>{
</span>        <span>"require": {
</span>            <span>"laravelbook/ardent": "2.*"
</span>        <span>}
</span>    <span>}</span>
Copy after login
Copy after login
Copy after login

… and you are ready to go!

Data Validation

The first thing to do is to analyze how Ardent makes our life easier in implementing validation. We already know how to do it with Laravel. Let’s make a classic example: the POST method that will handle data coming in from the form.

In a “normal” situation we would make something like this:

<span><span><?php
</span></span><span>    <span>class User extends <span>\LaravelBook\Ardent\Ardent</span> {
</span></span><span>        <span>// model code here!
</span></span><span>    <span>}</span></span>
Copy after login
Copy after login

… what about with Ardent?

With Ardent, things change a little bit. First of all, as you can easily imagine, the validation rules are going to be moved directly into the model: it is here that we will start our “restyle”. So, open the model file and change it like so:

<span><span><?php
</span></span><span>
</span><span>    <span>public function postSignup()
</span></span><span>    <span>{
</span></span><span>        <span>$rules = array(
</span></span><span>            <span>'first_name' => 'required',
</span></span><span>            <span>'last_name' => 'required',
</span></span><span>            <span>'email' => 'required|email|unique:users',
</span></span><span>            <span>'password' => 'required|min:8'
</span></span><span>        <span>);
</span></span><span>
</span><span>        <span>$messages = array(
</span></span><span>            <span>'first_name.required' => 'First name is required.',
</span></span><span>            <span>'last_name.required' => 'Last name is required.',
</span></span><span>            <span>'email.required' => 'Email is required.',
</span></span><span>            <span>'password.required' => 'Password is required.',
</span></span><span>
</span><span>            <span>'email.email' => 'Use a real email address!',
</span></span><span>            <span>'email.unique' => 'This email address already exists!',
</span></span><span>            <span>'password.min' => 'Password must be at least 8 character long.'
</span></span><span>        <span>);
</span></span><span>
</span><span>        <span>$validator = Validator<span>::</span>make(Input<span>::</span>all(), $rules, $messages);
</span></span><span>
</span><span>        <span>if($validator->fails())
</span></span><span>        <span>{
</span></span><span>            <span>return Redirect<span>::</span>to('user/signup')->with('errors', $validator->messages());
</span></span><span>        <span>}
</span></span><span>
</span><span>        <span>$user = new User;
</span></span><span>
</span><span>        <span>$user->first_name = Input<span>::</span>get('first_name');
</span></span><span>        <span>$user->last_name = Input<span>::</span>get('last_name');
</span></span><span>        <span>$user->email = Input<span>::</span>get('email');
</span></span><span>        <span>$user->password = Hash<span>::</span>make(Input<span>::</span>get('password'));
</span></span><span>
</span><span>        <span>if($user->save())
</span></span><span>        <span>{
</span></span><span>            <span>$status = 1;
</span></span><span>        <span>}
</span></span><span>        <span>else
</span></span><span>        <span>{
</span></span><span>            <span>$status = 0;
</span></span><span>        <span>}
</span></span><span>
</span><span>        <span>return Redirect<span>::</span>to('user/signup')->with('status', $status);
</span></span><span>    <span>}</span></span>
Copy after login
Copy after login

What happened? Not much: we changed the base class of our model (from Eloquent to Ardent) and we moved (using the same syntax, just a copy) the validation rules here, with the custom error messages.

So, the question now is: what are we going to write in our controller?

Let’s check it out:

<span><span><?php
</span></span><span>
</span><span>    <span>use Illuminate<span>\Auth\UserTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\UserInterface</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableInterface</span>;
</span></span><span>
</span><span>    <span>class User extends <span>\LaravelBook\Ardent\Ardent</span> implements UserInterface, RemindableInterface {
</span></span><span>
</span><span>        <span>public static $rules = array(
</span></span><span>            <span>'first_name' => 'required',
</span></span><span>            <span>'last_name' => 'required',
</span></span><span>            <span>'email' => 'required|email|unique:users',
</span></span><span>            <span>'password' => 'required|min:8'
</span></span><span>        <span>);
</span></span><span>
</span><span>        <span>public static $customMessages = array(
</span></span><span>            <span>'first_name.required' => 'First name is required.',
</span></span><span>            <span>'last_name.required' => 'Last name is required.',
</span></span><span>            <span>'email.required' => 'Email is required.',
</span></span><span>            <span>'password.required' => 'Password is required.',
</span></span><span>
</span><span>            <span>'email.email' => 'Use a real email address!',
</span></span><span>            <span>'email.unique' => 'This email address already exists!',
</span></span><span>            <span>'password.min' => 'Password must be at least 8 character long.'
</span></span><span>        <span>);
</span></span><span>
</span><span>        <span>use UserTrait, RemindableTrait;
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The database table used by the model.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>string</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $table = 'users';
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The attributes excluded from the model's JSON form.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>array</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $hidden = array('password', 'remember_token');
</span></span><span>
</span><span>        <span>public function tasks()
</span></span><span>        <span>{
</span></span><span>            <span>return $this->hasMany('Task');
</span></span><span>        <span>}
</span></span><span>
</span><span>    <span>}</span></span>
Copy after login

No more validation instructions here. They all disappeared. It’s not just a “moving”, however: the $user->save() method, now, will return false if there are some problems in the validation phase. Then, you will be able to retrieve errors with the $user->errors()->all() method. No strange classes: the returned object will be a classic MessageBag that you maybe already met while working with Laravel.

If you prefer, however, you can also use the $user->validationErrors property. In that case, or if you want to retrieve field-specific errors just use$user->validationErrors->get('field_name').

Now, it is very likely that you are thinking “OK, but what is the real advantage, beyond fewer lines of code?”

Let’s start with the most important: better code organization means better project maintainability. In simple applications you can’t feel it as a priority, but when it comes to bigger projects things can be easily messed up with a single wrong decision. Let me make a real-world situation example. We developed our awesome To-Do List application, and it is growing really quickly. We definitely need a RESTful API for the mobile application. Using the controller in the “normal” way will mean writing another signup routine for the API. Two different blocks with the same code! This is no good. Where is the good old DRY (Don’t Repeat Yourself) principle?

So, the best practice would be writing a signup() method in the model that handles everything. Using Ardent means handling really everything: from validation to the save procedure. Without it, we could not accomplish the first phase.

A second advantage is a more practical one: model auto-hydrate. Let’s discover it together.

Model Auto-Hydrate

Our postSignup() method counts exactly thirteen lines of code. Even if it seems difficult, Ardent can lower that number further. Take a look at this example:

php artisan migrate:make todo_setup
Copy after login
Copy after login
Copy after login
Copy after login

No errors here. You probably already understand what happened.

Ardent has a model auto-hydrate feature. This means that when you create the object and call the $user->save() method, every field is filled automatically with the Input object data. Of course, you will have to give the right name at every form field accordingly.

So, this code:

<span><span><?php
</span></span><span>
</span><span>    <span>use Illuminate<span>\Database\Schema\Blueprint</span>;
</span></span><span>    <span>use Illuminate<span>\Database\Migrations\Migration</span>;
</span></span><span>
</span><span>    <span>class TodoSetup extends Migration {
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * Run the migrations.
</span></span><span><span>         *
</span></span><span><span>         * <span>@return <span>void</span>
</span></span></span><span><span>         */
</span></span><span>        <span>public function up()
</span></span><span>        <span>{
</span></span><span>            <span>Schema<span>::</span>create('users', function(Blueprint $table)
</span></span><span>            <span>{
</span></span><span>                <span>$table->increments('id')->unsigned();
</span></span><span>
</span><span>                <span>$table->string('first_name');
</span></span><span>                <span>$table->string('last_name');
</span></span><span>                <span>$table->string('email');
</span></span><span>                <span>$table->string('password', 60);
</span></span><span>
</span><span>                <span>$table->timestamps();
</span></span><span>            <span>});
</span></span><span>
</span><span>            <span>Schema<span>::</span>create('tasks', function(Blueprint $table)
</span></span><span>            <span>{
</span></span><span>                <span>$table->increments('id');
</span></span><span>
</span><span>                <span>$table->string('name');
</span></span><span>                <span>$table->boolean('status');
</span></span><span>
</span><span>                <span>$table->integer('user_id')->unsigned();
</span></span><span>
</span><span>                <span>$table->timestamps();
</span></span><span>
</span><span>                <span>$table->index('user_id');
</span></span><span>            <span>});
</span></span><span>        <span>}
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * Reverse the migrations.
</span></span><span><span>         *
</span></span><span><span>         * <span>@return <span>void</span>
</span></span></span><span><span>         */
</span></span><span>        <span>public function down()
</span></span><span>        <span>{
</span></span><span>            <span>Schema<span>::</span>dropIfExists('users');
</span></span><span>            <span>Schema<span>::</span>dropIfExists('tasks');
</span></span><span>        <span>}
</span></span><span>
</span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

will have the same effect as

<span><span><?php
</span></span><span>
</span><span>    <span>use Illuminate<span>\Auth\UserTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\UserInterface</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableInterface</span>;
</span></span><span>
</span><span>    <span>class User extends Eloquent implements UserInterface, RemindableInterface {
</span></span><span>
</span><span>        <span>use UserTrait, RemindableTrait;
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The database table used by the model.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>string</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $table = 'users';
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The attributes excluded from the model's JSON form.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>array</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $hidden = array('password', 'remember_token');
</span></span><span>
</span><span>        <span>public function tasks()
</span></span><span>        <span>{
</span></span><span>            <span>return $this->hasMany('Task');
</span></span><span>        <span>}
</span></span><span>
</span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

From thirtheen lines we just went down to seven for an entire signup procedure.

To use this feature, you will have to activate it. Just switch the $autoHydrateEntityFromInput in your model to true, like this:

<span><span><?php
</span></span><span>
</span><span>    <span>class Task extends <span>\Eloquent</span> {
</span></span><span>        <span>protected $fillable = [];
</span></span><span>
</span><span>        <span>public function user()
</span></span><span>        <span>{
</span></span><span>            <span>return $this->belongsTo('User');
</span></span><span>        <span>}
</span></span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

Done!

You will also often have some redundant data that you will not need for the business logic. Think about _confirmation fields or the CSRF tokens. Well, we can discard them with the model’s $autoPurgeRedundantAttributes property. As before, just switch it to true.

<span>{
</span>        <span>"require": {
</span>            <span>"laravelbook/ardent": "2.*"
</span>        <span>}
</span>    <span>}</span>
Copy after login
Copy after login
Copy after login

Now the procedure is cleaner than before.

Model Hooks

Another good feature worth mentioning is the introduction of model hooks. They are, essentially, a list of methods that, if implemented, are called in certain execution moments. So, to make an example, the afterUpdate() method will be called before every update() call. The beforeValidate() method will be called before every validation, and so on.

Here’s a list of all these methods:

  • beforeCreate()
  • afterCreate()
  • beforeSave()
  • afterSave()
  • beforeUpdate()
  • afterUpdate()
  • beforeDelete()
  • afterDelete()
  • beforeValidate()
  • afterValidate()

A classic example could be some data elaboration before the save procedure. Like this:

php artisan migrate:make todo_setup
Copy after login
Copy after login
Copy after login
Copy after login

Every “before” method has a boolean return value. If true, the following operation is executed normally. If the method returns false, the operation is going to be stopped. In the method above, we generated a slug (and filled the proper field) with the beforeSave() method, right after the validation.

There is also a specific tip about beforeSave() and afterSave(): you can declare them at run-time. Look:

<span><span><?php
</span></span><span>
</span><span>    <span>use Illuminate<span>\Database\Schema\Blueprint</span>;
</span></span><span>    <span>use Illuminate<span>\Database\Migrations\Migration</span>;
</span></span><span>
</span><span>    <span>class TodoSetup extends Migration {
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * Run the migrations.
</span></span><span><span>         *
</span></span><span><span>         * <span>@return <span>void</span>
</span></span></span><span><span>         */
</span></span><span>        <span>public function up()
</span></span><span>        <span>{
</span></span><span>            <span>Schema<span>::</span>create('users', function(Blueprint $table)
</span></span><span>            <span>{
</span></span><span>                <span>$table->increments('id')->unsigned();
</span></span><span>
</span><span>                <span>$table->string('first_name');
</span></span><span>                <span>$table->string('last_name');
</span></span><span>                <span>$table->string('email');
</span></span><span>                <span>$table->string('password', 60);
</span></span><span>
</span><span>                <span>$table->timestamps();
</span></span><span>            <span>});
</span></span><span>
</span><span>            <span>Schema<span>::</span>create('tasks', function(Blueprint $table)
</span></span><span>            <span>{
</span></span><span>                <span>$table->increments('id');
</span></span><span>
</span><span>                <span>$table->string('name');
</span></span><span>                <span>$table->boolean('status');
</span></span><span>
</span><span>                <span>$table->integer('user_id')->unsigned();
</span></span><span>
</span><span>                <span>$table->timestamps();
</span></span><span>
</span><span>                <span>$table->index('user_id');
</span></span><span>            <span>});
</span></span><span>        <span>}
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * Reverse the migrations.
</span></span><span><span>         *
</span></span><span><span>         * <span>@return <span>void</span>
</span></span></span><span><span>         */
</span></span><span>        <span>public function down()
</span></span><span>        <span>{
</span></span><span>            <span>Schema<span>::</span>dropIfExists('users');
</span></span><span>            <span>Schema<span>::</span>dropIfExists('tasks');
</span></span><span>        <span>}
</span></span><span>
</span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

Let’s think about a couple of possible uses of these methods in our application.

Maybe a beforeSave() to deal with password hashing?

<span><span><?php
</span></span><span>
</span><span>    <span>use Illuminate<span>\Auth\UserTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\UserInterface</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableTrait</span>;
</span></span><span>    <span>use Illuminate<span>\Auth\Reminders\RemindableInterface</span>;
</span></span><span>
</span><span>    <span>class User extends Eloquent implements UserInterface, RemindableInterface {
</span></span><span>
</span><span>        <span>use UserTrait, RemindableTrait;
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The database table used by the model.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>string</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $table = 'users';
</span></span><span>
</span><span>        <span>/**
</span></span><span><span>         * The attributes excluded from the model's JSON form.
</span></span><span><span>         *
</span></span><span><span>         * <span>@var <span>array</span>
</span></span></span><span><span>         */
</span></span><span>        <span>protected $hidden = array('password', 'remember_token');
</span></span><span>
</span><span>        <span>public function tasks()
</span></span><span>        <span>{
</span></span><span>            <span>return $this->hasMany('Task');
</span></span><span>        <span>}
</span></span><span>
</span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

Or a cleaning hook right before the user delete procedure?

<span><span><?php
</span></span><span>
</span><span>    <span>class Task extends <span>\Eloquent</span> {
</span></span><span>        <span>protected $fillable = [];
</span></span><span>
</span><span>        <span>public function user()
</span></span><span>        <span>{
</span></span><span>            <span>return $this->belongsTo('User');
</span></span><span>        <span>}
</span></span><span>    <span>}</span></span>
Copy after login
Copy after login
Copy after login

There are many possibilities.

Defining Relationships (the Ardent way)

With Ardent, you can also define relationships in a shorter way than before. Let’s see how we actually define our relationships between models: the following example shows the tasks() method in the User model.

<span>{
</span>        <span>"require": {
</span>            <span>"laravelbook/ardent": "2.*"
</span>        <span>}
</span>    <span>}</span>
Copy after login
Copy after login
Copy after login

Using Ardent to define relationships means defining a simple array, called $relationsData.

<span><span><?php
</span></span><span>    <span>class User extends <span>\LaravelBook\Ardent\Ardent</span> {
</span></span><span>        <span>// model code here!
</span></span><span>    <span>}</span></span>
Copy after login
Copy after login

This has the exact same effect. Ardent uses the same naming convention to bind names and methods, without having to write them one by one.

However, there are many customizations that you can do:

<span><span><?php
</span></span><span>
</span><span>    <span>public function postSignup()
</span></span><span>    <span>{
</span></span><span>        <span>$rules = array(
</span></span><span>            <span>'first_name' => 'required',
</span></span><span>            <span>'last_name' => 'required',
</span></span><span>            <span>'email' => 'required|email|unique:users',
</span></span><span>            <span>'password' => 'required|min:8'
</span></span><span>        <span>);
</span></span><span>
</span><span>        <span>$messages = array(
</span></span><span>            <span>'first_name.required' => 'First name is required.',
</span></span><span>            <span>'last_name.required' => 'Last name is required.',
</span></span><span>            <span>'email.required' => 'Email is required.',
</span></span><span>            <span>'password.required' => 'Password is required.',
</span></span><span>
</span><span>            <span>'email.email' => 'Use a real email address!',
</span></span><span>            <span>'email.unique' => 'This email address already exists!',
</span></span><span>            <span>'password.min' => 'Password must be at least 8 character long.'
</span></span><span>        <span>);
</span></span><span>
</span><span>        <span>$validator = Validator<span>::</span>make(Input<span>::</span>all(), $rules, $messages);
</span></span><span>
</span><span>        <span>if($validator->fails())
</span></span><span>        <span>{
</span></span><span>            <span>return Redirect<span>::</span>to('user/signup')->with('errors', $validator->messages());
</span></span><span>        <span>}
</span></span><span>
</span><span>        <span>$user = new User;
</span></span><span>
</span><span>        <span>$user->first_name = Input<span>::</span>get('first_name');
</span></span><span>        <span>$user->last_name = Input<span>::</span>get('last_name');
</span></span><span>        <span>$user->email = Input<span>::</span>get('email');
</span></span><span>        <span>$user->password = Hash<span>::</span>make(Input<span>::</span>get('password'));
</span></span><span>
</span><span>        <span>if($user->save())
</span></span><span>        <span>{
</span></span><span>            <span>$status = 1;
</span></span><span>        <span>}
</span></span><span>        <span>else
</span></span><span>        <span>{
</span></span><span>            <span>$status = 0;
</span></span><span>        <span>}
</span></span><span>
</span><span>        <span>return Redirect<span>::</span>to('user/signup')->with('status', $status);
</span></span><span>    <span>}</span></span>
Copy after login
Copy after login

Every element in $relationsData has a key (yes, the relation’s method name) and an array with some parameters.

  • the first parameter (without a key, it’s just the first) describes the relation type (hasOne, hasMany, belongsTo, belongsToMany, morphTo, morphOne, morphMany).
  • the second parameter (without a key, it’s just the second) defines the destination model of the current relation;
  • further parameters don’t have a specific position, but a key. They could be:
    • foreignKey: optional, used for hasOne, hasMany, belongsTo and belongsToMany;
    • table, otherKey, timestamps and pivotKeys: optional, used for belongsToMany;
    • name, type and id: used with morphTo, morphOne and morphMany;

Conclusion

With a big pack of advantages (also 126k downloads and frequent updates) it’s very difficult to find a reason to not use Ardent in your next app. It is suitable for every kind of project, and being an extension of Eloquent’s Model, it achieves full compatibility with Laravel projects.

I definitely recommend it. Do you? Have you tried it out? Let us know in the comments below!

Frequently Asked Questions (FAQs) about Laravel Models

What are the key differences between Laravel 4.2, 5.0, 7.x, and 10.x Eloquent?

Laravel Eloquent has evolved significantly from version 4.2 to 10.x. In Laravel 4.2, Eloquent was a simple ORM (Object-Relational Mapping) with basic CRUD operations. Laravel 5.0 introduced new features like multiple connections, soft deletes, and event handling. Laravel 7.x brought in eager loading, model serialization, and API resources. Laravel 10.x has further enhanced Eloquent with improved performance, better error handling, and advanced features like batch operations and model factories.

How does Ardent enhance Laravel models?

Ardent is a package that adds a self-validating smart Eloquent model to Laravel. It provides automatic validation of attributes before they are saved, which reduces the amount of validation code you need to write in your controllers. Ardent also supports nested transaction-safe saving of models and their relationships, which simplifies complex save operations.

How do I use multiple connections in Laravel Eloquent?

In Laravel Eloquent, you can use multiple database connections by defining them in your config/database.php file. Then, in your Eloquent model, you can specify which connection to use with the $connection property. For example, protected $connection = 'mysql2'; would use the ‘mysql2’ connection.

What is eager loading in Laravel Eloquent?

Eager loading is a method of loading related data in a single database query, rather than multiple queries. This can significantly improve performance when working with large datasets. You can use the with() method in Eloquent to specify which relationships to eager load.

How do I use soft deletes in Laravel Eloquent?

Soft deletes in Laravel Eloquent allow you to ‘delete’ a record without actually removing it from the database. Instead, a deleted_at timestamp is set. You can enable soft deletes in an Eloquent model by using the SoftDeletes trait and adding a deleted_at column to your table.

What are model factories in Laravel Eloquent?

Model factories in Laravel Eloquent are a convenient way to generate new model instances for testing or seeding your database. You can define a model factory that specifies the default attribute values for your model, and then use the factory to create new instances with those defaults.

How does Ardent handle nested transaction-safe saves?

Ardent provides a saveNested() method that saves a model and all its related models in a single database transaction. This ensures that either all saves succeed, or none do, maintaining the integrity of your data.

How do I use API resources in Laravel Eloquent?

API resources in Laravel Eloquent allow you to transform your models and model collections into JSON format for use in an API. You can create a resource class that defines how the model should be transformed, and then return instances of that resource class from your API routes.

How does Ardent handle validation?

Ardent automatically validates your model’s attributes against a set of rules defined in the model before saving. If validation fails, the save operation is aborted and the validation errors are available through the errors() method.

What is the purpose of the boot() method in Laravel Eloquent?

The boot() method in Laravel Eloquent is a lifecycle hook that is called when the model is ‘booted’, i.e., loaded into memory. You can override this method in your model to add behavior that should occur whenever the model is booted, such as registering event listeners or customizing the model’s configuration.

The above is the detailed content of Ardent: Laravel Models on Steroids. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Explain JSON Web Tokens (JWT) and their use case in PHP APIs. Explain JSON Web Tokens (JWT) and their use case in PHP APIs. Apr 05, 2025 am 12:04 AM

JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

How does session hijacking work and how can you mitigate it in PHP? How does session hijacking work and how can you mitigate it in PHP? Apr 06, 2025 am 12:02 AM

Session hijacking can be achieved through the following steps: 1. Obtain the session ID, 2. Use the session ID, 3. Keep the session active. The methods to prevent session hijacking in PHP include: 1. Use the session_regenerate_id() function to regenerate the session ID, 2. Store session data through the database, 3. Ensure that all session data is transmitted through HTTPS.

What are Enumerations (Enums) in PHP 8.1? What are Enumerations (Enums) in PHP 8.1? Apr 03, 2025 am 12:05 AM

The enumeration function in PHP8.1 enhances the clarity and type safety of the code by defining named constants. 1) Enumerations can be integers, strings or objects, improving code readability and type safety. 2) Enumeration is based on class and supports object-oriented features such as traversal and reflection. 3) Enumeration can be used for comparison and assignment to ensure type safety. 4) Enumeration supports adding methods to implement complex logic. 5) Strict type checking and error handling can avoid common errors. 6) Enumeration reduces magic value and improves maintainability, but pay attention to performance optimization.

Describe the SOLID principles and how they apply to PHP development. Describe the SOLID principles and how they apply to PHP development. Apr 03, 2025 am 12:04 AM

The application of SOLID principle in PHP development includes: 1. Single responsibility principle (SRP): Each class is responsible for only one function. 2. Open and close principle (OCP): Changes are achieved through extension rather than modification. 3. Lisch's Substitution Principle (LSP): Subclasses can replace base classes without affecting program accuracy. 4. Interface isolation principle (ISP): Use fine-grained interfaces to avoid dependencies and unused methods. 5. Dependency inversion principle (DIP): High and low-level modules rely on abstraction and are implemented through dependency injection.

How to debug CLI mode in PHPStorm? How to debug CLI mode in PHPStorm? Apr 01, 2025 pm 02:57 PM

How to debug CLI mode in PHPStorm? When developing with PHPStorm, sometimes we need to debug PHP in command line interface (CLI) mode...

How to automatically set permissions of unixsocket after system restart? How to automatically set permissions of unixsocket after system restart? Mar 31, 2025 pm 11:54 PM

How to automatically set the permissions of unixsocket after the system restarts. Every time the system restarts, we need to execute the following command to modify the permissions of unixsocket: sudo...

How to send a POST request containing JSON data using PHP's cURL library? How to send a POST request containing JSON data using PHP's cURL library? Apr 01, 2025 pm 03:12 PM

Sending JSON data using PHP's cURL library In PHP development, it is often necessary to interact with external APIs. One of the common ways is to use cURL library to send POST�...

See all articles