<<

5.7.* Model Relations Explained

A DETAILED DISCUSSION OF MVC, , 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. Development Editor: Amitakkhar Deb, 12REACH

Cover designed by Kaberi Sinha

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

Acknowledgments

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

Contents

1. What is MVC Pattern

2. How MVC Pattern Works

3. Composer and Laravel

3.1 Composer’s role in Effective Patterns 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 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 Pattern

Implementing 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. 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 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 Works

Imagine 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 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 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 Laravel

Using 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 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. 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 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 distribution it is simple. If you are a Windows user, it’s better to install oracle SE Development Kit, Netbeans Tesxt Editor and XAMPP. 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 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 //Installing Composer and use it globally in the system ss@ss-Lenovo-3000-G530:/$ -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ss@ss-Lenovo-3000-G530:/$ php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fd fdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } 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 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/” 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 (/) [root/test-composer]: ss/mvc

Description []: mvc

Author [, n to skip]: n

Minimum Stability []: stable

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

License []: 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 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 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”. 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", "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

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

use Karnel\Apply as Apply;

$app = new Apply; Here, “$app” represents our application instance. And the code of “init.php” file looks like this:

// code 3.7

//karnel/init.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

* 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

/*

* 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); 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 Options -MultiViews

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-

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". 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 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 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 “ 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 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 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. // 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 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’. 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. // code 3.19

$ sudo add--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- 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 () 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 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/, or directory 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%) - 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 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 Laravel development server started:

[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 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 Application

We 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 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:

[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 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', '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', '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: '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. 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(); $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 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'); $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 $ 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) { $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');

} 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()

{ 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’. // 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 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

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. //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’. // 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 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. 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.KjNyWgaHb9cbcoQgdIVFlYg7B 77UdFm', // secret

'remember_token' => str_random(10),

];

});

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

return [

'user_id' => App\User::all()->random()->id, '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

];

}); 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);

});

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 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 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. 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 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: 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. 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; 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')

@endsection

In the whole code-body, this line attracts our extra attention: Written by {{ $article->user->name }}.

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

namespace App; 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');

}

} 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

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

];

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

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model

{

//

protected $fillable = [

'tag'

];

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

namespace App;

use Illuminate\Notifications\Notifiable;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable

{

use Notifiable; /**

* The attributes that are mass assignable.

*

* @var array

*/ protected $fillable = [

'name', 'email', 'password',

];

/**

* The attributes that should be hidden for arrays.

*

* @var array

*/ protected $hidden = [

'password', 'remember_token',

];

public function profile() {

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

}

public function article() { 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. 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

namespace App\Http\Controllers;

use App\Comment;

use Illuminate\Http\Request;

class CommentController extends Controller

{

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)

{ //

}

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 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’. 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 // resources/views/articles/index.blade.php

@extends('layouts.app')

@section('content')

@endsection 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 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(); $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

Now the home page of our application looks like this: 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:

This week we have showcased only the articles Written by {{ $article->user->name }}

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

This change has brought a nice change on the front page of our application. And it looks like this: 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: {{ $article- >user->name }}

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 Magic

What 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. 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' ]);

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