A Practical Introduction to Laravel Eloquent ORM

2.7k views

Introduction

Eloquent is an object relational mapper (ORM) that is included by default within the Laravel framework. An ORM is software that facilitates handling database records by representing data as objects, working as a layer of abstraction on top of the database engine used to store an application’s data.

Eloquent facilitates the task of interacting with database tables, providing an object-oriented approach to inserting, updating, and deleting database records, while also providing a streamlined interface for executing complex SQL queries.

In this project-based series, you’ll learn how to make database queries and how to work with relationships in Laravel Eloquent. To practice the examples explained throughout the series, you’ll download a demo Laravel application and use the included Docker Compose setup to run a PHP development environment on containers. The demo consists of a single page application that shows a list of links or bookmarks. You’ll improve the application by adding new models and defining new relationships between them that will extend the current database structure.

Screenshot of Landing Laravel app, updated to support link lists

If you’d like an introduction to the Laravel framework, you can follow the guide on How To Build a Links Landing Page in Laravel. That tutorial explains how you can build the demo application that this series uses as a foundation from scratch.

Prerequisites

Although the code shared throughout this series should work seamlessly across multiple environments and systems, the instructions explained here were tested within an Ubuntu 20.04 local system running Docker and Docker Compose. Regardless of your base operating system, here’s what you’ll need to set up in order to get started:

  • Docker installed on your local machine or remote development server. If you’re running Ubuntu 20.04, you can follow Steps 1 and 2 of How To Install and Use Docker on Ubuntu 20.04 to set it up. Windows and MacOS users need to install Docker Desktop instead.
  • Docker Compose installed on your local machine or development server. Docker Compose comes included by default with Docker Desktop for both Windows and MacOS systems, but Linux users need to install the Compose executable, following Step 1 of How To Install and Use Docker Compose on Ubuntu 20.04.
  • A code editor for PHP (optional). A code editor helps making code easier to read and to format, and can improve your productivity by pointing out issues before you execute your code. You can follow our guide on How To Set Up Visual Studio Code for PHP Projects to set up VSCode, a free code editor, within your local development environment.

Setting Up the Demo Project

To get started, you’ll need to set up the Landing Laravel demo project. There are two ways in which you can get the demo application code ready to use with this series:

  1. The first way is to follow the guide on How To Build a Links Landing Page in Laravel. That series explains how to build the demo application that you’ll use as base for the current series from scratch. In you choose this option, you can move on to the first tutorial in this series How To Create a One-To-Many Relationship in Laravel Eloquent.

  2. The second option is to download the complete demo application code and use it as the base that you will build on in this series.

To download the code from GitHub, first make sure that you have the curl and unzip tools available on your system:

  • sudo apt update
  • sudo apt install curl unzip

Next, change to your home directory using the cd ~ command, and then download release 0.1.1 of the project using curl:

  • cd ~
  • curl -L https://github.com/do-community/landing-laravel/archive/refs/tags/0.1.1.zip -o landing-laravel.zip

The demo code will be saved in the landing-laravel.zip file. Unzip the contents of the zip file, rename the directory to landing-laravel, and cd into the application folder using the following commands:

  • unzip landing-laravel.zip
  • mv landing-laravel-0.1.1 landing-laravel
  • cd landing-laravel

The MySQL image that you will use with Docker Compose uses environment variables to set up the database user and password. Before bringing the environment up for the first time, you’ll need to set up an .env file that contains database credentials. The demo application includes an example .env.example file that you can use. Copy it in place by running the following command:

  • cp .env.example .env

You can now bring your environment up with docker-compose:

  • docker-compose up -d

Install the Laravel application dependencies with:

  • docker-compose exec app composer install

This will install the PHP dependencies that Laravel needs via Composer. Next, create a unique application key using artisan:

  • docker-compose exec app php artisan key:generate

You should receive output like the following, indicating that artisan added a unique application key to your .env file:

Output
Application key set successfully.

Finally, run the database migrations and seeders to set up the database:

  • docker-compose exec app php artisan migrate --seed

You will receive output like the following, which indicates the database tables, and seed data are configured correctly:

Output
Migration table created successfully. . . . Database seeding completed successfully.

The application is now configured and running in your development environment. Point your browser to http://localhost:8000 and you’ll receive a page similar to this:

Landing Laravel demo application

With this base structure in place, you can proceed with the rest of the tutorials in this series.

The demo Landing Laravel application that you set up as a prerequisite for this series contains a single database table to store links. In this tutorial you’ll modify this initial database structure to include a second table, which you will use to organize links into lists.

For the links and lists example we’re going to use in this series, each link is part of only one list, but each list can have multiple links. This kind of relationship is also known as a one-to-many relationship.

A one-to-many relationship happens when one item, which we’ll call type A, can be linked to several items of type B, but the opposite doesn’t hold true: an item of type B can only be linked to one item of type A. Transposing this scenario to the current demo application models, A is the list type, and B is the link type.

To get started, you’ll need to create a model and a database table to represent a List of links. Then, you’ll update the existing Link model and table to include the relationship between both models. Because the term List is reserved for PHP internals, you won’t be able to name your new model with that term. You can call this new model LinkList instead.

First, make sure you’re in the application directory:

  • cd ~/landing-laravel

Create a new model using artisan:

  • docker-compose exec app php artisan make:model LinkList

This will generate a new model class in the app/Model directory:

app/Model/LinkList.php

If you look at your app/Console/Commands directory, you’ll notice that there’s already a class file named LinkList.php. This is not to be confused with the Eloquent model you just created. This class contains a CLI command that lists all the links in the database via artisan.

To avoid confusion in the future, now is a good moment to rename that class and its command signature to a different name. In this case use the class name LinkShow since that name also describes what the class does. To rename the app/Console/Commands/LinkList.php file to another valid name, run this command in your terminal:

  • mv app/Console/Commands/LinkList.php app/Console/Commands/LinkShow.php

Then, open the file app/Console/Commands/LinkShow.php in your code editor to change the class name from LinkList to LinkShow, and the command signature from link:list to link:show, like the highlighted lines in the following code listing. This is how the file should look like once you’re finished:

app/Console/Commands/LinkShow.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use Illuminate\Console\Command;

class LinkShow extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:show';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'List links saved in the database';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $headers = [ 'id', 'url', 'description' ];
        $links = Link::all(['id', 'url', 'description'])->toArray();
        $this->table($headers, $links);

        return 0;
    }
}

Save and close the file when you’re done. To check that everything worked as expected, run your newly renamed link:show artisan command:

  • docker-compose exec app php artisan link:show

You’ll receive output like this:

Output
+----+-------------------------------------------------+----------------------------------+ | id | url | description | +----+-------------------------------------------------+----------------------------------+ | 1 | https://digitalocean.com/community | DigitalOcean Community | | 2 | https://digitalocean.com/community/tags/laravel | Laravel Tutorias at DigitalOcean | | 3 | https://digitalocean.com/community/tags/php | PHP Tutorials at DigitalOcean | +----+-------------------------------------------------+----------------------------------+

The new app/Model/LinkList.php class that you generated with the previous artisan make:model command contains generic code for a new Eloquent class. Unlike other ORMs such as Doctrine, Eloquent doesn’t alter database structures, handling only data itself. Eloquent models are usually lean, with class properties automatically inferred from the model’s table structure.

This approach to handling data-only with Eloquent means that you don’t need to set up any properties for the LinkList class because they will be inferred from the database table structure for that model.

Structural database operations are typically handled in Laravel via database migrations. Migrations allow developers to programmatically define structural changes to the database, such as creating, modifying, and deleting tables.

You’ll now create a new migration to set up the lists table in the database.

The artisan command line tool included by default with Laravel contains several helper methods to bootstrap new components such as controllers, models, migrations, among others. To create a new migration using artisan, run:

  • docker-compose exec app php artisan make:migration create_link_lists_table
Output
Created Migration: 2021_07_07_152554_create_link_lists_table

This command will generate a new file under the database/migrations directory in your Laravel application, using an auto-generated name based on the current date and time, and the migration name. That file contains generic code that you’ll modify to set up the lists table.

Using your code editor, open the generated migration file. The file currently looks like this:

database/migrations/2021_07_07_152554_create_link_lists_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateLinkListsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('link_lists', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('link_lists');
    }
}

The migration runs the up() method when executed with the artisan migrate command. This is where your table definition goes, and by default it creates an id primary key field and two timestamp fields (created_at and updated_at), defined with the timestamps() Schema method. Those fields are automatically filled by Eloquent when a model is created and updated, respectively. The down() method is called when the migration is rolled back with the artisan rollback command, and typically executes code to drop the table or revert structural changes.

You’ll change the up method to include the following fields:

  • title: a string representing the title of this List
  • description: a string representing the description of a List
  • slug: a unique, short string based on the title, typically used to create user-friendly URLs

In a one-to-many relationship, the many side (which in this scenario corresponds to the links table) is the one to hold the column reference (or foreign key) to the other element (corresponding to the lists table). That means you’ll have to modify the links table later on, in order to include a reference field that will link that table to the lists table.

The lists table, on the other hand, doesn’t need any special field to reference its links.

Replace the current content in your migration file with the following code:

database/migrations/2021_07_07_152554_create_link_lists_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateLinkListsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('link_lists', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('title', 60);
            $table->string('slug', 60)->unique();
            $table->text('description')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('link_lists');
    }
}

Save the file when you’re done.

Next, open the existing links migration file in your code editor. In the demo project, you’ll find the migration at the following path:

2020_11_18_165241_create_links_table.php

First, include a use directive pointing to the fully qualified class name for the LinkList class, at the beginning of the file and right after the last use line:

…
use Illuminate\Support\Facades\Schema;
use App\Models\LinkList;
...

Next, include the following line in the table definition, within the up method and right after the line that sets up the description field:

$table->text('description');
$table->foreignIdFor(LinkList::class);

The foreignIdFor() method creates a foreign key column to the referenced Eloquent model. It uses default nomenclature to set up a field that is linked to the primary key field of the referenced table.

This is how the full migration class should look like when you’re done:

database/migrations/2020_11_18_165241_create_links_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use App\Models\LinkList;

class CreateLinksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('links', function (Blueprint $table) {
            $table->id();
            $table->string('url', 200);
            $table->text('description');
            $table->foreignIdFor(LinkList::class);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('links');
    }
}

Save the file when you’re finished editing it. Next, wipe the database and then run the migration command again to recreate your database structure with the updated migrations files:

  • docker-compose exec app php artisan db:wipe
  • docker-compose exec app php artisan migrate

Configuring Eloquent Model Relationships

The database tables are now set up, but you still need to configure the Eloquent models to define the relationship between them.

On the List model, which is the one side of the relationship, you’ll set up a new method named links. This method will work as a proxy to access the links that are related to each list, using the hasMany method from the parent Illuminate\Database\Eloquent\Model class.

In your code editor, open the file app/Model/LinkList.php. Replace the current generic code with the following content:

app/Model/LinkList.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class LinkList extends Model
{
    use HasFactory;

    public function links()
    {
        return $this->hasMany(Link::class);
    }
}

Save the file when you’re done.

Next, you’ll edit the many side of the relationship to include a reference back to the List model, so that links can access their respective list. This is done with the belongsTo method from the parent Model class. This method is used to define the inverse side of the one-to-many relationship.

Open the Link model in your code editor:

app/Model/Link.php

Replace the current content in your Link.php file with the following code:

app/Model/Link.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Link extends Model
{
    public function link_list()
    {
        return $this->belongsTo(LinkList::class);
    }
}

Save the file when you’re done.

With both models updated, your database is now configured completely, but it is currently empty. In the next section of this series, you’ll learn how to insert new records in the database using Eloquent models.

In a previous section of this series, you set up two models for a one-to-many relationship between the LinkList and Link models. In this section, you’ll learn how to insert links and lists in the database using Eloquent models. To limit the scope of this work, you’ll use custom Artisan commands to manage links and lists from the command line, which won’t require a web form.

One of the biggest advantages of using an ORM system is the ability to manipulate rows in a database table as objects within your codebase. With Eloquent, as with other ORMs, the object itself provides methods that can be used to persist it to the database, saving you the work of writing SQL statements and manually managing data within tables.

When working with one-to-many relationships in Laravel Eloquent, you have a few different options to save related models. In most cases, you’ll need to first set up the model representing the one side of the relationship, which in this demo is the LinkList model, and save that to the database. After doing that, you’ll be able to reference this model (which, once saved, represents a database record) when setting up the many side of the relationship (the Link model). That also means you’ll need to first have one or more lists in order to be able to create links.

Before creating a new command to insert lists, however, you should update the existing link:new command to support the list feature.

Open the following file in your code editor:

app/Console/Commands/LinkNew.php

You’ll see code like this:

app/Console/Commands/LinkNew.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class LinkNew extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:new';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a New Link';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $url = $this->ask('Link URL:');

        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            $this->error("Invalid URL. Exiting...");
            return 1;
        }

        $description = $this->ask('Link Description:');

        $this->info("New Link:");
        $this->info($url . ' - ' . $description);

        if ($this->confirm('Is this information correct?')) {
            $link = new Link();
            $link->url = $url;
            $link->description = $description;
            $link->save();

            $this->info("Saved.");
        }

        return 0;
    }
}

The handle() method is where the command executes its procedures. This is what it does:

  1. The ask() method, made available through the parent Illuminate\Console\Command class, is a method used to obtain input from a user in the command line. This will prompt a user for a link, and validate the input to make sure it’s a valid URL.
  2. The script then asks for an optional description.
  3. Once values for url and description are obtained, the script will prompt for a confirmation using the confirm() method, available through the parent Illuminate\Console\Command.
  4. When a confirmation is submitted with y or yes, the script will set up a new link object and save it to the database using the save() method, available through the model’s parent Illuminate\Database\Eloquent\Model class.
  5. The script outputs a message to inform the user that the link was saved to the database, using the info output method.

Note about return values: in the context of command line applications running on bash, non-zero return values are used to signal that the application exited in error, while 0 means it exited with success.

If you run the link:new command now, it will break before it is finished because the database expects every link to be connected to a list. You’ll need to let the user choose which list a link should be included in, using a default list if none is provided by the user.

The following code will ask the user to specify a list or leave it blank to use the default list. Then, it will try to locate the list or create a new list using the specified slug in case the list doesn’t exist yet. To retrieve a list provided by the user, this code uses the firstWhere method to find a list based on its slug field. Finally, it saves the new link using the links() relationship that can be accessed from the LinkList object.

Substitute the current content in your LinkNew command class with:

app/Console/Commands/LinkNew.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use App\Models\LinkList;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class LinkNew extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:new';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a New Link';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $url = $this->ask('Link URL');

        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            $this->error("Invalid URL. Exiting...");
            return 1;
        }

        $description = $this->ask('Link Description');
        $list_name = $this->ask('Link List (leave blank to use default)') ?? "default";

        $this->info("New Link:");
        $this->info($url . ' - ' . $description);
        $this->info("Listed in: " . $list_name);

        if ($this->confirm('Is this information correct?')) {
            $list = LinkList::firstWhere('slug', $list_name);
            if (!$list) {
                $list = new LinkList();
                $list->title = $list_name;
                $list->slug = $list_name;
                $list->save();
            }

            $link = new Link();
            $link->url = $url;
            $link->description = $description;
            $list->links()->save($link);

            $this->info("Saved.");
        }

        return 0;
    }
}

Save and close the file when you’re done. Then, run the command with:

  • docker-compose exec app php artisan link:new

You’ll be prompted to provide a URL, a description, and a list name, in case you don’t want to save this link to the default list.

Once you save your new link, if you run the link:show command, you should see the new link added to the results. However, there is no information included in the output about lists yet. You’ll need to update the LinkShow command to include a column that displays this information.

Open the app/Console/Commands/LinkShow.php file in your code editor:

app/Console/Commands/LinkShow.php

This is how the class should look like now:

app/Console/Commands/LinkShow.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use Illuminate\Console\Command;

class LinkShow extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:show';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'List links saved in the database';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $headers = [ 'id', 'url', 'description' ];
        $links = Link::all(['id', 'url', 'description'])->toArray();
        $this->table($headers, $links);

        return 0;
    }
}

You’ll see that the current handle() method is fetching a certain number of fields and converting the result to an array. By default, results come from Eloquent as an Eloquent Collection, so this function converts them to an array in order to use that data within the table() method. The problem is that when the array conversion is made, you lose the relationship between class models (Link and LinkList), which makes it more difficult to access information about the list that a link is connected to.

You’ll need to change this code so that it fetches the full Link object, including the related objects from the database. To create an array that is suitable for using with the table() method, you can iterate through the collection of results returned by Link::all().

Replace the current contents in the app/Console/Commands/LinkShow.php file with the following code:

app/Console/Commands/LinkShow.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use Illuminate\Console\Command;

class LinkShow extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:show';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'List links saved in the database';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $headers = [ 'id', 'url', 'list', 'description' ];
        $links = Link::all();

        $table_rows = [];
        foreach ($links as $link) {
            $table_rows[] = [ $link->id, $link->url, $link->link_list->slug, $link->description ];
        }

        $this->table($headers, $table_rows);

        return 0;
    }
}

Now, if you run the link:show method, you’ll see an additional column showing the list slug:

Output
+----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+ | id | url | list | description | +----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+ | 1 | https://digitalocean.com | default | DigitalOcean Website | | 2 | https://digitalocean.com/community/tutorials | tutorials | DO Tutorials | | 3 | https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04 | tutorials | Initial server setup on ubuntu 20.04 | +----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+

Later in this tutorial series, you’ll update the front end and main route code to show links organized into lists. For now, you’ll use the command line to add, migrate, and validate your changes to the database and models.

The next tutorial in this series will demonstrate another way of inserting new records in the database using Eloquent models, this time through the use of database seeders.

Laravel’s Seeders are special classes that live in the database/seeders directory in a Laravel project that allow you to programmatically insert a collection of default or sample records in the database. The demo application has a seeder class that imports links from a links.yml file in the root of the application folder.

In your code editor, open the following file:

database/seeders/LinkSeeder.php

It will contain the following code:

database/seeders/LinkSeeder.php
<?php

namespace Database\Seeders;

use App\Models\Link;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Yaml\Yaml;

class LinkSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //only import seeds if DB is empty.
        if (!Link::count()) {
            $this->importLinks();
        }
    }

    /**
     * Imports Links from the default links.yml file at the root of the app.
     * Change that file to import a set of personal basic links you want to show
     * as soon as the application is deployed.
     */
    public function importLinks()
    {
        $links_import_path = __DIR__ . '/../../links.yml';

        $yaml = new Yaml();
        if (is_file($links_import_path)) {
            $links = $yaml->parsefile($links_import_path);

            foreach ($links as $link) {
                DB::table('links')->insert([
                    'url' => $link['url'],
                    'description' => $link['description']
                ]);
            }
        }
    }
}

Notice that this code does not use the Link model and instead uses the query builder to insert new links in the database. This is a different way of working with database records in Laravel that doesn’t depend on Eloquent models. Even though this works well, by using Eloquent models you’ll have access to a series of helpful methods and shortcuts to make your code more concise and easier to read.

To improve this code, you’ll change the foreach loop to use Eloquent models instead of querying the database directly with the query builder. You’ll also have to create a default list of links (called $default_list in the following code) before the loop is started, so that you can reference this list in each new link created.

Replace the current content in your seeder class with the following code:

database/seeders/LinkSeeder.php
<?php

namespace Database\Seeders;

use App\Models\Link;
use App\Models\LinkList;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Yaml\Yaml;

class LinkSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //only import seeds if DB is empty.
        if (!Link::count()) {
            $this->importLinks();
        }
    }

    /**
     * Imports Links from the default links.yml file at the root of the app.
     * Change that file to import a set of personal basic links you want to show
     * as soon as the application is deployed.
     */
    public function importLinks()
    {
        $links_import_path = __DIR__ . '/../../links.yml';

        $yaml = new Yaml();
        if (is_file($links_import_path)) {
            $links = $yaml->parsefile($links_import_path);

            $default_list = new LinkList();
            $default_list->title = "Default";
            $default_list->description = "Default List";
            $default_list->slug = "default";
            $default_list->save();

            foreach ($links as $link) {
                $seed_link = new Link();
                $seed_link->url = $link['url'];
                $seed_link->description = $link['description'];

                $default_list->links()->save($seed_link);
            }
        }
    }
}


The updated code uses an object-oriented approach for setting up the properties for the LinkList and List models that are translated into table columns by Eloquent. The final line of the for loop uses the $default_list reference to the links table, which is accessed via the method links(), to save new links within that list.

Save the file when you’re done. Laravel seeders will only run when the database is empty, so as to not conflict with actual data that was inserted in the database by other means. Thus in order to run the modified seeder, you’ll need to wipe the database once again with the artisan db:wipe command..

Run the following command to wipe the development database:

  • docker-compose exec app php artisan db:wipe
Output
Dropped all tables successfully.

Now to recreate the tables and run the updated seeders, you can use the following artisan migrate --seed command:

  • docker-compose exec app php artisan migrate --seed

You should receive output that is similar to the following:

Output
Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (124.20ms) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (121.75ms) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (112.43ms) Migrating: 2020_11_18_165241_create_links_table Migrated: 2020_11_18_165241_create_links_table (61.04ms) Migrating: 2021_07_09_122027_create_link_lists_table Migrated: 2021_07_09_122027_create_link_lists_table (112.18ms) Seeding: Database\Seeders\LinkSeeder Seeded: Database\Seeders\LinkSeeder (84.57ms) Database seeding completed successfully.

In the next chapter of this series, you’ll learn in more detail how to query database records with Eloquent.

This tutorial is part of an ongoing weekly series about Laravel Eloquent. You can subscribe to the Laravel tag if you want to be notified when new tutorials are published.