laravel 5.7.* model relations explained -...

101
Laravel 5.7.* Model Relations Explained A DETAILED DISCUSSION OF MVC, COMPOSER, MIGRATIONS, DATABASE RELATIONSHIPS, RESOURCE CONTROLLERS AND FAKER, ADVANCED CRUD, ONE TO ONE, ONE TO MANY, MANY TO MANY, HAS MANY THROUGH, AND POLYMORPHIC RELATIONSHIPS IN LARAVEL 5.7.* Sanjib Sinha Laravel 5.5.* Model Relations Explained Copyright © 2018 by Sanjib Sinha This work is subject to copyright. All rights are reserved by the Writer, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. Regarding re-publication of this book, you may contact the author, here, Sanjib Sinha, at this email address: [email protected] While the advice and information in this book are believed to be true and accurate at the date of publication, the author cannot accept any legal responsibility for any errors or omissions that may be made. The author makes no warranty, express or implied, with respect to the material contained herein.

Upload: others

Post on 05-Aug-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Laravel 5.7.* ModelRelations Explained

A DETAILED DISCUSSION OF MVC, COMPOSER, MIGRATIONS,DATABASE RELATIONSHIPS, RESOURCE CONTROLLERS AND

FAKER, ADVANCED CRUD, ONE TO ONE, ONE TO MANY, MANY

TO MANY, HAS MANY THROUGH, AND POLYMORPHIC

RELATIONSHIPS IN LARAVEL 5.7.*

Sanjib Sinha

Laravel 5.5.* Model Relations Explained Copyright © 2018 by Sanjib Sinha

This work is subject to copyright. All rights are reserved by the Writer, whether the whole or part of the material

is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on

microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer

software, or by similar or dissimilar methodology now known or hereafter developed.

Regarding re-publication of this book, you may contact the author, here, Sanjib Sinha, at this email address:

[email protected]

While the advice and information in this book are believed to be true and accurate at the date of publication, the

author cannot accept any legal responsibility for any errors or omissions that may be made. The author makes no warranty,

express or implied, with respect to the material contained herein.

Page 2: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Development Editor: Amitakkhar Deb, 12REACH

Cover designed by Kaberi Sinha

Any source code or other supplementary material referenced by the author in this book is available to readers on

GitHub via the book's product page, located at https://github.com/sanjibsinha/laravelmodelrelations

About the Author

Sanjib Sinha is a certified “.NET Windows and Web Developer”, specializing in

Python, Security Programming and PHP; he won Microsoft's Community Contributor Award in

2011. As a published author, Sanjib Sinha has written “Beginning Ethical Hacking with Python”,

and “Beginning Laravel” for Apress.

AcknowledgmentsI wish to record my gratitude to my wife, Kaberi, for her unstinting support and

encouragement in the preparation of this book.

I am extremely grateful to Mr. Amitakkhar Deb, Lead Development Editor of

12REACH, for his numerous valuable suggestions, complementary opinions and thorough

thumbing and the whole 12REACH team for their persistent support and help.

Page 3: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

In the preparation of this book, I have had to consult numerous open source

documentation and text-books on a variety of subjects related to PHP, I thank countless authors

and writers who have written them.

Who should read this book?This book is intended for Intermediate PHP developers. Advanced users may also

find this book helpful for some quick references. You should have a good grasp of object-

oriented PHP7 programming knowledge.

What you will Learn from this Book and The Application we are going to build

Apparently, this contents management application does not look very complicated,

however, the relations are quite tangled and we will try to understand these relations through

Laravel’s Model relations and Eloquent ORM; at the end, we will also learn how resourceful

controllers play vital roles in such model relations.

How an article is related to a particular user and how from the article table we can

fetch the data of that particular user or writer? An article uses many tags, but how we can access

those tags from that article itself? An article may have many comments. Who has written those

comments? Of course users. And these users have their own profiles which tell us about them,

including name, email, city, and a short biography. Each profile page may have multiple

comments written by other users about that profile-holder user. So we have comments table for

both – articles and profiles. Can we use one single comment table to serve them both? Yes, we

can do! A polymorphic relationship allows us to do that.

Page 4: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

These questions are all very tricky, however, laravel model relations, Eloquent ORM,

and resourceful controllers has solved these problems quite easily. As we progress we will learn

one-to-one, one-to-many, many-to-many, has-many-through, and polymorphic relationships with

concrete examples. By the way, we will also learn some major tricks of Laravel (like resource

controller and views) that makes your development experience more pleasant.

Finally, what we will see in this application? A user have many articles. When you

open the application, you will find the series of article titles. Each title will show who is the

writer of it. If you click on each title, you can read the full article. If you click on the user name,

you will see the user’s profile and all the articles he/she has written. The same rule is applied for

the tags. Each tag may belong to many articles. Again any article may belong to many tags. So

each article shows many tags. In the user profile we will see which tags he/she has used often

and so on. In addition to that, we have comments on both pages, with a link to the users who

have written them.

All together, it’s an interconnected contents management application that handles

many complex queries effortlessly.

Contents1. What is MVC Pattern

2. How MVC Pattern Works

3. Composer and Laravel

3.1 Composer’s role in Effective Patterns

Page 5: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

3.2 Composer and Separation of Concerns

3.3 Laravel Homestead, Virtual Box and Vagrant

3.4 Installing Virtual Box and Vagrant

3.5 Installing Homestead Vagrant Box

3.6 Homestead installation and configuration

4. How to start our Application

5. How Migrations work in Laravel

5.1 Model Relations for Application

5.2 Controllers and Views

5.3 Creating Views to show Relationships

5.4 One To One

5.5 One to Many

5.6 Dependency Injection and Separation of Concerns

5.7 Many to Many

5.8 Has Many Through

5.9 Polymorphic Relations

Page 6: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

6. Resource Controllers and Eloquent Magic

6.1 Model and Controller

Where to go from here

Last but not the Least

1. What is MVC PatternImplementing user interfaces successfully is our main goal when we build a web

application. How we could do this in a decent way, keeping ‘separation of concerns’ principle

intact? Model View Controller (MVC) architecture is the answer. It is commonly used and a very

popular choice. The ‘separation of concerns’ principle usually separates the application logic

from the presentation layers. Likewise, it makes the application more flexible; iterations, which

is the core part of our logic flow becomes easier. Quite naturally, our application becomes more

flexible, modular, and reusable.

Let us imagine a social networking application where you want to view a user’s page.

You may click a link and heads out straight to the page where every details are being shown.

Page 7: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Imagine a simple URI like this: https://example.com/home/index/username. Here you may

imagine that ‘home’ is the controller, ‘index’ is the method and in the ‘username’ section you can

even pass an ID. Apparently, it looks simple; you use home controller calling index method and

pass an user name or ID. It takes you to the user’s page.

How we can make our ‘app’ work through an MVC model?

As you guess, we will get the user’s data from a database. Our Model defines what

data our application should contain. So, it is Model’s job to interact with the database. Now, a

user’s database will constantly evolve, changes will take place, the user will give her updates. If

the state of this data changes, the Model will usually notify the View. If different logic is needed

to control the View, the Model notifies the controller.

Keeping our social media app in mind, the model would specify what data the list

item should contain – first name, last name, location, etc.

Compared to the functions of Model and Controller, the work-flow of View consists

of simple tasks. It would only define how the list is presented to another user. It will also receive

the data from Model to display.

The role of Controller is critical. It contains logic that updates the Model and

sometimes View in response to input from the users of the app. Usually, in other social media

app almost same thing happens. The app could have input form-boxes to allow us to post or edit

or delete the data. The actions require the Model to be updated, so the input is sent to the

Controller, which then acts upon the Model and the Model then sends the updated data to the

View. Now, this View can be manipulated in different manner – you can use your layout template

Page 8: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

engine. In some cases, Controller can handle these tasks independently without needing to

update the Model.

Actually, we have seen this pattern before. Our data model uses some kind of

database; most probably MySQL in LAMP technology. In such cases, our controller’s code is

written in PHP and in View part we have used the combination of HTML and CSS.

2. How MVC Pattern WorksImagine a portal, where user interacts with the user interface in some way: clicking a

link or submitting a form. Now, the controller takes the charge and handles the user input event

from the user interface. Consequently, the controller notifies the Model of the user action.

Usually, the state of Model gets changed. Suppose, the Controller updates the status of the user.

It interacts with the Model and the model has no direct knowledge of the view. It passes data

objects to Controller and then Controller generates the contents gathering that dynamic data.

For its simple iterations and the principle of separation of concerns, MVC pattern is

often found in web application.

Now, the MVC pattern can be interpreted in different ways: a section thinks that the

actual processing part is handled by the Model and the Controller only handles the input data. In

such interpretation, the ‘input-processing-output’ flow is represented by ‘Controller-Model-

View’; here the Controller interprets the mouse and keyboard inputs from the user.

Therefore, a Controller is responsible for mapping end-user action to application

response, whereas a Model’s actions include activating business processes or changing the state

Page 9: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

of the Model. The user’s interactions and Model’s response decide how a Controller will respond

by selecting an appropriate View.

We can summarize the whole section by this conclusion: an MVC pattern must have

a minimum of three components, each of which performs their own responsibilities. Now many

MVC frameworks add extra functionalities such as Data Access Object (DAO) to communicate

with the relational database.

In normal circumstances, the data flow between each of these components carry out

their designated tasks; however, it is up to you to decide how this data flow is to be implemented.

In the framework we are going to build, the data is pushed by the Controller into the View. At the

same breath, the Controller keeps manipulating data in the Model. Now the question is, who is

the real processing part? Model or Controller? Does the Controller play the intermediary role and

behind the scene, the Model actually pulls the strings? Or, the Controller is the actual processing

unit controlling the database manipulations and representation simultaneously?

It does not matter as long as the data flows, and the pattern works. In our framework,

we will implement in a way, so that the Controller will do processing job, controlling Model and

View simultaneously.

While building the MVC framework, we will note the following:

We will keep a separate Data Access Object (DAO) and our Model will handle the

DAO as appropriate. Therefore, all SQL statements can only be generated and executed in one

place. Data validation and manipulation can be applied in one place – Model. The Controller will

handle the request and response cycle, taking the input from the user interface and updates

Page 10: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Model accordingly. As it gets the green signals from the Model, it sends the response to the

View. The View is only aware of one thing – display.

3. Composer and LaravelUsing Composer, installation of Laravel is very easy. However, I would like you to

have a basic understanding of Composer; how it works, why it is indispensable in any type of

PHP development, including Laravel.

If you plan to design object-oriented software, it is not a simple task. Designing a

reusable object-oriented software is even harder. How can a dependency management system

like Composer make this task easier? Let us try to understand that in this chapter.

3.1 Composer’s role in Effective Patterns

I would like to start this section by quoting from the famous book “Design Patterns,

Elements of Reusable Object-Oriented Software” by the “Gang of Four” Erich Gamma, Richard

Helm, Ralph Johnson and John Vlissides.

The book starts with this meaningful discussion - “Designing object-oriented

software is hard, and designing reusable object-oriented software is even harder. You must find

pertinent objects, factor them into classes at the right granularity, define class interfaces and

inheritance hierarchies, and establish key relationships among them. Your design should be

specific to the problem at hand but also general enough to address future problems and

requirements. You also want to avoid redesign, or at least minimize it. Experienced object-

oriented designers will tell you that a reusable and flexible design is difficult if not impossible to

Page 11: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

get "right" the first time. Before a design is finished, they usually try to reuse it several times,

modifying it each time.

Yet experienced object-oriented designers do make good designs. Meanwhile, new

designers are overwhelmed by the options available and tend to fall back on non-object-oriented

techniques they've used before. It takes a long time for novices to learn what good object-

oriented design is all about. Experienced designers evidently know something inexperienced

ones don't. What is it?”

This introductory paragraph ends with a question mark. I will always encourage you

to read the book itself; a must read, however, at the same time I would like to start our discussion

keeping this question mark in the background - “Experienced designers evidently know

something inexperienced ones don't. What is it?”

I have no doubt that “Single Responsibility Principle” or SRP is one of the more

important concepts in object-oriented design, which experience designers know and follow from

the beginning, and the inexperienced designers do not understand that core concept. And, it

makes a real big difference. Laravel also uses this principle very heavily.

Let us start with the core concept that sits right in the heart of SRP – classes should

not do far too many things. Yes, a class can do many things for an object; but, you cannot abuse

that power. It could cause unexpected harm to the organization of code in general. When a gentle

tap with a hammer works fine, why strike the nail with a huge force? It may have a boomerang

effect.

Page 12: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Thinking before and designing properly is entirely a different activity than getting the

software to work. We always try to make our code work fast; keeping no rooms for organization

and cleanliness. It’s a wrong approach and it causes a lot of harm to the effectiveness as a whole.

When the program works, we are done; we forget that maintaining a separation of concerns is as

important an activity in our programming design as it is in the running program. The real

problem starts with the overstuffed classes that are burdened with too many tasks. They are not

"decoupled units" with single responsibility principles. Large numbers of small, single-purpose

classes are like many caskets with well-defined-labels; this type of organization makes our tasks

easier to find the appropriate things than dumping all staff in one single casket.

So we need many small classes, not a few large ones staffed with too many tasks.

Each small class should have single responsibility encapsulated in a way so that they have a

single reason to change. They will also communicate with a few other small classes to get the

desired result. In the final chapter, we will build an MVC patterned framework keeping these

single responsibility principles and separation of concerns intact.

Hopefully, you have started guessing how Composer fits into this big picture where

we are going to learn a framework like Laravel. Actually, that is the reason why every good PHP

framework such as Symfony or Laravel depends on this dependency management system. What

is more, Composer has now become the standard of dependency management.

You can always use Composer project wise; although, it is always good to install it in

your system globally. You can run it anywhere in your system. Let us install it globally. For any

Debian based Linux distribution it is simple. If you are a Windows user, it’s better to install

oracle JAVA SE Development Kit, Netbeans Tesxt Editor and XAMPP.

Page 13: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

In Windows 7 and onwards, you can also download Composer installer, just run the

“EXE” file and, voila, it will be installed globally in your system. After that you can use

Composer anywhere to install any package.

JAVA SE Development Kit is available in Oracle web portal. This is extremely

important for Netbeans text editor. I won’t press you to use Netbeans, if you are happy with

Sublime or any other IDE, stick to that.

Image 3.1 – JAVA SE Development Kit in Oracle web portal

Page 14: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

For this book, I have used Windows 7 in my virtual machine and installed JAVA SE

Development Kit, Netbeans and XAMPP. As an operating system I use Ubuntu, as I have been a

hardcore Linux user since I have started using Computer. Here is an image of virtual Netbeans

and XAMPP, running on my virtual machine.

Image 3.2 – Netbeans and XAMPP Control Panel running parallel

in Virtual Windows 7

If you want to use Laravel in Ubuntu, that is also easy. Keeping that in mind, I have

also shown how to install Laravel in Ubuntu using Composer. In Ubuntu, you need to install

Composer first.

// code 3.1

Page 15: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

//Installing Composer and use it globally in the system

ss@ss-Lenovo-3000-G530:/$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

ss@ss-Lenovo-3000-G530:/$ php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installerverified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

Installer verified

ss@ss-Lenovo-3000-G530:/$ php composer-setup.php

All settings correct for using Composer

Downloading...

Composer (version 1.6.5) successfully installed to: //composer.phar

Use it: php composer.phar

ss@ss-Lenovo-3000-G530:/$ sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer

All settings correct for using Composer

Downloading...

Composer (version 1.6.5) successfully installed to: /usr/local/bin/composer

Use it: php /usr/local/bin/composer

Page 16: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

In the first half, I have downloaded the Composer installer in my root directory and I

have verified the product. After that I have chosen the directory “usr/local/bin/composer” to set

it up so that I can use it globally.

Next, I will check whether it works or not.

In “var/www/html” directory I have created a folder called “test-composer” and

initialize the newly-installed composer into it.

// code 3.2

ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$ composer init

Welcome to the Composer config generator

This command will guide you through creating your composer.json config.

Package name (<vendor>/<name>) [root/test-composer]: ss/mvc

Description []: mvc

Author [, n to skip]: n

Minimum Stability []: stable

Package Type (e.g. library, project, metapackage, composer-plugin) []: project

License []:

Page 17: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]? y

Search for a package: cocur/slugify

Enter the version constraint to require (or leave blank to use the latest version):

Using version ^3.1 for cocur/slugify

Search for a package:

Would you like to define your dev dependencies (require-dev) interactively [yes]?

Search for a package:

{

"name": "ss/mvc",

"description": "mvc",

"type": "project",

"require": {

"cocur/slugify": "^3.1"

},

"minimum-stability": "stable"

}

Do you confirm generation [yes]? Y

Page 18: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

I have successfully created a “composer.json” file inside the test folder. Now, I can

install and run Composer locally in that particular folder by using "global" composer command.

// code 3.3

ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$ composer install

Loading composer repositories with package information

Updating dependencies (including require-dev)

Package operations: 1 install, 0 updates, 0 removals

- Installing cocur/slugify (v3.1): Downloading (100%)

Writing lock file

Generating autoload files

ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$

Composer has been successfully installed locally. We can check the directory listing.

// code 3.4

ss@ss-Lenovo-3000-G530:/var/www/html/test-composer$ ls

composer.json composer.lock vendor

Now, you can use the “slugify” object to convert your any string into a slug. It can

provide a good support to our MVC patterned framework. Not only that, we need to leverage the

Page 19: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

resources of other useful packages, available in “Packagist – The PHP Package Repository”

(https://packagist.org/).

Solving every problem from first principles is not a good idea at all. Effective

patterns always reuse solutions that have worked for them in the past so that we can use it again

and again. The combination of Composer and other PHP Packages solves a great problem that

we have faced over the time.

There are recurring patterns of classes and communicating objects in many object-

oriented systems, however, the availability of these patterns was extremely scarce in the past. We

didn’t do enough job of recording experiences for others to do. If they did, there would not have

been a good common resource to pull recurring patterns from it.

Using the combination of Composer and Packagist now we can not only find a

package, we can also find all its dependencies and related library, meta package, and composer-

plugin. Even PEAR packages are there to assist in your project’s decision-making process.

3.2 Composer and Separation of Concerns

One of the major design principles is “separation of concerns”. Composer helps us to

achieve that software design principle quite easily. This principle reminds us of two main factors

– the first one is, every class should have a single responsibility. The second one is, the single

responsibility of any class should be encapsulated by that class itself. Let us see how it works.

Before going to write the codes, let us design it properly. At the end of this book, we

will build an MVC framework from the scratch. Keeping that in our mind, let me create a folder

first in my “/var/www/html” directory. Let us name that folder “mymvc”.

Page 20: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Let us separate the output from our application logic. So we create two folders “src”

and “public” in our “mymvc” application. In “public” folder, we have three folders - “css”, for

keeping our CSS style files; “js” for JavaScript files; and “images” for keeping images. We also

have an “index.php” file in our “public” folder as it will act as an entry point to our MVC web

application.

Now, let us think about the “src” (it actually represents the word “source” or

“resource”) folder. We must have “controllers”, “models”, and “views” folders for keeping our

related classes. I have created another special folder called “kernel”, to keep special classes to

maintain the separation of concerns. We will also have “init.php” file for initializing the

application logic.

Let us see, how using Composer, we can maintain this separation of concerns.

The “composer.json” file looks like this:

// code 3.5

//composer.json

{

"autoload": {

"psr-4": {

"App\\": "src/",

"Controller\\": "src/controllers",

Page 21: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

"Kernel\\": "src/kernel",

"Model\\": "src/models",

"View\\": "src/views"

}

}

}

The file structure is quite simple to follow. Now, we can run the Composer and create

the “../vendor/autoload.php” file.

The entry point of our application, that is, the “index.php” file must require this

“init.php” file so that we can create an instance of our “App” there.

The code of “index.php” file looks like this:

// code 3.6

//public/index.php

<?php

require_once '../src/init.php';

use Karnel\Apply as Apply;

$app = new Apply;

Page 22: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Here, “$app” represents our application instance. And the code of “init.php” file

looks like this:

// code 3.7

//karnel/init.php

<?php

require_once '../vendor/autoload.php';

use Kernel\Error as Error;

$error = new Error;

We want to display errors on our every production page to follow the flow correctly.

So, we keep a separate “Error” class for that in our “kernel” folder. In some cases,

“display_errors” modules are commented out in “php.ini” file. This “$error” instance will also

help us understand the separation of concerns principle.

The code of “Error.php” page is like this.

// code 3.8

//src/Kernel/Error.php

<?php namespace Kernel;

Page 23: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

/*

* To display PHP errors on every page

*/

class Error

{

public function __construct() {

ini_set('display_errors', 1);

ini_set('display_startup_errors', 1);

error_reporting(E_ALL);

}

}

This “Error” class could be a perfect example of single responsibility ut, but, it

violates the separation of concerns principle.

Why? It is because, with each initialization, a part of our application logic directly

hits the output. The same thing is true for our application instance. Let us see the “Apply” class

code.

// code 3.9

//src/Kernel/Apply.php

Page 24: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

<?php

namespace Kernel;

/*

* This Kernel Apply class defines the types of our framework app object

*/

class Apply

{

public function __construct() {

$url = $this->parsingURL();

}

public function parsingURL() {

if (isset($_GET['url'])) {

$string = filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL);

$url = explode('/', $string);

Page 25: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

print_r($url);

}

}

}

Now, if we type in the browser like this:

http://localhost/mymvc/public/hello/world/from/sanjib

We get an output like this:

Array ( [0] => hello [1] => world [2] => from [3] => sanjib )

There are other mechanisms like using the “.htaccess” file in our “public” folder; so

that we can parse the URL in our “Apply” class. In such cases, the code of “.htaccess” file looks

like this:

// code 3.10

//public/.htaccess

Page 26: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Options -MultiViews

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.+)$ index.php?url=$1

For this chapter, let us concentrate on the "output", which I have got on my browser.

It is an array where the $url[0] is “home”. The $url[1] is "index" and so on. Now, we can make

one thing out of this output. We can make this “home” as our primary controller; it could be

“home” controller and the “index” could be its method. What is more, we can pass other array

values as the parameters of the “index” method.

As I have structured the file and used the concept of "namespace", it is quite clear

that Composer helps us allow to use namespace and file structure to achieve the separation of

concerns principle. While making the controller classes we should take care of one thing – the

controller should not know where the data comes from and where it goes. It should not hit the

database directly. It should not be tightly coupled with the output. It should use one or more

"contracts" so that it remains "loosely coupled" to achieve the principle of "separation of

concerns".

Page 27: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

As we progress, we will find more examples. We will see how Composer helps us

apply the principle of "separation of concerns". Laravel is a classic example of this principle.

Well, in the coming chapters, we will learn those key concepts used in Laravel.

3.3 Laravel Homestead, Virtual Box and Vagrant

If you have already installed latest Laravel, you can skip this section entirely and

jump to the chapter 4.

Laravel Homestead is an official, pre-packaged Vagrant box. An absolute beginner

may find that concept a little bit quirky. You can imagine it as a scaffold platform or magical box

that contains everything for building Laravel applications on your local machine. I encourage

you to search about learning Laravel Homestead package. If you have Laravel Homestead

installed, you need not worry about the latest PHP and Linux versions. It also comes with a web

server and all types of server software that you need to develop some awesome PHP applications

besides Laravel!

Before running Laravel/Homestead you must have Virtual Box 5.x,

// code 3.11

https://www.virtualbox.org/wiki/Downloads.

You also must install Vagrant.

http://www.vagrantup.com/downloads.html.

3.4 Installing Virtual Box and Vagrant

Page 28: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

The first question that comes to our mind is: why do we need a virtual box when we

have a default operating system in place? There are several reasons. The most important reason

is: in a virtual box we can play with any operating system without any fear of messing it up, and

breaking it up. There is every possibility that while testing any tool we could break a system. I

encourage you to do that in a virtual machine; not on your default OS. Since it is a virtual

machine you can go ahead with any experimentation. Test everything that comes to your mind.

Another great reason of using virtual box is the safety. When you visit a web site you might

consider it to be safe but in reality it could not be so. But nothing matters in the case of virtual

box. It is not your original machine with confidential data. Visiting unsafe web site is not

annoying any more.

The Oracle Virtual Box official web site offers plenty of download options. You can

choose any one of them. According to your OS you go to the “download” section and see what is

available for you. From the next image you will have an idea how you can proceed further.

Virtual Box is very easy to install. Whatever your OS is – Mac OS X, or Windows or

Linux, you can install it. First you need to know about your Operating System itself. It could be

either 32 bit or 64 bit architecture. In any Linux distribution it is extremely easy to learn. Just

open up the terminal and type: “uname -a”.

The terminal will spit out some vital information that includes all data regarding the

current default system; what type of system architecture is this.

As in my case it is “x86_64” which stands for 64 bit. In the Virtual Box official

download page for all Linux distribution you first download the required packages and then

Page 29: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

install it according to the nature of your OS. For Red Hat, Fedora or any Linux distribution

belonging to that category you will notice that the last extension is “.rpm”. In that case you can

move to the Virtual Box folder and issue commands like “rpm -i” or “yum install” in case you

run Red Hat or Fedora.

But there are more simple methods to install Virtual Box.

For the absolute beginners it is much helpful to run “UBUNTU” Linux distribution

as your default OS. You can install Virtual Box from the software center directly without opening

up the terminal or issuing any command.

“UBUNTU” software center has many categories. One of them shows the “Installed”

software. You may not find it there by default. In that case it is extremely easy to install. You can

just type “Virtual Box” on the search text box and it will pop up. Move ahead and press the

installation button and it will get installed in your system. Installing vagrant is also easy. Go to

the official web site and download it according to your operating systems. Installation process is

also easy. For Ubuntu just extract the content any where and install it according to the procedure

mentioned in the site.

Through Virtual Box you can run different operating systems on your machine.

Having installed Virtual Box you can issue ‘vagrant -v’ command on your terminal

and the message will pop up as: ‘vagrant 1.8.5’. It’s running.

Now it’s time to install Laravel/Homestead.

3.5 Installing Homestead Vagrant Box

Page 30: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Once you have installed Virtual Box and Vagrant, you can add ‘laravel/homestead’

box to your vagrant box using this command on your terminal.

// code 3.12

vagrant box add laravel/homestead

It will take a few minutes from one hour to fifteen minutes, depending on your

Internet speed.

3.6 Homestead installation and configuration

Next you can install Homestead by cloning homestead repository to your

‘/home/Homestead’ folder using this command.

// code 3.13

git clone https://github.com/laravel/homestead.git Homestead

It’ll take a few seconds. Next you need to initialize your homestead and create the

configuration file. To do that, you need to stay inside the Homestead folder.

// code 3.14

bash init.sh

Page 31: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Next run a ‘ls -la’ command to find out the hidden ‘./homestead’ directory. Type

‘cd ./homestead’ command to enter into it and run ‘ls -la’ command again. You’ll find a file

called ‘Homestead.yaml’. You may consider this file as the brain of your ‘laravel/homestead’

local developmental environment.

Trough this file you can instruct the local web server. You can mention the path of

your project root. You can decide the name of your local application. I think it’s always wise to

adopt the same name that you are going to use in your production environment. Suppose your

final application in the production level will be named ‘www.example.com’ in that case it’s good

to use the same name locally so that you can type http://example.com in your browser to test the

application locally.

Before editing ‘Homestead.yaml’ file you can do two things more. First check your

‘laravel/homestead’ version and if necessary run this command – ‘sudo composer global require

laravel/homestead:v2.0.8’. Always try to keep the latest one. Check it in internet. Next you can

run this command also – ‘export PATH="~/.composer/vendor/bin:$PATH"’. It’ll help you to run

‘homestead’ command from any where on your system.

Now you need to edit the ‘Homestead.yaml’ file for keeping two major things in

place. The first is the provider. Run ‘sudo gedit Homestead.yaml’ command to open up the file

on the text editor. By default you’d see ‘provider: virtualbox’ in your file. So you need not

change this. Next you check this part.

The second part is very important. By default the ‘Homestead.yaml’ file comes up

with this folders and sites structure.

Page 32: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

// code 3.15

folders:

- map: ~/Code

to: /home/vagrant/Code

sites:

- map: homestead.app

to: /home/vagrant/Code/Laravel/public

We have already installed laravel at the ‘Code/test/blog’ folder on the desktop. So we

need to add that in this folders and sites section first.

// code 3.16

folders:

- map: ~/Code

to: /home/vagrant/Code

- map: ~Desktop/Code/test/blog

to: /home/vagrant/ Desktop/Code/test/blog

sites:

- map: homestead.app

to: /home/vagrant/Code/Laravel/public

- map: test.app

Page 33: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

to: /home/vagrant/ Desktop/Code/test/blog/public

The added lines are marked in red. Look I have mentioned the full path. Wherever you keep your

laravel application, you need to mention the full path. So, we have almost come to the close.

You’ve probably noticed that we‘ve named our application ‘test.app’. Next you need

to add the "domains" for your local sites to the `hosts` file on your machine. The ‘hosts’ file will

redirect requests for your Homestead sites into your Homestead machine. On Mac and Linux,

this file is located at ‘/etc/hosts’. Open this file in your text editor.

// code 3.17

sudo gedit /etc/hosts/

Generally it comes up with two lines on the top. You must add your ‘test.app’ after

the two lines.

// code 3.18

127.0.0.1 localhost

127.0.0.1 hagudu-H81M-S1

192.168.10.10 test.app

Everything done you may now fire your vagrant and run your site. Go to the laravel

folder ‘cd /Desktop/Code/test/blog’ and issue this command: ‘vagrant up’.

Page 34: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

The terminal usually looks like below. It may look different depending on your

operating system. It normally takes a few seconds, to fire it up. Give it that time, and next you

can safely type http://test.app on your browser to see the laravel welcome page.

Being on your laravel folder, you may run ‘php artisan serve’ command to run the

same application. In that case, you must type: http://localhost:8000 on your browser. However,

there are lots of differences with the homestead server. When you run homestead you get the

latest php version that is php 7 or the latest version.

So, there are lots of options open to you. If you are a Window user, you can install

JAVA SE Development Kit, Netbeans and XAMPP together to install any distribution of Laravel.

In normal circumstances, XAMPP comes up with the latest php version (currently it is PHP

7.2.9). Because of that, you shouldn’t face any problem and can install Laravel quite easily. Yet,

it is always good not to mess up with your default system; for that, I’d suggest to install Virtual

Box and in that virtual machine you can mock your present system and it is always much safer.

In second case, when you’re using Linux Debian version such as Ubuntu or using

MAC, you can install vagrant and homestead; in that case, you can keep your code anywhere in

your system and work on it.

The third and final option is installation of laravel on Ubuntu directly. To do that, you

must update your PHP version to the latest. It is the easiest among all. I am going to show you

the steps. Just paste those commands on your terminal, and you are done.

First step, remove the old PHP from your system and update it to the current version.

You have to do that, because Laravel always use the latest PHP.

Page 35: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

// code 3.19

$ sudo add-apt-repository ppa:ondrej/php

$ sudo apt-get update

$ sudo apt-get purge php7.0 php7.0-common

$ sudo apt-get install php7.2-curl php7.2-xml php7.2-zip php7.2-gd php7.2-mysql php7.2-mbstring

$ sudo shutdown -r now

After rebooting the system, you can check your PHP version through this command.

// code 3.20

ss@ss-H81M-S1:~$ php -v

PHP 7.2.9-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Aug 19 2018 07:16:12) ( NTS )

Copyright (c) 1997-2018 The PHP Group

Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

with Zend OPcache v7.2.9-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies

Page 36: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Now, we can install Laravel quite easily on the “/var/www/html/” folder. Our next

commands and the consequent output will be like this:

// code 3.21

ss@ss-H81M-S1:~$ cd /var/www/html/

ss@ss-H81M-S1:/var/www/html$ ls

index.html index.php info.php mvc myframework mymvc pdo test

ss@ss-H81M-S1:/var/www/html$ mkdir laravelmodelrelations

ss@ss-H81M-S1:/var/www/html$ cd laravelmodelrelations/

ss@ss-H81M-S1:/var/www/html/blog$ composer create-project --prefer-dist laravel/laravel laravelmodelrelations

- Installing laravel/laravel (v5.7.0): Downloading (100%)

Created project in laravelmodelrelations

Cannot create cache directory /home/ss/.composer/cache/repo/https---packagist.org/, or directory is not writable. Proceeding without cache

Cannot create cache directory /home/ss/.composer/cache/files/, ordirectory is not writable. Proceeding without cache

> @php -r "file_exists('.env') || copy('.env.example', '.env');"

Loading composer repositories with package information

Updating dependencies (including require-dev)

Package operations: 71 installs, 0 updates, 0 removals

- Installing vlucas/phpdotenv (v2.5.1): Downloading (100%)

- Installing symfony/css-selector (v4.1.4): Downloading (100%)

Page 37: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

- Installing tijsverkoyen/css-to-inline-styles (2.2.1): Downloading(100%)

- Installing symfony/polyfill-php72 (v1.9.0): Downloading (100%)

- Installing symfony/polyfill-mbstring (v1.9.0): Downloading (100%)

- Installing symfony/var-dumper (v4.1.4): Downloading (100%)

- Installing symfony/routing (v4.1.4): Downloading (100%)

- Installing symfony/process (v4.1.4): Downloading (100%)

.....…

Image 3.3 – Installation of Laravel 5.7 on Ubuntu Terminal

Page 38: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

It takes a few minute to fetch all the packages; after this fetching-process is over, it

will generate the application key.

// code 3.21

Writing lock file

Generating optimized autoload files

> Illuminate\Foundation\ComposerScripts::postAutoloadDump

> @php artisan package:discover

Discovered Package: fideloper/proxy

Discovered Package: laravel/tinker

Discovered Package: nesbot/carbon

Package manifest generated successfully.

> @php artisan key:generate

...

Now, you can run your newly installed Laravel application through this command:

//code 3.22

ss@ss-H81M-S1:/var/www/html/laravelmodelrelations$ ls

blog

ss@ss-H81M-S1:/var/www/html/laravelmodelrelations$ cd laravelmodelrelations/

ss@ss-H81M-S1:/var/www/html/laravelmodelrelations/laravelmodelrelations$ php artisan serve

Page 39: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Laravel development server started: <http://127.0.0.1:8000>

[Fri Sep 7 06:07:05 2018] 127.0.0.1:54802 [200]: /favicon.ico

Next, open your browser and type http://localhost:8000, it will open up the Laravel.

Image 3.4 – Laravel 5.7 on Ubuntu

Whatever method you adopt, Laravel will finally be launched like this. Now, we are

ready to dig more and turn over the Laravel application to understand how it works.

Our next destination: we will build an advanced content management system such as

Wordpress where an administrator can add more users, profiles, articles, tags and comments and

Page 40: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

relate them with each other using all types of Laravel Model relations. While building this app

we will learn a lots of advanced features involving the latest Laravel 5.7.*.

4. How to start our ApplicationWe will start by issuing this command on our terminal. I am using Ubuntu, but you

can use the same command on XAMPP in Windows or in your MAC. My current Laravel’s

directory is: /var/www/html/laravelmodelrelations/laravelmodelrelations

// code 4.1

$ php artisan make:auth

Authentication scaffolding generated successfully.

It builds a nice interface for registration and log in. Before you can register, you need

to run another command to migrate your users table into your selected database.

// code 4.2

$ php artisan migrate

Migration table created successfully.

Migrating: 2014_10_12_000000_create_users_table

Migrated: 2014_10_12_000000_create_users_table

Migrating: 2014_10_12_100000_create_password_resets_table

Migrated: 2014_10_12_100000_create_password_resets_table

Page 41: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

What it does? It has successfully migrated your users and password resets tables into

your database. Next, if we learn the following command, it will start the local server to run your

application. If you use Homestead or build a workspace in your MAC, it will be slightly

different.

//code 4.3

$ php artisan serve

Laravel development server started: <http://127.0.0.1:8000>

[Tue Sep 18 05:02:21 2018] 127.0.0.1:58112 [200]: /favicon.ico

[Tue Sep 18 05:02:23 2018] 127.0.0.1:58120 [200]: /js/app.js

[Tue Sep 18 05:02:23 2018] 127.0.0.1:58124 [200]: /css/app.css

[Tue Sep 18 05:02:23 2018] 127.0.0.1:58128 [200]: /favicon.ico

[Tue Sep 18 05:02:32 2018] 127.0.0.1:58138 [200]: /favicon.ico

Since our local server is running, our new application will pop up with the the login

and register link on the top right side. You can register and see that it works. However, we are

going to use ‘Faker’ and Database seeder to populate our each tables so that we don’t have to

manually insert a huge amount of data. So our next step will be to create few Models, Tables,

Controllers and respective Views. Before that we need to understand how migration works and

how we should connect our database to this application.

5. How Migrations work in Laravel

Page 42: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

For the sake of building our application, we start with database. We could have

started with Controllers and Views, or we could have discussed Model; but I thought, database

migration could be a good option, as we have decided to create a completely database-driven

application.

Laravel supports four databases currently: MySQL, PostgreSQL, SQLite and

Microsoft SQL Server. The ‘config/database.php’ file defines MySQL as the default database

connection.

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

You can change it to your requirements. Next, we will have a look at the database

connection set up in that file, so that you have a proper understanding of how Laravel has

designed this beautifully.

'connections' => [

'sqlite' => [

'driver' => 'sqlite',

'database' => env('DB_DATABASE', database_path('database.sqlite')),

'prefix' => '',

],

'mysql' => [

'driver' => 'mysql',

Page 43: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

'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' => '',

'strict' => true,

'engine' => null,

],

'pgsql' => [

'driver' => 'pgsql',

'host' => env('DB_HOST', '127.0.0.1'),

'port' => env('DB_PORT', '5432'),

'database' => env('DB_DATABASE', 'forge'),

'username' => env('DB_USERNAME', 'forge'),

'password' => env('DB_PASSWORD', ''),

'charset' => 'utf8',

'prefix' => '',

'schema' => 'public',

Page 44: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

'sslmode' => 'prefer',

],

'sqlsrv' => [

'driver' => 'sqlsrv',

'host' => env('DB_HOST', 'localhost'),

'port' => env('DB_PORT', '1433'),

'database' => env('DB_DATABASE', 'forge'),

'username' => env('DB_USERNAME', 'forge'),

'password' => env('DB_PASSWORD', ''),

'charset' => 'utf8',

'prefix' => '',

],

],

Here, I would like to add one key concept. Object Relational Mapping or ORM. As

an intermediate PHP user you must already have acquainted with this concept; yet, a few lines

about it won’t hurt us, as Laravel using Eloquent ORM has managed this feature magnificently.

Mapping the application object to the database tables has been one of the greatest challenges;

however, ORM has solved it completely. It provides an interface that converts application objects

to database table records and does the reverse act too.

The next line is also very important:

Page 45: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

'migrations' => 'migrations',

What does this mean? It is a default name of the table used for the projects’ migration

status. You better don’t change it.

The next lines of code are like this:

'redis' => [

'client' => 'predis',

'default' => [

'host' => env('REDIS_HOST', '127.0.0.1'),

'password' => env('REDIS_PASSWORD', null),

'port' => env('REDIS_PORT', 6379),

'database' => 0,

],

],

The ‘redis’ is open source, fast key-value store; among other things, you can manage

cache and session data with it.

Now, after studying the ‘config/database.php’ file, we will see the ‘.env’ file. It’s a

very important file playing a major role in building any awesome application. You will find it in

the root directory; and we are interested about these particular lines.

Page 46: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

DB_DATABASE=laravelmodelrelations

DB_USERNAME=root

DB_PASSWORD=********

By default, the database was ‘homestead’; if you use homestead, it’s okay, otherwise,

you could change it accordingly. I have created a database called ‘laravelmodelrelations’ and

connected it with our laravel application through this ‘.env’ file.

Now, using migration, I can build my database tables and relate them with each other

by some simple default methodology.

Keeping our application logic in our mind, we need to design the tables. Laravel

comes up with two tables: ‘users’ and ‘password-resets’. We need not change the second one.

However, if needed we can change the ‘users’ table. Here, we don’t do that, because we will have

a separate ‘Profile’ table where we will add some more information about a user. Besides, we

need to build other tables as our application demands.

Let us see the ‘database/migrations/create_password_resets_table.php’ file first.

// code 5.1

// database/migrations/create_password_resets_table.php

public function up()

{

Schema::create('password_resets', function (Blueprint $table) {

$table->string('email')->index();

Page 47: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

$table->string('token');

$table->timestamp('created_at')->nullable();

});

}

public function down()

{

Schema::dropIfExists('password_resets');

}

I didn’t paste the whole code for brevity. Let me explain the first chunk: through the

up() method, the ‘Schema’ class creates the table ‘password_resets’, and it is created dynamically

into your database using a closure where ‘Blueprint’ table object takes the charge. Inside this

function, you can add extra functionalities. In

database/migrations/create_password_resets_table.php, we don’t have to do that. Next, we will

build the ‘Profile’ Model and table by issuing a single command.

// code 5.2

$ php artisan make:model Profile -m

Model created successfully.

Created Migration: 2018_09_16_235301_create_profiles_table

Page 48: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Our First Model ‘Profile’ has been created under the ‘app’ folder and next, we should

work on the ‘profiles’ table before run the migration.

Our profiles table comes up with this code:

// code 5.3

public function up()

{

Schema::create('profiles', function (Blueprint $table) {

$table->increments('id');

$table->timestamps();

});

}

In fact, whenever you create a Model with the respective table, it comes up with a

skeleton like this. So for the next tables we won’t repeat this skeleton anymore. We need to add

some more functionalities in this code. So it looks like this:

// code 5.4

public function up()

{

Schema::create('profiles', function (Blueprint $table) {

$table->increments('id');

$table->integer('user_id');

Page 49: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

$table->string('city', 64);

$table->text('about');

$table->timestamps();

});

}

We could have added more functionalities such as ‘first name, last name’ etc.

However, we didn’t do that for brevity. At present, our purpose will be served by only ‘city’ and

‘about’. The interesting part is of course the ‘user_id’. Each profile is connected with a single

user.

Therefore, we can say, each user has one profile and one profile belongs to one user.

We can define that relationship in two respective Models: User and Profile. We will come to that

relationship part later, before that let us create other Models and tables by issuing these

commands one after another.

// code 5.5

$ php artisan make:model Profile -m

Model created successfully.

Created Migration: 2018_09_17_233619_create_profiles_table

$ php artisan make:model Tag -m

Model created successfully.

Created Migration: 2018_09_18_013602_create_tags_table

Page 50: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

$ php artisan make:model Article -m

Model created successfully.

Created Migration: 2018_09_18_013613_create_articles_table

$ php artisan make:model Comment -m

Model created successfully.

Created Migration: 2018_09_18_013629_create_comments_table

$ php artisan make:migration create_article_tag_table --create=article_tag

Created Migration: 2018_09_17_094743_create_article_tag_table

Let me explain what we have done. By using a single command like: ‘php artisan

make:model Comment -m’ you create a Model Comment and at the same time Laravel creates

a related ‘comments’ table for that.

Now, before run the migration, we should plan our application and add

functionalities to our newly created tables. You will find them inside ‘database/migrations’

folder.

// code 5.6

// profiles table

public function up()

{

Schema::create('profiles', function (Blueprint $table) {

Page 51: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

$table->increments('id');

$table->integer('user_id');

$table->string('city', 64);

$table->text('about');

$table->timestamps();

});

}

Now, we have ‘users’ and ‘profiles’ tables and we have a corresponding key that may

attach one profile to one user. So we will add these methods to User and Profile Models

respectively.

// code 5.7

// app/User.php

public function profile() {

return $this->hasOne('App\Profile');

}

Page 52: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

It means one user has one profile and that attaches to the ‘App\Profile’ Model. This is

an one-to-one relationship between User and Profile models. Now it has an inverse in the Profile

model.

// code 5.8

// app/Profile.php

public function user() {

return $this->belongsTo('App\User');

}

It means the same, only in an inverse way. Each Profile should belong to one User

model. To speed up our application, let us add functionalities to other tables and after that define

the relationship accordingly.

Next, we have ‘tags’ and ‘articles’ table. They have a very interesting relationship

between them. Many tags belong to many articles and the inverse is also true. In a simple logic

you can say they have many-to-many relations. So we need a pivot table to maintain that

relationship. Let us see the functionalities of those tables first.

// code 5.9

// tags table

public function up()

{

Page 53: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Schema::create('tags', function (Blueprint $table) {

$table->increments('id');

$table->string('tag');

$table->timestamps();

});

}

Next we have articles table.

// code 5.10

// articles table

public function up()

{

Schema::create('articles', function (Blueprint $table) {

$table->increments('id');

$table->integer('user_id');

$table->string('title');

$table->text('body');

$table->timestamps();

});

}

And, now we have the pivot table ‘article_tag’.

Page 54: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

// code 5.11

// article_tag table

public function up()

{

Schema::create('article_tag', function (Blueprint $table) {

$table->increments('id');

$table->integer('article_id');

$table->integer('tag_id');

$table->timestamps();

});

}

At the same go, we want to create a Role model and ‘roles’ table; because we want

our users should have some privileges such as Administrator, Moderator, and Member.

Therefore, we need a pivot table like ‘role_user’ also.

Let us create them also. The commands are simple.

$ php artisan make:model Role -m

And to create a ‘role_user’ table we issue this command:

$ php artisan make:migration create_role_user_table –create=role_user

Page 55: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

The ‘Role’ model has some methods that allow it to have relationship with ‘User’

model. Let us have a look at the code:

// app/Role.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model

{

protected $fillable = [

'name'

];

public function user() {

return $this->belongsTo('App\User');

}

public function users() {

return $this->belongsToMany('App\User');

}

}

One role may belong to one user and the same time it may belong to many users. So

at the same time, we need to add two methods in our ‘User’ model.

Page 56: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

//app.User.php

public function role() {

return $this->belongsTo('App\Role');

}

public function roles() {

return $this->belongsToMany('App\Role');

}

One user may have one role or many roles at the same time.

Now we need to work on the tables we have just created. First add a ‘name’ column

at the ‘roles’ table.

// database/migrations/roles table

public function up()

{

Schema::create('roles', function (Blueprint $table) {

$table->increments('id');

$table->string('name');

$table->timestamps();

});

}

And at the same time in our pivot table ‘role_user’, we have added two columns -

‘role_id’ and ‘user_id’.

Page 57: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

// database/migrations/roles table

public function up()

{

Schema::create('role_user', function (Blueprint $table) {

$table->increments('id');

$table->integer('role_id');

$table->integer('user_id');

$table->timestamps();

});

}

I have not touched the comment table at present, for one reason. We will work on

that table at the end-phase of building our contents management application. It is because the

comment table will have polymorphic relations with other tables. We will discuss and implement

them at the end.

So we have most of the tables ready to migrate with our database. So we can run the

migration by using this command.

// code 5.12

$ php artisan migrate

Migrating: 2018_09_17_233619_create_profiles_table

Migrated: 2018_09_17_233619_create_profiles_table

Migrating: 2018_09_18_013602_create_tags_table

Migrated: 2018_09_18_013602_create_tags_table

Page 58: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Migrating: 2018_09_18_013613_create_articles_table

Migrated: 2018_09_18_013613_create_articles_table

Migrating: 2018_09_18_013629_create_comments_table

Migrated: 2018_09_18_013629_create_comments_table

Migrating: 2018_09_18_013956_create_article_tag_table

Migrated: 2018_09_18_013956_create_article_tag_table

the list is incomplete

We can see the tables in our ‘phpmyadmin’ interface.

Page 59: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Image 5.1 – Migrated tables in phpMyAdmin

Since, we have migrated our tables, we can populate them with data. It will be a

tedious job to add them manually. Laravel has taken care of that to test your application with

‘fake’ data that can be inserted into your database tables.

To do that, open your ‘database/factory/UserFactory.php’ file. We will use ‘Faker’

object to define the Model and add some fake data into it.

// code 5.13

// database/factory/UserFactory.php

$factory->define(App\User::class, function (Faker $faker) {

return [

'name' => $faker->name,

'email' => $faker->unique()->safeEmail,

'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret

'remember_token' => str_random(10),

];

});

$factory->define(App\Article::class, function (Faker $faker) {

return [

'user_id' => App\User::all()->random()->id,

Page 60: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

'title' => $faker->sentence,

'body' => $faker->paragraph(random_int(3, 5))

];

});

$factory->define(App\Profile::class, function (Faker $faker) {

return [

'user_id' => App\User::all()->random()->id,

'city' => $faker->city,

'about' => $faker->paragraph(random_int(3, 5))

];

});

$factory->define(App\Tag::class, function (Faker $faker) {

return [

'tag' => $faker->word

];

});

$factory->define(App\Role::class, function (Faker $faker) {

return [

'name' => $faker->word

];

});

Page 61: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Let me explain this code a little bit – here, we use ‘faker’ object to populate the

database tables with some dummy data. We will run the database seeds through

‘database/seeds/DatabaseSeeder.php’. The code is like this:

// code 5.14

// database/seeds/DatabaseSeeder.php

public function run()

{

factory(App\User::class, 10)->create()->each(function($user){

$user->profile()->save(factory(App\Profile::class)->make());

});

factory(App\Tag::class, 20)->create();

factory(App\Article::class, 50)->create()->each(function($article){

$ids = range(1, 50);

shuffle($ids);

$sliced = array_slice($ids, 1, 20);

$article->tags()->attach($sliced);

});

Page 62: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

factory(App\Role::class, 3)->create()->each(function($role){

$ids = range(1, 5);

shuffle($ids);

$sliced = array_slice($ids, 1, 20);

$role->users()->attach($sliced);

});

}

We are going to create 10 users, 20 tags and 50 articles. One single command will

handle the whole operations. In the last two factory() method, we have attached ‘tags’ with

‘article’ object, and ‘role’ with ‘users’. While populating the tables with fake data, it will

automatically attach some tags with some articles. The same is true for roles and users.

// code 5.15

$ php artisan migrate:refresh –seed

It will give us a long output where it rolls back the all tables and migrate them

instead. Remember, any time you can issue this command, and it will populate the database

tables with new combination of data. This enhances the testability, because you can always add

Page 63: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

some new columns in a table and run this command and it will roll back the old tables and

migrate the new.

// output

Rolling back: 2018_09_18_013956_create_article_tag_table

Rolled back: 2018_09_18_013956_create_article_tag_table

Rolling back: 2018_09_18_013629_create_comments_table

Rolled back: 2018_09_18_013629_create_comments_table

Rolling back: 2018_09_18_013613_create_articles_table

Rolled back: 2018_09_18_013613_create_articles_table

Rolling back: 2018_09_18_013602_create_tags_table

Rolled back: 2018_09_18_013602_create_tags_table

Rolling back: 2018_09_17_233619_create_profiles_table

Rolled back: 2018_09_17_233619_create_profiles_table

Rolling back: 2014_10_12_100000_create_password_resets_table

Rolled back: 2014_10_12_100000_create_password_resets_table

Rolling back: 2014_10_12_000000_create_users_table

Rolled back: 2014_10_12_000000_create_users_table

Migrating: 2014_10_12_000000_create_users_table

Migrated: 2014_10_12_000000_create_users_table

Migrating: 2014_10_12_100000_create_password_resets_table

Migrated: 2014_10_12_100000_create_password_resets_table

Migrating: 2018_09_17_233619_create_profiles_table

Page 64: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Migrated: 2018_09_17_233619_create_profiles_table

Migrating: 2018_09_18_013602_create_tags_table

Migrated: 2018_09_18_013602_create_tags_table

Migrating: 2018_09_18_013613_create_articles_table

Migrated: 2018_09_18_013613_create_articles_table

Migrating: 2018_09_18_013629_create_comments_table

Migrated: 2018_09_18_013629_create_comments_table

Migrating: 2018_09_18_013956_create_article_tag_table

Migrated: 2018_09_18_013956_create_article_tag_table

this list is incomplete

You may open your ‘phpMyAdmin’ interface on your browser and see how the tables

have been populated with dummy data.

Page 65: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Image 5.2 – Articles table with dummy data in phpMyAdmin

Not that you have to use ‘phpMyAdmin’ always. You can check it on your terminal

also this way:

// code 5.16

mysql> use laravelmodelrelations

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

Page 66: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

mysql> show tables;

+---------------------------------+

| Tables_in_laravelmodelrelations |

+---------------------------------+

| article_tag |

| articles |

| comments |

| migrations |

| password_resets |

| profiles |

| role_user |

| roles |

| tags |

| users |

+---------------------------------+

10 rows in set (0.00 sec)

mysql> select * from users;

It will also give you a long listing of all ten users on your terminal like this:

Page 67: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Image 5.3 – Output of all dummy users on MySQL terminal

Take the third use – the name is: ‘Van Gorczany’ and the email ID is:

[email protected]’. Now through that dummy email you can log in to your

application. Every user has one password and that is ‘secret’.

So we have progressed a lot. We have migrated all tables except the ‘Comment’. We

have dummy data inside the tables, therefore, we can now build the relations and after that we

can use resource Controllers and Views to show how these Model relations work perfectly.

Before proceeding any further we will take a look at how our ‘Home’ page looks

like.

Page 68: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Image 5.4 – Home page of Contents management system

To get the ‘Home’ page of our contents management system (Image 5.4), we slightly

change the default ‘routes/web.php’ page and we also change the code of

‘resource/views/welcome.blade.php’ file.

// code 5.17

// routes/web.php

use App\Article;

use App\Tag;

Page 69: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Route::get('/', function () {

$articles = Article::all();

$tags = Tag::all();

return view('welcome', ['articles' => $articles, 'tags' => $tags]);

});

All we have done is passing ‘articles’ and ‘tags’ separately. Now in the

‘welcome.blade.php’ file, we will get the output.

// code 5.18

// resources/views/ welcome.blade.php

@extends('layouts.app')

@section('content')

<div class="container">

<div class="row">

<div class="col-md-8 blog-main col-lg-8 blog-main col-sm-8 blog-main">

<div class="blog-post">

<ul class="list-group">

@foreach($articles as $article)

<li class="list-group-item">

<h2 class="blog-post-title">

<li class="list-group-item"><a href="/articles/{{ $article->id }}">{{ $article->title }}</a>

</h2>

Page 70: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Written by <a href="/users/{{ $article->user_id }}/articles">{{ $article->user->name }}</a>

</li>

@endforeach

</ul>

</div>

<nav class="blog-pagination">

<a class="btn btn-outline-primary" href="#">Older</a>

<a class="btn btn-outline-secondary disabled" href="#">Newer</a>

</nav>

</div>

<aside class="col-md-4 blog-sidebar">

<div class="p-3">

<h4 class="font-italic">Tags Cloud</h4>

@foreach($tags as $tag)

<font class="font-italic" color="gray"> {{ $tag->tag }}...

@endforeach

</div>

</aside>

</div>

Page 71: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

</div>

@endsection

In the whole code-body, this line attracts our extra attention: Written by <a

href="/users/{{ $article->user_id }}/articles">{{ $article->user->name }}</a>.

The article object directly accesses the user object and gets the respective name

associated with that article from there. How it happens? This is a very good example of one-to-

one relationship. If we click the link, we will reach the user’s page and can watch all the articles

written by him. We need to understand one thing: every article belongs to one user and we can

access that user from that article. Laravel Model relations handle that behind the scene. To make

them properly we have to define them in the Models.

Our next step will be to check all the Models and finally define the relationship

between them so that they can talk to each other in fetching respective data. After that we will

build the resource controllers and views to complete the whole set up.

5.1 Model Relations for Application

Building Models from the scratch is, no doubt, a cumbersome job; however, Laravel

has taken care of this and in a very elegant way. By default Laravel comes up only with the User

model, but you could configure it according to your requirements. We have not done any such

things here to build our application. We have kept it as it is. According to the MVC pattern, the

Model talks to the database, either retrieves data from the database, or inserts, updates data and

Page 72: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

passes it to the Controller. So that, the Controller could pass it to the Views. Reversely, the

Controller takes the inputs from the Views and passes them to the Model to process data.

The User model interacts with the ‘users’ database; and at the same way other models

will work at tandem with the other tables to run this projects management application smoothly.

Behind the curtain, Laravel handles a huge task and this is evident from these simple

expressive functions. Consider few scenarios where a user has many comments. It is obvious, a

user should be able to comment as much as he/she wishes. He/she should be able to comment on

another user’s profile. So the comment object may have polymorphic relationship with two

Model objects: Article and Profile. One user may have many articles too. Now each article may

have many tags and many tags may belong to many articles.

Therefore, we see many types of relations here. Article to user and the inverse (one-

to-one), one user to one profile (one-to-one) one article to many tags (one-to-many), many

articles to many tags (many-to-many) and comments to articles and profiles (polymorphic).

Next we will see the series of code from our Models so that we can associate our

relational ideas with the models.

// code 5.19

// app/Article.php

<?php

namespace App;

Page 73: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

use Illuminate\Database\Eloquent\Model;

class Article extends Model

{

//

protected $fillable = [

'user_id', 'title', 'body',

];

public function user() {

return $this->belongsTo('App\User');

}

public function users() {

return $this->belongsToMany('App\User');

}

public function tags() {

return $this->belongsToMany('App\Tag');

}

}

Page 74: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

I have not included ‘comment’ methods here. We will do it later as we progress.

Initially the Article model has one-to-one and one-to-many and many-to-many relations with

User and Tag models.

// code 5.20

// app/Profile.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Profile extends Model

{

/**

* The attributes that are mass assignable.

*

* @var array

*/

protected $fillable = [

'user_id', 'city', 'about',

];

Page 75: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

public function user() {

return $this->belongsTo('App\User');

}

}

The Profile model has one method ‘user’ that defines the relationship with one User.

We will see later how we can access the profile of any user from the ‘user’ object.

// code 5.21

// app/Tag.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model

{

//

protected $fillable = [

'tag'

];

Page 76: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

public function articles() {

return $this->belongsToMany('App\Articles');

}

}

Next we will take a look at the User model. It is important to note that User model

plays a vital role in this application.

// code 5.22

// app/User.php

<?php

namespace App;

use Illuminate\Notifications\Notifiable;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable

{

use Notifiable;

Page 77: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

/**

* 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',

];

public function profile() {

return $this->hasOne('App\Profile');

}

public function article() {

Page 78: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

return $this->hasOne('App\Article');

}

public function articles() {

return $this->hasMany('App\Article');

}

}

At present, this Model has one component missing. That is Comment. We will add it

in the last stage. From the above code (Code 5.22) it is evident that user has one profile, has one

and many articles.

We have our database tables ready with dummy data. We have made our Models

ready for maintaining the relationship among the objects. So the time has come to make resource

controllers first. After that, we will build our views to test that our application works fine.

5.2 Controllers and Views

PHP database integration is a tedious process. It usually takes five essential steps to

complete the operations. First, it creates a connection. Second, it selects a database; we know

these parts have been defined in the ‘.env’ file. Usually the third step is the most complicated

one: performing database query. Laravel’s Eloquent ORM handles that complicated part in such

a decent manner that you don’t have to worry about it. After that it automatically closes the

connection. As we build our application, we have discussed this topic in great detail.

Page 79: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

There are some advantages of using resource controller. With a single command you

can attach the controller to the associated model. Moreover, you can have every necessary

methods in one place. Let us create the resource Comment controller and associate it with the

Comment model. A single command will serve our purpose.

// code 5.23

$ php artisan make:controller CommentController --resource --model=Comment

Let us look at the newly created Comment controller. Now it is empty. However, it

provides all the essential methods.

// code 5.24

// app/HTTP/Controllers/CommentController.php

<?php

namespace App\Http\Controllers;

use App\Comment;

use Illuminate\Http\Request;

class CommentController extends Controller

{

Page 80: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

public function index()

{

}

public function create()

{

//

}

public function store(Request $request)

{

//

}

public function show(Comment $comment)

{

//

}

public function edit(Comment $comment)

{

//

}

public function update(Request $request, Comment $comment)

{

Page 81: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

//

}

public function destroy(Comment $comment)

{

//

}

}

The index() method may serve the purpose of presenting the home page where you

can show every comment in one place. Through the show() method, you can show each

comment. While showing each comment, you can also show who is the commentator. The

possibility is endless. At the same time, using this resource controller you can create/store,

edit/update and finally destroy the comment object.

So we have created other resource controllers the same way.

// code 5.25

$ php artisan make:controller UserController --resource –model=User

$ php artisan make:controller ArticleController --resource –model=Article

$ php artisan make:controller TagController --resource –model=Tag

Page 82: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Now we can define the routes in our ‘routes/web.php’.

// code 5.26

// routes/web.php

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::resource('users', 'UserController');

Route::resource('profiles', 'ProfileController');

Route::resource('articles', 'ArticleController');

Route::resource('comments', 'CommentController');

Route::get('/users/{id}/articles', 'ArticleController@articles');

Route::get('/', 'ArticleController@main');

I have also changed the main route. You have seen the previous process, where we

had used an anonymous function to return the view. Now we have taken that view under the

main() method of ArticlleController.

5.3 Creating Views to show Relationships

For the first phase of our application we are ready to create the views. We have seen

the ‘welcome.blade.php’ page. For showing articles along with other associated objects we are

going to create three more view pages. They are ‘index.blade.php’, ‘show.blade.php’, and

‘articles.blade.php’.

Page 83: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

First the code of index() method of ‘ArticleController.php’.

// code 5.27

// app/HTTP/Controllers/ArticleController.php

public function index()

{

$articles = Article::all();

$users = User::all();

$tags = Tag::all();

return view('articles.index', compact('articles', 'users', 'tags'));

}

We are passing all articles, users and tags to the index page of all Articles. So that we

can move to other pages easily. We could do that because of the Eloquent ORM. It provides a

very simple yet elegant ActiveRecord implementation for working with your database. Here you

might have noticed that each database table has a corresponding ‘Model’ and I have used that to

get all records such as:

$articles = Article::all();

Here, the Model ‘Article’ has allowed me to query for data in the tables and we have

just passed that data to the Views. The same way, later we will insert the data as well into the

database. Next, we will get those values in the index page, so the code of

‘resources/views/articles/index.blade.php’ is like this:

// code 5.28

Page 84: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

// resources/views/articles/index.blade.php

@extends('layouts.app')

@section('content')

<div class="container">

<div class="row">

<div class="col-md-6 blog-main col-lg-6 blog-main col-sm-6 blog-main">

<div class="blog-post">

<ul class="list-group">

@foreach($articles as $article)

<li class="list-group-item"><h2 class="blog-post-title">

<li class="list-group-item"><a href="/articles/{{ $article->id }}">{{ $article->title }}</a>

</h2>

</li>

@endforeach

</ul>

</div>

<nav class="blog-pagination">

<a class="btn btn-outline-primary" href="#">Older</a>

<a class="btn btn-outline-secondary disabled" href="#">Newer</a>

</nav>

Page 85: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

</div>

<aside class="col-md-3 blog-sidebar">

<div class="p-3">

<h4 class="font-italic">All Writers</h4>

@foreach($users as $user)

<a href="/users/{{ $user->id }}">{{ $user->name }}</a>...

@endforeach

</div>

</aside>

<aside class="col-md-3 blog-sidebar">

<div class="p-3">

<h4 class="font-italic">Tags-Cloud</h4>

@foreach($tags as $tag)

<a href="/tags/{{ $tag->id }}">{{ $tag->tag }}</a>...

@endforeach

</div>

</aside>

</div>

</div>

@endsection

Page 86: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Now, if you type http://localhost:8000/articles, on your browser, it will show this

page:

Image 5.5 – Index page of Articles with users and tags

So, here we find all tables related to the respective Models. You must understand the

naming conventions that Eloquent ORM follows. When we have created the Model in the

Page 87: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

command line, Laravel creates a table for that. By convention, the ‘snake case’ plural name of

the class has been used as the table name. We have seen that for ‘Article’ model, a table ‘articles’

has been created. We didn’t tell Eloquent which table to use for our Article model. By default, it

has chosen the name. First, in the ‘ArticleController’ using the ‘index()’ method, we are start

retrieving data from my database. Here the Eloquent model has acted as a powerful query builder

allowing us to fluently query the database associated with the database.

Instead of writing this code in the main() method:

$articles = Article::all();

We have added constraints to queries, and then use the get method to retrieve the

results this way:

$articles = Article::where('user_id', 1)->orderBy('title', 'desc')->take(5)->get();

It has brought a massive change in our whole structure of the main page

http://localhost:8000. We have used the constraints, where we have chosen the ‘user_id’ as 1, and

ordered the title in descending order. The four records have been taken from the database.

Finally, our main() method of ‘ArticleController’ looks like this:

// code 5.29

// app/HTTP/Controllers/ ArticleController.php

public function main()

{

$articles = Article::where('user_id', 1)->orderBy('title', 'desc')->take(4)->get();

Page 88: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

$tags = Tag::all();

return view('welcome', ['articles' => $articles, 'tags' => $tags]);

}

And in the ‘welcome.blade.php’ we have changed a few portions this way:

// code 5.30

//resources/views/ welcome.blade.php

<ul class="list-group">

@foreach($articles as $article)

<li class="list-group-item">

<h2 class="blog-post-title">

<li class="list-group-item"><a href="/articles/{{ $article->id }}">{{ $article->title }}</a>

</h2>

</li>

@endforeach

</ul>

<aside class="col-md-4 blog-sidebar">

<div class="p-3">

<h3 class="blog-post-title">This week we have showcased only the articles

Page 89: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Written by <a href="/users/{{ $article->user_id }}/articles">{{ $article->user->name }}</a>

</h3>

<strong>Showing the first four results</strong>

<hr class="linenums" color="red">

<h4 class="font-italic">Tags Cloud</h4>

@foreach($tags as $tag)

<font class="font-italic" color="gray"> {{ $tag->tag }}...

@endforeach

</div>

</aside>

Now the home page of our application looks like this:

Page 90: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Image 5.6 – Home page of Contents Management

Application

As you see, the methods like ‘all()’ and ‘get()’ retrieve multiple results. Actually, an

instance of ‘Illuminate\Database\Eloquent\Collection’ has been returned. This Collection class

provides many helpful methods for working with the Eloquent results. In our case, we have

looped over the Collection like an array.

However, the most interesting line in our code is:

<h3 class="blog-post-title">This week we have showcased only the articles

Page 91: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Written by <a href="/users/{{ $article->user_id }}/articles">{{ $article->user->name }}</a>

</h3>

Why this is the most fascinating line of all? The $article object directly accesses the

$user object and get its name property. In the ‘ArticleController’ main() method we have directed

the Article model to select the articles belonged to the user ID 1. And alongside, in the Article

model, we have defined the method this way:

// code 5.31

// app/Article.php

public function user() {

return $this->belongsTo('App\User');

}

It is true that a user has many articles; likewise, it is also true that a particular article

belongs to a particular user. We must understand properly how this relationship works.

5.4 One To One

In the Article Model class, you have probably noticed that relationships have been

defined not only as methods(Code 5.31) but also as powerful query builders. When we define

relationships, the methods provide powerful method chaining and querying capabilities.

{{ $article->user->name }}

Page 92: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

So from Article model, we get the respective user name who has written that

particular article. In the ‘app/User.php’ we have this line of code:

public function article() {

return $this->hasOne('App\Article');

}

The first argument passed to the ‘hasOne('App\Article')’ method is the name of the

related model. And inversely we have seen in ‘app/Article.php’, this line of code:

public function user() {

return $this->belongsTo('App\User');

}

The relationship has been defined in both models and once it has been defined, we

can retrieve the affiliated record using Eloquent’s dynamically defined properties. These

dynamically defined properties in Eloquent are so powerful that accessing relationship methods

become a cakewalk. It seems as if they were defined on the model. We have seen this below

example before.

{{ $article->user->name }}

We couldn’t have the user name from the Article model if Eloquent had not

determined the foreign key of the relationship based on the model name. In this case, the Article

model mechanically assumes that it has a ‘user_id’ foreign key. Here the parent is User model

and it has users table which has a custom ‘$primaryKey’ column (id). So, ‘user_id’ of Article

model matches the ‘id’ of the parent User model.

Page 93: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Based on this assumption, we can take our application’s functionalities further. We

can grab the very first article written by the user using the Article model. Consider this line of

code:

{{ $article->user->find($article->user_id)->article->title }}

It is same as User::find(1)→article→title. However, if we wanted to grab the user’s

first ever written article this way, we should have gone back to the related Controller class and

added this line of code there. The flexibility of Eloquent ORM has allowed us to get the same

result using Article model. So let us change the lower part of the ‘welcome.blade.php’ this way:

// code 5.32

// resources/views/welcome.blade.php

<aside class="col-md-4 blog-sidebar">

<div class="p-3">

<h3 class="blog-post-title">This week we showcase the articles

Written by <p></p>

<a href="/users/{{ $article->user_id }}/articles">{{ $article->user->name }}</a>

</h3>

<strong>Showing the first four results</strong><p></p>

<italic>His first article is:</italic>

<p></p>

<a href="/articles/{{ $article->user->article->id }}">

Page 94: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

{{ $article->user->find($article->user_id)->article->title }}</a>

<hr class="linenums" color="red">

<h4 class="font-italic">Tags Cloud</h4>

@foreach($tags as $tag)

<font class="font-italic" color="gray"> {{ $tag->tag }}...

@endforeach

</div>

</aside>

This change has brought a nice change on the front page of our application. And it

looks like this:

Page 95: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Image 5.7 – Home page of Contents Management

Application

Let us move to the one-to-many relationship. A user has many articles. An article has

many tags. A user has many tags. A user has many comments and so on. These all indicate to a

very important feature of Eloquent relationship management techniques: one-to-many.

On our home page of application we have given the link to all the articles written by

the user. On the top left sidebar of the home page, we can click the user’s name and read his all

articles and the short profile also.

The link given on the home page was like this:

Page 96: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

<a href="/users/{{ $article->user_id }}/articles">{{ $article->user->name }}</a>

The URI is very expressive – it reads like this ‘users/1/articles’. Among all user, the

number one user has written many articles and we want to read them. This could be an ideal

candidate of one-to-many relationship. In that page we can also show the user’s profile too.

6. Resource Controllers and Eloquent MagicWhat we have seen above, until now, is nothing but a representation of typical

“CRUD”. We have created contents by using factories, seeds and Faker. We could have done that

by using Forms through which we could have taken the inputs and insert into our database tables.

The same way we can update our application using forms. I have discussed these features in my

other book, so I have avoided the repetition.

However, “resource controllers” is a concept that plays a very vital role in our model

relations book. Assigning a typical “CRUD” routes to a controller is done through a single line of

code. I have used that command quite often while discussing the model relations. We have

created our Comment controller this way:

php artisan make:controller CommentController --resource

The advantage is, through that controller you can handle all HTTP requests for

“comments” saved by your application (Please refer to the Code 5.24 to see what happens

exactly). You have already seen that this command creates the controller at

“app/Http/Controllers/CommentController.php”. The controller contains all the methods that are

necessary for doing the “CRUD” operations.

Page 97: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Let us see our “routes/web.php” code:

// code 6.1

// routes/web.php

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::resource('users', 'UserController');

Route::resource('profiles', 'ProfileController');

Route::resource('articles', 'ArticleController');

Route::resource('comments', 'CommentController');

Route::get('/users/{id}/articles', 'ArticleController@articles');

Route::get('/', 'ArticleController@main');

We have used four resource controllers here (Code 6.1). This is called “resourceful

routes” to the controller. We could have written the resourceful routes in this way too:

// code 6.2

// routes/web.php

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::resources([

'users' => 'UserController',

'profiles' => 'ProfileController',

'articles' => 'ArticleController',

'comments' => 'CommentController'

Page 98: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

]);

//Route::resource('users', 'UserController');

//Route::resource('profiles', 'ProfileController');

//Route::resource('articles', 'ArticleController');

//Route::resource('comments', 'CommentController');

Route::get('/users/{id}/articles', 'ArticleController@articles');

Route::get('/', 'ArticleController@main');

I have registered many resource controller at once by passing an array to the

‘resources’ method. It’s working the same way it worked before.

Whether it is a single route declaration or passing an array to the resource, it creates a

variety of actions on the resource. It also creates methods for each of these actions. The

advantage of creating resource controllers is it gives you enough information about the HTTP

verbs and URI-s they handle (Table 6.1). Consider the Article Controller we have created for our

application. Inside that controller, we have seen all these actions and route names. In our

‘routes/web.php’ we have incorporated all those Verbs and URI-s into one single word -

‘resource’. We could have got the same effects by writing them separately, however, it would

take plenty of space, nothing else. In some special cases, we need to do that. But, in most cases,

resourceful controllers serve our purposes.

Verb URI Action Route Name

GET /articles index articles.index

GET /articles/create create articles.create

Page 99: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

Verb URI Action Route Name

POST /articles store articles.store

GET /articles/{article} show articles.show

GET /articles/{article}/edit edit articles.edit

PUT/PATCH /articles/{articles} update articles.update

DELETE /articles/{articles} destroy articles.destroy

Table 6.1: The magic of resource controller

6.1 Model and Controller

While studying the model relations, you have probably found that model and

controller have a very close relationship and they are interdependent. Without the presence of a

model you cannot leverage the Eloquent magic into your controller. So sometimes, we guess

what type of model is required for what type of controller. We can always add them manually,

but while creating a resourceful controller we can also attach the model name along with it.

Consider this command:

php artisan make:controller ArticleController --resource –model=Tag

This command will automatically add Tag Model to your Article controller.

Page 100: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

So far in this book we have seen only the ‘index()’ and ‘show()’ methods. In fact, to

understand the core concepts of model relations, they are enough. However, there is a catch. The

drawback is not readily evident. When we only create resourceful controllers our sensitive

actions also opens up. We don’t want our viewers to see these actions: 'create', 'store', 'update',

'destroy'; as they are related to actions that are not to be shared.

However, Laravel has thought about it and solved this problem. During the

declaration of a resource route, you may specify a subset of actions the controller should handle

instead of the full set of default actions. In our ‘routes/web.php’, we may be specific about the

Article Controller this way:

Route::resource('photos', 'ArticleController')->only([

'index', 'show'

]);

Route::resource('photos', 'ArticleController')->except([

'create', 'store', 'update', 'destroy'

]);

Once you declare the resource route this way, people can no longer view the pages

associated with the sensitive actions. Of course, there are other techniques available also; but

they belong to different topic.

Page 101: Laravel 5.7.* Model Relations Explained - Leanpubsamples.leanpub.com/laravel5learneasy-sample.pdf · 3.5 Installing Homestead Vagrant Box 3.6 Homestead installation and configuration

For the sake of building model relations in multiple ways you can add additional

routes to a resourceful controller. When you create a resourceful controller, it always comes up

with a default set of resource routes.

Suppose you want to show popular articles based on the votes by the users. You have

decided to choose the URI as ‘articles/popular’ and the action you have chosen is ‘popular’.

Quite naturally these URI-s and actions don’t come up with the resourceful controller, you have

to manually add them this way:

Route::get('articles/popular', 'ArticleController@popular');

Route::resource('articles', 'ArticleController');

While manually adding them, one thing you should remember. You must define those

routes before your call to `Route::resource`; as I have shown above. If you don’t do that, the

resourceful routes may overpower them and will be a hindrance.