Laravel is a web application framework with an expressive, elegant syntax, and also currently the most popular PHP framework ever existed.
Eloquent ORM is inclusion in Laravel which enables developers to interact with the database of their applications. I know many people may ask “why should I use ORM when I know my SQL QUERIES?”. I will say that it’s possible to know your SQL queries but I bet you that you may only be limited to one or two databases, but laravel eloquent has support for many underlying database types. You just need to write your eloquent command and allow laravel eloquent to initiate the queries.
Let me show you what I'm talking about, I'm assuming you have your laravel project set up already, with the correct database type in config/database.php
of your project. Right out of the box, laravel is configured to use MySQL so we will stick to that for this post.
'default' => env('DB_CONNECTION', 'mysql')
and in your connection array
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
Let us say we want to create a blogging platform and we expect to have the following tables (entities) in our database:
- Users
- Posts
- Comments
- Replies
The Laravel framework out of the box provides us with the User Model and the create_users_table migration file which exist under the database/migrations
folder of our project (migrations are the PHP files which laravel will use to create our database structure). The User Model here represents an entity in the users’ table of our project. Let’s have a look at what the User model which exist in the app/
folder looks like
//User.php
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Looking at the User model we see that the User model extends the User class in Illuminate\Foundation\Auth\User
imported as Authenticatable, this class behind the extends the Model class and implements lots of interfaces.
//Illuminate\Foundation\Auth\User.php
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable;
class User extends Model implements
AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}
But our focus will be our Model class which is the brain of our Eloquent ORM.
All models representing our database entities must extend the Illuminate\Database\Eloquent\Model
, which is used by eloquent to create communication between our application and the database. Let's run the following command to create a Post model and migration;
$ php artisan make:model Post -m
Model created successfully.
Created Migration: 2020_01_07_015353_create_posts_table
The -m directive here instruct laravel to create our migration file alongside creating for our Post model. Let’s take a look at our generated Post model existing in our App namespace.
//Post.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
//
}
Notice that our Post model is extending the Illuminate\Database\Eloquent\Model
class, which provide the Post model with the superpowers of Eloquent ORM
Protected $table
If your table name is different from what you have as your model name (let’s say you had an existing database with tables which you want to bind to your laravel project ), you can set up the $table property of the Model class specifying the table name;
protected $table = 'app_posts'; // replace users with your custom table name
one thing to note is that models are singular form for your plural table names, for example, User Model is applicable to users table.
Protected $primaryKey
Also eloquent takes your primary key to be id, but you can as well override this to a custom column name by setting the protected $primaryKey value to your primary key column name.
protected $primaryKey = 'post_id'; // custom column to use as primary key
NOTE: We will discuss more on customizing of models in subsequent articles
Let’s run our migrations so that laravel will generate our tables for us with the following command
$ php artisan migrate
Let’s create a user for our database, take a look at the create_user_table provided for us in database/migrations, inside our up method of the CreateUserClass with extends the Illuminate\Database\Migrations\Migration class (we will discuss on this class), the columns created for our users’ table can be seen there. On the terminal of your project root, type the following
save() method
We are going to use the interactive shell provided for us by laravel framework,run the following command;
$ php artisan tinker
we are going to use this shell to create a new user,
>>> $user = new \App\User;
>>> $user->name = “Samfield Hawb”;
>>> $user->email = “samfield4sure@gmail.com”;
>>> $user->password = bcrypt(“secret”);
>>> $user->save(); //eloquent save() method
>>> exit
$ Exit: Goodbye
Under the hood of the save()
method, eloquent performs the SQL insert command for us, saving us the stress of thinking on how we can insert the values correctly.
create() method
The above code snippet can also be achieved with the static create()
method of the model class, which accepts a keys/values pair array, with the keys representing the table column names.
$user = \App\User::create([
'name' => 'Samfield Hawb',
'email' => 'samfield4sure@gmail.com',
'password' => bcrypt('secret')//create an encrypted password
]);
Once the create method is executed, our user gets created with the $user
containing the created user and a generated id property.
Protected $fillable
The command creates a new user in the database too. In other for the create method to work for us, we will need to include the column fields here in our protected $fillable property of our model, we are doing this because Eloquent by default protects all it models against mass assignment vulnerability.
According to Laravel documentation,
A mass-assignment vulnerability occurs when a user passes an unexpected HTTP parameter through a request, and that parameter changes a column in your database you did not expect. For example, a malicious user might send an is_admin parameter through an HTTP request, which is then passed into your model's create method, allowing the user to escalate themselves to an administrator.
So adding the fields in our $fillable array, we instruct Eloquent to allow for the mass assignment of the fields.
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
Protected $guarded
The reverse for the fillable property is protected $gaurded, which can be used to specify the fields we cannot allow for mass assignment
/**
* The attributes that are not mass assignable.
*
* @var array
*/
protected $gaurded = [
'password',
];
all() method
With our user model now, let’s say we want to retrieve all our users from the database by
$users = App\User::all();
Calling the starting method all() which eloquent provides for us, return a collection of all the users in our database
Under the hood, laravel is executing the MySQL command (since we are using MySQL database)
SELECT * from users
With the collection return, we can easily perform actions with our data. Let print out the names of all the users returned (that will be only if you have data on the users’ table), Let print out the names of all the users from our database now.
foreach ($users as $user)
{
echo $user->name;
}
//Samfield Hawb
find() method
Laravel Eloquent provides us with the find()
method which can be used to get an instance of a model record or records. When the find method is passed in a primary key, it returns a single record matching the primary key, if no record its found, eloquent returns a null.
$user = App\User::find(1);
Here we instruct Eloquent to retrieve the user with the primary key 1
SELECT * FROM users WHERE id=1
An array of primary keys can also be passed to the find()
method of our model,
$users = App\User::find([1,2,3]);
When this is done the underlying Eloquent fetches and return a collection of records for the primary keys passed to it,
findOrFail() method
In most situations, we may want to throw an error when no model is found for a primary key. This can be achieved using the findOrFail()
method on our model
$user = App\User::findOrFail(1);
When a model is not found, an Illuminate\Database\Eloquent\ModelNotFoundException
will be thrown. If the exception is not handled, a 404 HTTP response is automatically sent back to the user which is the Laravel way of handling the ModelNotFoundExeption
error.
Conclusion
So far you have seen basically how eloquent is making queries simple. Watch out for my next article, as we continue our journey to see Eloquent ORM superpowers in action.
Top comments (6)
Thanks for this post, it's a very good explanation for diving into the Eloquent ORM.
I encourage you to re-read it to correct some spelling and grammar details that may confuse new developers trying to learn it.
Thanks for this, I sat down and read this yesterday (sunday).
Got to work this morning and allready am opening this up in another tab for reference.
You are welcome. I'm so please to hear it's a great guide to you. And a big encouragement to me to continue.
Good job Man.
thank you for the good explanation
Awesome read