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.
LinkList
ModelTo 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:
<?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:
<?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 Listdescription
: a string representing the description of a Listslug
: a unique, short string based on the title, typically used to create user-friendly URLsIn 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:
<?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:
<?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
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:
<?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:
<?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.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Eloquent is an object relational mapper (ORM) that is included by default within the Laravel framework. In this project-based series, you’ll learn how to make database queries and how to work with relationships in Laravel Eloquent. To follow along with the examples demonstrated throughout the series, you’ll improve a demo application with new models and relationships. Visit the series introduction page for detailed instructions on how to download and set up the project.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!