search
HomeBackend DevelopmentPHP TutorialArdent: Laravel Models on Steroids

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

and then, fill the file with this code:

php artisan migrate:make todo_setup

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></span>

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></span>

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></span>

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>

… 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></span>

… 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></span>

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></span>

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

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></span>

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></span>

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></span>

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>

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

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></span>

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></span>

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></span>

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>

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></span>

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></span>

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
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
11 Best PHP URL Shortener Scripts (Free and Premium)11 Best PHP URL Shortener Scripts (Free and Premium)Mar 03, 2025 am 10:49 AM

Long URLs, often cluttered with keywords and tracking parameters, can deter visitors. A URL shortening script offers a solution, creating concise links ideal for social media and other platforms. These scripts are valuable for individual websites a

Introduction to the Instagram APIIntroduction to the Instagram APIMar 02, 2025 am 09:32 AM

Following its high-profile acquisition by Facebook in 2012, Instagram adopted two sets of APIs for third-party use. These are the Instagram Graph API and the Instagram Basic Display API.As a developer building an app that requires information from a

Working with Flash Session Data in LaravelWorking with Flash Session Data in LaravelMar 12, 2025 pm 05:08 PM

Laravel simplifies handling temporary session data using its intuitive flash methods. This is perfect for displaying brief messages, alerts, or notifications within your application. Data persists only for the subsequent request by default: $request-

Build a React App With a Laravel Back End: Part 2, ReactBuild a React App With a Laravel Back End: Part 2, ReactMar 04, 2025 am 09:33 AM

This is the second and final part of the series on building a React application with a Laravel back-end. In the first part of the series, we created a RESTful API using Laravel for a basic product-listing application. In this tutorial, we will be dev

Simplified HTTP Response Mocking in Laravel TestsSimplified HTTP Response Mocking in Laravel TestsMar 12, 2025 pm 05:09 PM

Laravel provides concise HTTP response simulation syntax, simplifying HTTP interaction testing. This approach significantly reduces code redundancy while making your test simulation more intuitive. The basic implementation provides a variety of response type shortcuts: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

cURL in PHP: How to Use the PHP cURL Extension in REST APIscURL in PHP: How to Use the PHP cURL Extension in REST APIsMar 14, 2025 am 11:42 AM

The PHP Client URL (cURL) extension is a powerful tool for developers, enabling seamless interaction with remote servers and REST APIs. By leveraging libcurl, a well-respected multi-protocol file transfer library, PHP cURL facilitates efficient execution of various network protocols, including HTTP, HTTPS, and FTP. This extension offers granular control over HTTP requests, supports multiple concurrent operations, and provides built-in security features.

12 Best PHP Chat Scripts on CodeCanyon12 Best PHP Chat Scripts on CodeCanyonMar 13, 2025 pm 12:08 PM

Do you want to provide real-time, instant solutions to your customers' most pressing problems? Live chat lets you have real-time conversations with customers and resolve their problems instantly. It allows you to provide faster service to your custom

Announcement of 2025 PHP Situation SurveyAnnouncement of 2025 PHP Situation SurveyMar 03, 2025 pm 04:20 PM

The 2025 PHP Landscape Survey investigates current PHP development trends. It explores framework usage, deployment methods, and challenges, aiming to provide insights for developers and businesses. The survey anticipates growth in modern PHP versio

See all articles

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

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool