Laravel 5 example application

We are going to build an application in very good php framework – Laravel – list of tasks to complete. The list of tasks of the user will be protected by login and password. To understand the following course and run on your computer, you must be familiar with the following topics:

  • object-oriented programming in PHP
  • MVC pattern
  • HTML i CSS
  • dependencies management tool – Composer
  • Linux and / or Windows console basics
  • local servers (eg. Vagrant box, Wamp, Apache on Debian, Xampp, etc.)

Details of specific topics, such as the description of the Laravel’s template engine can be found in the official Laravel docs.

Installation

We begin by installing a fresh application by using Composer command:

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

Then you set recursive write permissions for folders: storage and bootstrap / cache. If after entering the home page you get the message “Laravel 5”, this means that the installation was correctly.

Building database

We set the access data to the database in .env file. (change DB_DATABASE, DB_USERNAME, DB_PASSWORD to appropriate your own values).

Migrations

php artisan make:migration create_tasks_table --create=tasks

Option “–create=tasks” will add a field of type int to the table and the field of type timestamp. After finishing the above command there will be created a file with “tasks”table definition in the database/migrations folder. Then we add to the up() function the following new columns of tasks table:

$table->integer('user_id')->index();
$table->string('name');

Then, in the console type the command php artisan migrate, which creates a new table in the database (you do not have to create tables manually).

Become a Professionalist in Web Application Development! Enroll In The Course Of Laravel You will also learn how to create hybrid applications for smartphones

Seeders

Time to fill the tables with sample data. For this purpose seeders are used.

php artisan make:seeder UsersTableSeeder

The above command will create UsersTableSeeder.php file in the database/seeds folder. We complete the run() function with the following code:

for($i=1;$i<=2;$i++)
{
   DB::table('users')->insert([
   'name' => str_random(10),
   'email' => 'email'.$i.'@gmail.com',
   'password' => bcrypt('secret'.$i),
   ]);
}

This will create two new members for us. Then uncomment in the database/seeds/DatabaseSeeder.php line $this>call(UsersTableSeeder::class);, then in the console type the command php artisan db:seed to save the result in a database. If we again call the above command, we will get an error that the email address already exists in the database. So, to completely reset our database type in the console php artisan migrate:refresh --seed, which will delete the existing tables, create them from scratch and populate with the sample data.

Models

php artisan make:model Task – a console command for creating a Task model in the app folder. We complete our model with protected $fillable = ['name']; which means that the name field in the Users table will be writable by the active record pattern, which Laravel uses to interact with the database. We add also protected $casts = ['user_id'=>'int']; , which ensures projection user_id field on type of int, which is useful when authorizing the user to take action to delete a task (user id must be exactly equal to the task user_id).

It’s time to add the relationships between database tables.

In the User model we add:

public function tasks() // user can have multiple tasks to be done
{
return $this->hasMany(Task::class);
}

And in the Task model we add:

public function user() // each task belongs to a single user
{
return $this->belongsTo(User::class);
}

Then we create a repository responsible for performing database operations. Create app/Repositories folder and TaskRepository.php file in it.

namespace App\Repositories;

use App\User;
use App\Task;

class TaskRepository
{
    /**
     * Get all of the tasks for a given user.
     *
     * @param  User  $user
     * @return Collection
     */
    public function forUser(User $user)
    {
        return Task::where('user_id', $user->id)
                    ->orderBy('created_at', 'asc')
                    ->get();
    }
}

Repository pattern is particularly useful in large applications. We achieve separation of code for various purposes. The application is easier to modify.

Views

php artisan make:auth – this Composer command generates for us a lot of views useful during login and user registration in Laravel 5. From this moment, we can log in to the application on account of one of the two users previously created by the seeder. In addition, this console command adds new controller called HomeController, adds to the routes.php file handlers for routing and logging (links: login, register and password recovery). Because after login you will want to be redirected to the list of user tasks, we need to change some generated files. In the app/Http/Controllers/Auth/AuthController.php file change $redirectTo property to tasks. Similarly in the app/Http/Middleware/RedirectIfAuthenticated.php file.

We must define another application views ourselfs. We create tasks folder in app/resources/views. Create there index.blade.php file and write to it:

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="col-sm-offset-2 col-sm-8">
            <div class="panel panel-default">
                <div class="panel-heading">
                    New Task
                </div>

                <div class="panel-body">
                    <!-- Display Validation Errors -->
                    @include('common.errors')

                    <!-- New Task Form -->
                    <form action="./task" method="POST" class="form-horizontal">
                        {{ csrf_field() }}

                        <!-- Task Name -->
                        <div class="form-group">
                            <label for="task-name" class="col-sm-3 control-label">Task</label>

                            <div class="col-sm-6">
                                <input type="text" name="name" id="task-name" class="form-control" value="{{ old('task') }}">
                            </div>
                        </div>

                        <!-- Add Task Button -->
                        <div class="form-group">
                            <div class="col-sm-offset-3 col-sm-6">
                                <button type="submit" class="btn btn-default">
                                    <i class="fa fa-btn fa-plus"></i>Add Task
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>

            <!-- Current Tasks -->
            @if (count($tasks) > 0)
                <div class="panel panel-default">
                    <div class="panel-heading">
                        Current Tasks
                    </div>

                    <div class="panel-body">
                        <table class="table table-striped task-table">
                            <thead>
                                <th>Task</th>
                                <th>&nbsp;</th>
                            </thead>
                            <tbody>
                                @foreach ($tasks as $task)
                                    <tr>
                                        <td class="table-text"><div>{{ $task->name }}</div></td>

                                        <!-- Task Delete Button -->
                                        <td>
                                            <form action="./task/{{ $task->id }}" method="POST">
                                                {{ csrf_field() }}
                                                {{ method_field('DELETE') }}

                                                <button type="submit" id="delete-task-{{ $task->id }}" class="btn btn-danger">
                                                    <i class="fa fa-btn fa-trash"></i>Delete
                                                </button>
                                            </form>
                                        </td>
                                    </tr>
                                @endforeach
                            </tbody>
                        </table>
                    </div>
                </div>
            @endif
        </div>
    </div>
@endsection

Files with the name of blade.php are Laravel’s template engine files. In this engine there are many useful directives, among which the most important are the curly braces {{ }} in which we store a variable or function result to display. Next create app/resources/views/common folder and errors.blade.php file in it, and write to it:

@if (count($errors) > 0)
<!-- Form Error List -->
<div class="alert alert-danger">
<strong>Whoops! Something went wrong!</strong>

<br><br>

<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif

Here will be present error messages in case of errors in the application forms.

Controllers in Laravel 5

We create artisan make:controller TaskController

We complete the code so that file in the app/Http/Controllers folder looks like:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;

use App\Repositories\TaskRepository;

use App\Task;


class TaskController extends Controller
{
    public function __construct( TaskRepository $tasks )
    {
	$this->tasks = $tasks;
        $this->middleware('auth'); // this means that every action in the controller will be protected against not logged access
    }


    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|max:255',
        ]);   // in view will be $errors->all()

        // Create The Task…
          $request->user()->tasks()->create([
            'name' => $request->name,
        ]);

        return redirect('/tasks');
    }


    public function index(Request $request)
    {
        //$tasks = Task::where('user_id', $request->user()->id)->get();

          return view('tasks.index', [
                'tasks' => $this->tasks->forUser($request->user()),
            ]);
    }


    public function destroy(Request $request, Task $task)
    {

        $this->authorize('destroy', $task); // if the user id is equal to the task user_id further code will be executed
        $task->delete();

        return redirect('/tasks');
    }
}

The new controller methods we must mention in the route.php file:

Route::get('/tasks', 'TaskController@index');
Route::post('/task', 'TaskController@store');
Route::delete('/task/{task}', 'TaskController@destroy');

Authorization

We create the code responsible for user authorization when deleting task (each user can delete only his own task).

php artisan make:policy TaskPolicy

The above command will create app/Http/Policies/TaskPolicy.php file. Change it into:

namespace App\Policies;

use Illuminate\Auth\Access\HandlesAuthorization;

use App\Task;
use App\User;

class TaskPolicy
{
    use HandlesAuthorization;

    /**
     * Create a new policy instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    
    public function destroy(User $user, Task $task)
    {
        return $user->id === $task->user_id;
    }
}

In the app/Providers/AuthServiceProvider.php file we add into $policies a table entry: 'App\Task' => 'App\Policies\TaskPolicy'

Additional settings

In the application we use the mechanism of recovery of forgotten passwords by sending an e-mail. For this purpose we have to set up our own e-mail account information in the .env file. Change all the parameters that begin with MAIL_. You must also change parameters of ‘from’ key of the table in config/mail.php. Additionally, if you want the logged-in user session to expire after the browser is closed, set the ‘expire_on_close’ key to true in the config/session.php file.

enroll in the course of Laravel framework >>>> or affiliate program
Share

Leave a Reply

Your email address will not be published. Required fields are marked *