Mastering Laravel Eloquent ORM - The Eloquent Journey (PART 1)
Tags: laravel, php
Published: 2020-01-10 12:28:46

---
title: Mastering Laravel Eloquent ORM - The Eloquent Journey (PART 1)
published: true
description: A series on mastering Laravel Eloquent ORM(Object-Relational Mapping)
tags: laravel,PHP
series: Mastering Laravel Eloquent ORM - The Eloquent Journey
cover_image: https://res.cloudinary.com/samfield/image/upload/v1578485140/Post%20Images/laravel-eloquent-orm-5a5d9744cab14.png
---
>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.

```php
'default' => env('DB_CONNECTION', 'mysql')
```

and in your connection array 

```php
'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:
1. Users
2. Posts
3. Comments
4. 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

<?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
<?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.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/w5c5h7gmznjnvmzjocsg.png)

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; 
```bash
$ 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
<?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;
```php
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.
```php
 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
```shell
$ 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;
```shell
$ php artisan tinker
```
 we are going to use this shell to create a new user,
```shell
>>> $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.
```php
$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.
```php
    /**
     * 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
```php
    /**
     * 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
```php
$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) 
```sql
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.
```php
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. 
```php
 $user = App\User::find(1);
```
Here we instruct Eloquent to retrieve the user with the primary key 1 
```sql
SELECT * FROM users WHERE id=1
```
An array of primary keys can also be passed to the `find()` method of our model,
```php
$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
```php
 $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.