Building web applications using PHP and the Laravel Framework.

Laravel describes itself as the the PHP Framework for Web Artisans. For this tutorial I created a mini shop using a bootstrap template of course. With Laravel I implemented CRUD operations and user authentication. Laravel is a pretty cool framework and its not hard to understand the flow. There are different major versions and the current version that I used had sooooooo many folders. Wow! Besides that it was easy to work with. Some of the things you will learn in this tutorial are

  • Installing and setting up Laravel
  • Using the server
  • Using blade Templates
  • Using eloquent ORM
  • Creating Controllers, routes and models
  • Database migrations and version control
  • Using forms and posting data
  • User authentication

You can learn more about Laravel here at their website. I used some videos from YouTube to learn about Laravel you can check that out here. The author is Traversy Media and they create some great content for software learning.

Laravel Shop Dashboard

Getting Started

So to get started I updated PHP version on my computer to 7.1. I use Linux so I did the required installs. However if you’re using XAMPP you can download the correct version here. The latest Laravel requires PHP >= 7.1.3 . You also should have composer to install your start up application. So make sure to install composer. Once you do you can issue the following command.

composer create-project --prefer-dist laravel/laravel blog

The above command sets up your application. You could change the name blog to whatever you want. This is the folder where the application is stored.

Now if you don’t want to start from scratch you can just download the application from Github. To do this follow the instructions below. This is the suggested way to go. You can review the code on your own and change and test different things.

# download repo
git clone https://github.com/wyntonfranklin/laravel-shop.git

# Go into repo
cd laravel-shop

#Install dependencies
composer install

#run the app
php artisan serve

Presuming this works you will be good to go. You can review the repo here. The command artisan serve starts the application server. So you wouldn’t need to use XAMPP however you need to ensure your database servers are running as well so you will still need it.

Application Structure

So Laravel directory structure is interesting, I’m not going to list it but I will show where each of the files I review will be located. There are default or suggestion folders to put everything. Its not confusing just not as flat as you might hope it to be.

Virtual Host Configuration

In a production environment or using XAMPP or something like it you will need to setup your Virtual host configurations. The important thing to note here is that the public directory is where to point your document root as seen below. The public directory also hosts your CSS and JS files and vendor assets packages that you want to use.

<VirtualHost *:80>
    DocumentRoot "/var/www/laravel-shop/public"
    ServerName www.laravelshop.com
    ServerAlias www.laravelshop.com
    <Directory "/var/www/laravel-shop/public"> 
        AllowOverride All
        Require all Granted
    </Directory>
</VirtualHost>

Configuration

In your root folder there is and .env file. This will be created for you as it isn’t added with the repository. You can see an example of this file from the .env.example file. The .env file is where you should add your database setup information. You can also change the name of the app.

// .env

APP_NAME="Laravel Shop"
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=wf_tutorials
DB_USERNAME=root
DB_PASSWORD=

You can access these attributes using the config function.

config('app.name') // get app name

Assets

You can add assets to your project in the public folder. There is actually a more dynamic way to do this using npm but I choose the simple way. So to add your files you can just add them the normal way by pointing to the directory.

<link href="/../vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/../css/shop-item.css" rel="stylesheet">
<script src="/../vendor/jquery/jquery.min.js"></script>

Alternatively you can use the asset function to get the URL of assets in your public folder.

<link href="{{ asset("/css/shop-item.css") }}" rel="stylesheet">
<script src="{{ asset("/vendor/jquery/jquery.js") }}"></script>

Assets Management using NPM

Laravel comes with a package JSON that has development dependencies you can use in your application. You can install these dependencies and use them to manage your assets. The development JavaScript and CSS files are located in the resources directory and when you run the npm development command the public files are created in the public directories as app.css and app.js. You can then uses these files in your application. In the resources/sass directory you have a variables file and a main file. You can edit these files to generate your app.css.

To get started with npm development assuming you already of node installed. Run the following commands.

npm install // install dependencies

npm dev // run the dev script

The dev script takes care of creating your javascript files and css files from your resources templates.

Routes

The routes for your application is located in the routes folder. It has a few files well.

 routes/
    api.php
    channels.php
    console.php
    web.php

We will focus on the web.php files. All of your routes go in here. A basic route in Laravel is shown below but you can learn more about routing here.

Route::get('foo', function () {
    return 'Hello World';
});

We don’t create routes like this. No..no..no. Our routes are attached to controllers and we render our views from controllers.

// routes/web.php

Route::get('/', 'HomeController@homePage')->name("dashboard");
Route::post('/shop/save','ShopController@save');
Route::resource('reviews', 'ReviewController');

So we have three different types of route functions that we used to build this application. The first is a get request. Basically the function homePage in the home controller will run at the url ‘/’. Then we have the post route. We use this in a form setting and it is controlled by the ShopController. The save function in that controller will execute when the url ‘/shop/save’ is executed. Next we have a resource function. This function generates all the routes we will need to build an basic CRUD application. You can learn more about the resource controller here.

Create a resource function can be done using the command line and artisan. So to create the ReviewController I ran the following command

php artisan make:controller ReviewController --resource

To create a normal controller just remove the argument –resource.

php artisan make:controller ShopController 

Attached to the route get function I have a function called name that takes a string argument. I pass the argument “dashboard”. Doing this allows me to use the route function to get the correct URL.

// naming a route

Route::get('/', 'HomeController@homePage')->name("dashboard");
// get the path of a named route

route('dashboard')

 <a class="navbar-brand" href="{{ route('dashboard') }}">{{ config('app.name') }}</a>

I can use this function in blade views to get the URL of a particular route. So I’m basically just naming my routes.

If I need to add a parameter to my urls and pass it into my controller function I would create a route with a placeholder.

// routes/web.php

Route::get('/shop/product/{id}','ShopController@product');
Route::get('/shop/edit/{id}','ShopController@edit');
Route::post('/shop/update/{id}','ShopController@update');

I’ve done this for the product view so I can view a particular product. For the edit view when I’m editing a product and in the update function using post to update my product.

In the controller you can access the passed attributed by adding it as a requirement in the function. So in the shop controller the product function looks like below.

// get the id from a get request

public function product( $id="" )
{
   
}

Controllers

Controllers are located in app/Http/Controllers. I have a few controllers in my application.

laravel-shop/
  app/
    Http/
       Controllers/
         Controller.php
         HomeController.php
         ReviewController.php
         ShopController.php

The controller.php is the base controller all other controllers extend from this controller.

Rendering Views

So a simple rendering in the home controller is the about page.

// app/Http/Controllers/HomeController.php
 
 public function aboutPage()
 {
    $title = "About Page";
    return view('home.about')->with("title", $title);
 }

You create your function that is mapped in routes and you return the view function with the name of the template file. You can pass data to your views with a function named with. It takes a key and the data you want to pass. Things can of course get more complicated as the homePage function shows.

// app/Http/Controllers/HomeController.php

public function homePage()
{
   $title = "Laravel Shop";
   $list = Product::all()
      ->sortByDesc("created_at")
      ->take(5);
   return view('home.index',[
     'products' => $list
     ])->with("title", $title);
}

The main thing to note here is how I can allows pass an array in the view function so that data can be accessed in my view. The home page function uses our product model to get a list of products. But I will go into that more later.

Request Object

The ReviewController has a store method that takes in a request object. In routes this function is mapped to a post route. I used this function to save data from a form. I can use the request object to get $_POST data from the form. In truth you can require the request object for all your http requests functions.

// app/Http/Controllers/ReviewsController.php

   public function store(Request $request)
    {
        $model = new Reviews();
        $model->content = $request->input("review");
        $model->author = $this->getAuthor();
        $model->product_id = $request->input("productId");
        $model->save();
        return redirect('/shop/product/'.$model->product_id)
            ->with("success","Review Created");
    }

Above we can see the request object in use. We get the POST key review from the $_POST object and the productId the same way using the input function on the request object. We then return the redirect function with the URL and some session data.

With the redirect function we can add session parameters that we can access in views. So the success session key will have the message – “Review Created”. In the view we check to see if the session key exists and if it does the message is displayed.

Validation

In your controllers you can validate requests coming in from your forms. In the ShopController I used this on the save function.

// app/Http/Controllers/ShopController.php

  
 $this->validate($request,[
    "name" => 'required'
  ]);

If the request object does not have the required fields the form will not post the request. Instead it returns with errors.

Models and Migrations

Laravel uses eloquent which is an ORM ( object relational mapper ). This gives you some amazing features without having to interact with the database. Well you still need to interact but a lot is done for you so you don’t repeat yourself. Migrations is a way to manage your database changes. You can create, run migrations and roll back changes made to your database. To get started creating our models all we had to do was run an artisan command in the command line.

Creating Models

php artisan make:model Product --migration
php artisan make:model Reviews --migration

These commands above allowed me to create models and migrations. The models are saved in the App directory and the migrations are stored in the database/migrations directory.

When we created your application Laravel also created some default migrations for us to use. The users table and the password resets tables are created by default. When we run our migrations these are also executed.

Edit a Migration

Inside our migration for products table we can see the code that creates the table. The two main functions are up down. The up function is executed on migrate and the down function on rollback.

  public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string("title",150);
            $table->string("cost",125);
            $table->text("summary");
            $table->integer("rating");
            $table->string("url",150);
            $table->timestamps();
        });
    }

When using the string function you should add the limit. The string function creates a varchar field in your table. You can learn more about schema functionality here.

When you are ready you can run the migrations you created.

php artisan migrate  # run migrations

Model Setup

My actually models are pretty empty but they inherit a load of features from the parent class Model. Firstly you can manually choose the table the class represents by changing the class variable $table.

protected $table = 'my_flights'; // change or add this in a model class

Next you can do awesome things in your model for example I returned a view url by creating a function in my model. This was helpful because I didn’t have to do it many times.

public function getViewUrl()
{
   return '/shop/product/' . $this->id;
}

I also set my form data to my model by creating a setFormData function that takes a request object.

  public function setFormData( Request $request )
    {
        $this->title = $request->input("name");
        $this->cost = $request->input("cost");
        $this->url = $request->input("preview");
        $this->summary = $request->input("description");
        $this->rating = $request->input('rating');
    }

Model Inherited Functions

You can get collections from your model. When getting the list of products for my dashboard view I used the model collections function called all().

 $list = Product::all()
            ->sortByDesc("created_at")
            ->take(5);

I call the product model statically, called the all function on it and added some functions for sorting and limiting. The take function sets a limit on how many results can be returned.

To find or get a row from your table using the model you can use the find function. Where $id is the primary key that you are searching for.

   $model = Product::find($id);

If you wanted to get collections with a where query you can use the where function. The get and all functions return collections. You can loop through the results to get an individual model.

  $reviews = Reviews::where("product_id", $id)
            ->orderBy('created_at', 'desc')
            ->get();

You can learn more about collections and other features here.

Two other features of a model – where there is so much more – that we will look at is save and delete. These functions are descriptive enough. To use them is just as simple.

$product= Product::find($id);
$product->save();
$product->delete();

Views

The resources/views folder holds our view templates. Laravel uses blade as its templating engine which has the features you would expect. Files using blade are created with blade in the name. The shop create view is named create.blade.php.

Extending a View

If you wanted to add a header and footer on a page you can use the @extends function. This allows you add the current view to the extended view content section. The @section is where your view content should go.

@extends('layouts.home') // add the current view to layouts.home

@section('content')
  <h1>Hellow World</h1> <!-- Html content -->
@endsection

In the extended view all you need to do is call @yield(‘content’) to get the content from the view that extended it.

<div class="col-lg-9">
    @yield('content')
</div>

Looping through objects

In blade you can use the for each function to loop through objects passed to your view. To display the initial posts on the dashboard I used the for each function. @foreach and @endforeach are blade functions.

    @foreach ($products as $product)
        <div class="card mt-4">
            <img class="card-img-top img-fluid"
                 src="{{ $product->url }}"
                 style="height:150px;" alt="">
            <div class="card-body">
                <h3 class="card-title"><a href="{{ $product->getViewUrl() }}">{{ $product->title }}</a></h3>
                <h4>${{ $product->cost }}</h4>
                <p class="card-text">
                    {{ $product->summary }}
                </p>
                <span class="text-warning"><?php echo $product->getStars();?></span>
                {{ $product->rating }}.0 stars
            </div>
        </div>
@endforeach

You can access the object in your view using the doubly curly braces {{ }}. I use this to echo the product url, cost, summary and rating.

If statements

I wanted to show the username if the user was logged in so I used an if statements in blade to achieve this. @if and @endif are blade functions.

 @if(!Auth::guest())
        <div class="alert alert-primary" role="alert">
            Welcome {{ Auth::user()->name }}
        </div>
@endif

To get the session parameters passed I called the session function in the view with an if function.

@if (session('status'))
    <div class="alert alert-success" role="alert">
       {{ session('status') }}
     </div>
@endif

Creating Form

You can create forms really easily in Laravel. For this version we need to add some plugins first in order to use the form and html functions.

To get access to form features we go to Laravel Collective and install the html collection. Learn more here.

Using composer you can install the Laravel Collective html package.

composer require "laravelcollective/html":"^5.4.0"

Next we need to make some updates to our config files. The config file location is config/app.php. In providers we add –

// config/app.php  

'providers' => [
    // ...
    Collective\Html\HtmlServiceProvider::class,
    // ...
  ],

in aliases we add.

// config/app.php

'aliases' => [
    // ...
      'Form' => Collective\Html\FormFacade::class,
      'Html' => Collective\Html\HtmlFacade::class,
    // ...
  ],

Once those things are added we can use forms.

Form functions

In the shop/create.blade.php view we create our form to add a product to our shop. Now creating forms is pretty simple now we have installed the functions required to do them. To create a form follow the instructions below.

To open and close a form div we call the open and close methods. Note our attributes include URL and method.

 {!! Form::open(['url' => 'shop/save','method'=>'POST']) !!}
    //
{!! Form::close() !!}

For your form we had bootstrap divs wrapping our inputs and labels. On our text field we can add class attributes and a placeholder. Anything you will have added on a normal text field.

<div class="form-group">
                {{Form::label('name', 'Name', ['class' => 'awesome'])}}
                {{ Form::text('name', '',['class'=>'form-control','placeholder'=>'Product Name']) }}
</div>

We can add numbers and different types of inputs including date fields.

   <div class="form-group">
                {{Form::label('rating', 'Rating', ['class' => 'awesome'])}}
                {{ Form::number('rating', '',['class'=>'form-control']) }}
</div>

Then we create the submit button to post the information to the server.

When we do validation server side error objects are returned to our views if something goes wrong. We can display these errors as we see fit. For my create view for shop I did the following.

@if(count($errors) >0)
    @foreach($errors->all() as $error)
        <div class="alert alert-danger" role="alert">
            {{ $error }}
        </div>
    @endforeach
@endif

So basically above I check to see if I have any errors and then I loop through all and echo the results on them using an alert div.

Authentication

Authentication in our forms requires two steps. First we must have the functionality to login a user and then we must be able to distinguish between a logged in user and a guest and grant access to portions of our application based on the current state. The second part is access control so I will actually cover that in a separated section.

To get started with authentication you can run a cli command

php artisan make:auth

This command creates views, controllers and routes to manage your login and logout process. It is all done by automation magic. It’s important to note that it creates a homeController and a app.blade layout file. If these files existed they may be overwritten. Keep that in mind has it happened to me. You can make modifications to the layouts and code as you see necessary. Once auth is active you can use some really cool functions.

Auto generated login Page
Auth::user()->name // get the user name of the logged in user
Auth::guest() // is user guest

I say really cool but they are normal functions :). You can use these functions in your views and controllers to manage your application. Say you needed to tag a product with a certain user you would do the following.

$product->user_id = auth()->user()->id; 

The auth function gets the user object and we take the ID from it.

Access Control

Now a guest user should not be able to go everywhere in your application. So this is where access control comes in.

public function __construct()
{
   $this->middleware('auth', ['except'=>['homePage']]);
}

In your controllers you can add the _construct function and in it add middleware called auth. The middleware function takes in the type of middleware and an array. For the auth middleware the array can be used to describe what views ( functions ) in the controller should be available to the public. In the example above only the homePage function is available if users are not logged in. If they try to navigate to any other page they will be redirected to the login page.

Conclusion

Alrite you are done. You have created a Laravel CRUD application. Now with any framework there is so much more to learn and do but this is a good start. Learning is fun isn’t it :).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s