Since it’s initial launch in 2011, Laravel has experienced exponential growth. In 2015 it became the most outstanding PHP framework in GitHUb.
Laravel’s philosophy is to develop PHP code in an elegant and simple way based on a model MVC (Model-View-Controller). It has a modular and extensible code through a package manager and robust support for database management.
This guide is elaborated thinking in people who are starting with Laravel, a registration system will be developed to cover the basic operations of create, read, update and delete records, commonly known as CRUD.
Server Requirements
All the requirements of the server for the development of this guide are in the article Install Laravel with Apache and MySQL
Create Database
Execute the following command in the terminal:
mysql -u root -p
It will ask you for the password of the root user, once you enter the password correctly it will show you the mysql prompt>
You can also use phpmyadmin to create the database, if you have it installed.
From the terminal create the database to use:
CREATE DATABASE laravelcrud;
Create the username and password, which will be assigned to the created database:
CREATE USER 'laravel_user'@'127.0.0.1' IDENTIFIED BY 'LaB_101
Assign the created user to the database:
GRANT ALL ON laravelcrud.* TO 'laravel_user'@'127.0.0.1';
To reload the privilege table, the following command is executed:
FLUSH PRIVILEGES;
Create Laravel Project
Execute the command that will create a new project called laravelcrud, this command will generate the entire structure of folders, files and dependencies necessary to run the application:
laravel new laravelcrud
Open The Project in the Preference Editor
Once the new Laravel project is generated, open it in your preferred editor, personally I like to use Visual Code.
Through the terminal access to the project folder:
cd laravelcrud
Set Database Configuration
Search the .env file and proceed to write the configuration of the database created and that will be used by the application:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravelcrud DB_USERNAME=laravel_user DB_PASSWORD=LaB_101$
To be sure that there is a connection between our application and the database, execute the command:
php artisan migrate
This command will create 3 tables in the default database:
- migratios
- password_resets
- users
In the terminal connected to the MySQL prompt run:
mysql> use laravelcrud; mysql> show tables;
Additional in the project the migrations for those tables were automatically created in the generated folder app -> database-> migrations
Create Model and Migration
In the terminal execute:
php artisan make:model Registry -m
Two files will be created:
- Registry.php the model.
- create_registries_table.php the migration.
You need to create the structure (schema) of the registry table to modify the newly created migration file found in app -> database -> migrations -> create_registries_table.ph
In the class created for the migration, the methods up and down are automatically generated, modifying as follows:
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateRegistriesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('registries', function (Blueprint $table) { $table->integer('id')->unsigned(); $table->string('first_name',50); $table->string('second_name',50)->nullable(); $table->string('surename',50); $table->string('second_surename',50)->nullable(); $table->string('email',100); $table->string('cell_phone',50)->nullable(); $table->string('phone',50)->nullable(); $table->string('coments',500)->nullable(); $table->integer('age'); $table->boolean('flosspainfo')->nullable(); $table->boolean('fedorainfo')->nullable(); $table->boolean('latansecinfo')->nullable(); $table->timestamps(); $table->primary(array('id', 'email')); }); DB::statement('ALTER TABLE registries MODIFY id INTEGER NOT NULL AUTO_INCREMENT'); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('registries'); } }
Re-execute the migration command:
php artisan migrate
To validate the creation of the table run the database command used previously and to validate the creation of the columns run in the terminal:
use laravelcrud; show columns from registries;
Create The Register View
The first view is generated, to do this create the registries folder inside app -> resources -> views and then create the create.blade.php file inside this folder:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>FLOSSPA Asistencia Evento </title> <link rel="stylesheet" href="{{asset('css/app.css')}}"> <link rel="stylesheet" href="{{asset('css/registry.css')}}"> </head> <body> <div class="container"> <img alt="FLOSSPA" srcset="{{ URL::to('/images/logo-flosspa.svg') }}"> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div><br /> @endif @if (\Session::has('success')) <div class="alert alert-success"> <p>{{ \Session::get('success') }}</p> </div><br /> @endif <form method="post" action="{{url('registries')}}" id="formRegistry"> {{csrf_field()}} <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Primer Nombre:</label> <input type="text" class="form-control" name="first_name" value={{old('first_name')}}> </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Segundo Nombre:</label> <input type="text" class="form-control" name="second_name" value={{old('second_name')}}> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Primer Apellido:</label> <input type="text" class="form-control" name="surename" value={{old('surename')}}> </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Segundo Apellido:</label> <input type="text" class="form-control" name="second_surename" value={{old('second_surename')}}> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Email:</label> <input type="text" class="form-control" name="email" value={{old('email')}}> </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Edad:</label> <input type="text" class="form-control" name="age" value={{old('age')}}> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Télefono Residencial:</label> <input type="text" class="form-control" name="phone" value={{old('phone')}}> </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Celular:</label> <input type="text" class="form-control" name="cell_phone" value={{old('cell_phone')}}> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Desea recibir información de:</label> <div class="checkbox"> <label> <input type="checkbox" name="flosspainfo" @if(old('flosspainfo') !== NULL ){{ 'checked' }}@endif> FLOSSPA</label> </div> <div class="checkbox"> <label> <input type="checkbox" name="fedorainfo" @if(old('fedorainfo') !== NULL ){{ 'checked' }}@endif> FEDORA</label> </div> <div class="checkbox disabled"> <label> <input type="checkbox" name="latansecinfo" @if(old('latansecinfo') !== NULL ){{ 'checked' }}@endif> LATANSEC</label> </div> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-12 col-md-12"> <label for="name">Comentarios:</label> <textarea class="form-control" rows="5" name="coments" >{{old('coments')}}</textarea> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-12 col-md-12"> <button type="submit" class="btn btn-success">Agregar Asistencia</button> </div> </div> </form> </div> <div id="toast-container" class="toast-top-right"> </div </body> </html>
To avoid CSRF attacks (Cross-site request forgery or cross-site request forgery) is a type of malicious exploit of a website in which unauthorized commands are transmitted by a user in which the website trusts. This vulnerability is also known by other names such as XSRF, hostile link, session thrust, and automatic attack. Larvel provides the protection {{csrf_field ()}}.
To preserve the information in the form, it is achieved by adding value = {{old (‘first_name’)}} in each of the added controls.
Now create the route to display the view, execute the following command:
php artisan make:controller RegistryController --resource
Inside the folder app -> Http -> Controllers you will find the controller, automatically generated with all the necessary methods for the CRUD.
In order to have access to the methods created, a route referring to the controller must be added, the file app -> routes -> web.php is modified
<?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::resource('registries','RegistryController');
To watch the list of routes execute in the terminal:
php artisan route:list
In the create method of the controller, the following code is added:
public function create() { return view('registries.create'); }
Start the Laravel development server and you will watch the first view:
php artisan serve
Load the next URL in the browser:
http://localhost:8000/registries/create
In the public -> css folder, custom CSS was added and the images folder was created to add the image that is displayed on the screen. You can download the code from my GitHub account.
In the model, you must handle the Mass Assignment vulnerability, the class found in app -> Registry.php is modified.
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Registry extends Model { protected $fillable = ['first_name','second_name','surename','second_surename', 'email','age','phone','cell_phone','flosspainfo','fedorainfo','latansecinfo','coments']; }
For to save the data that is sent from the view, the RegistryController.php controller must be modified, including the Registry class and the static interface (Facades) Input.
use App\Registry; use Illuminate\Support\Facades\Input;
Now you must modify the store method:
public function store(Request $request) { $registry = $this->validate(request(), [ 'first_name' => 'required', 'surename' => 'required', 'email' => 'required|email', 'age' => 'integer|min:0' ]); $flosspainfo = Input::get('flosspainfo') == 'on' ? true :false; $fedorainfo = Input::get('fedorainfo') == 'on' ? true :false; $latansecinfo = Input::get('latansecinfo') == 'on' ? true :false; Registry::create([ 'first_name'=> Input::get('first_name'), 'second_name'=> Input::get('second_name'), 'surename'=> Input::get('surename'), 'second_surename'=> Input::get('second_surename'), 'email'=> Input::get('email'), 'cell_phone' => Input::get('cell_phone'), 'phone'=> Input::get('phone'), 'coments'=> Input::get('coments'), 'age'=> Input::get('age'), 'flosspainfo'=> $flosspainfo, 'fedorainfo'=> $fedorainfo, 'latansecinfo'=> $latansecinfo ]); return back()->with('success', 'Información almacenada con éxito'); }
Load the view and try to save without filling the data, validation messages will be received.
To display the messages in Spanish you can use the following translation package.
List View
Now you will create a list of all saved records, create the view in
app–>resources–>views–> registries–>index.blade.php
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index Page</title> <link rel="stylesheet" href="{{asset('css/app.css')}}"> </head> <body> <div class="container"> <img src="equilateral.png" alt="FLOSSPA" srcset="{{ URL::to('/images/logo-flosspa.svg') }}"> <br /> @if (\Session::has('success')) <div class="alert alert-success"> <p>{{ \Session::get('success') }}</p> </div><br /> @endif <table class="table table-striped"> <thead> <tr> <th>ID</th> <th>Nombre</th> <th>Apellido</th> <th >Email</th> <th >Teléfono</th> <th >Celular</th> <th colspan="2">Acción</th> </tr> </thead> <tbody> @foreach($registries as $registry) <tr> <td>{{$registry['id']}}</td> <td>{{$registry['first_name']}}</td> <td>{{$registry['surename']}}</td> <td>{{$registry['email']}}</td> <td>{{$registry['phone']}}</td> <td>{{$registry['cell_phone']}}</td> <td><a href="{{action('RegistryController@edit', $registry['id'])}}" class="btn btn-warning">Edit</a></td> <td> <form onsubmit="return confirm('Do you really want to delete?');" action="{{action('RegistryController@destroy', $registry['id'])}}" method="post"> {{csrf_field()}} <input name="_method" type="hidden" value="DELETE"> <button class="btn btn-danger" type="submit">Delete</button> </form> </td> </tr> @endforeach </tbody> </table> </div> </body> </html
Modify the controller by adding the view load:
public function index() { $registries = Registry::all()->toArray(); return view('registries.index', compact('registries')); }
Load the view http://localhost:8000/registries
Edit View
Create the editing functionality of a record, for it starts creating the view that is quite similar to that of the creation app -> resources -> views -> registries -> edit.blade.php
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>FLOSSPA Editar Asistencia Evento </title> <link rel="stylesheet" href="{{asset('css/app.css')}}"> <link rel="stylesheet" href="{{asset('css/registry.css')}}"> </head> <body> <div class="container"> <img src="equilateral.png" alt="FLOSSPA" srcset="{{ URL::to('/images/logo-flosspa.svg') }}"> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div><br /> @endif @if (\Session::has('success')) <div class="alert alert-success"> <p>{{ \Session::get('success') }}</p> </div><br /> @endif <form method="post" action="{{action('RegistryController@update', $id)}}" id="formRegistry"> {{csrf_field()}} <input name="_method" type="hidden" value="PATCH"> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Primer Nombre:</label> <input type="text" class="form-control" name="first_name" value="{{$registry->first_name}}" > </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Segundo Nombre:</label> <input type="text" class="form-control" name="second_name" value="{{$registry->second_name}}"> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Primer Apellido:</label> <input type="text" class="form-control" name="surename" value="{{$registry->surename}}"> </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Segundo Apellido:</label> <input type="text" class="form-control" name="second_surename" value="{{$registry->second_surename}}"> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Email:</label> <input type="text" class="form-control" name="email" value="{{$registry->email}}"> </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Edad:</label> <input type="text" class="form-control" name="age" value="{{$registry->age}}"> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Télefono Residencial:</label> <input type="text" class="form-control" name="phone" value="{{$registry->phone}}"> </div> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Celular:</label> <input type="text" class="form-control" name="cell_phone" value="{{$registry->cell_phone}}"> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-6 col-md-6"> <label for="name">Desea recibir información de:</label> <div class="checkbox"> <label> <input type="checkbox" name="flosspainfo" @if($registry->flosspainfo == true ){{ 'checked' }}@endif> FLOSSPA</label> </div> <div class="checkbox"> <label> <input type="checkbox" name="fedorainfo" @if($registry->fedorainfo == true){{ 'checked' }}@endif> FEDORA</label> </div> <div class="checkbox disabled"> <label> <input type="checkbox" name="latansecinfo" @if($registry->latansecinfo == true ){{ 'checked' }}@endif> LATANSEC</label> </div> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-12 col-md-12"> <label for="name">Comentarios:</label> <textarea class="form-control" rows="5" name="coments" >{{$registry->coments}}</textarea> </div> </div> <div class="row"> <div class="form-group col-xs-12 col-sm-12 col-md-12"> <button type="submit" class="btn btn-success">Update</button> </div> </div> </form> </div> <div id="toast-container" class="toast-top-right"> </div </body> </html>
Modify the edit method, as well as the update method of the controller:
/** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit($id) { $registry = Registry::find($id); return view('registries.edit',compact('registry','id')); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { $registry = Registry::find($id); $this->validate(request(), [ 'first_name' => 'required', 'surename' => 'required', 'email' => 'required|email', 'age' => 'integer|min:0' ]); $registry->first_name = Input::get('first_name'); $registry->second_name = Input::get('second_name'); $registry->surename = Input::get('surename'); $registry->second_surename = Input::get('second_surename'); $registry->email = Input::get('email'); $registry->cell_phone = Input::get('cell_phone'); $registry->phone = Input::get('phone'); $registry->coments = Input::get('coments'); $registry->age = Input::get('age'); $registry->flosspainfo = Input::get('flosspainfo') == 'on' ? true :false; $registry->fedorainfo = Input::get('fedorainfo') == 'on' ? true :false; $registry->latansecinfo = Input::get('latansecinfo') == 'on' ? true :false; $registry->save(); return back()->with('success', 'Registry updated successfully'); }
Deleting Record
To delete a record, add the following in the destroy method of the controller:
public function destroy($id) { $registry = Registry::find($id); $registry->delete(); return redirect('registries')->with('success','Registry has been deleted'); }
You can find the fully functional project in my GitHub account.
What do you think?