Quick Laravel Tutorial on CRUD operations

In the last episode we saw how to create a simple web app with the use of Symfony, now we’re going to do the same thing, but this time we’re gonna do it with Laravel.

Let’s begin with the installation, if you need more informations please refer to the Laravel documentation, type these commands on your shell:

$ composer create-project --prefer-dist laravel/laravel laravel_tutorial
$ cd laravel_test

The next thing you’re gonna have to do is to create a database for your Laravel installation:

$ mysql -u root -p
mysql> CREATE DATABASE laravel_test;
mysql> exit;

Connecting to the database

Now, let’s configure Laravel to connect to the database, we have to modify these lines into your project folder’s .env file:

DB_DATABASE=laravel_test
DB_USERNAME=root

In some cases you might have to modify also other lines like port and hostname, depending on your MySQL configuration, in addition put your own password into that file.

Then, let’s create a table for our model, with all the required fields, in this case we’re creating an article for our blog:

$ php artisan make:model Article -mc

Let’s make the coding

Again, modify your newly created migration file under the following path database/migrations. Make it look like this, adding the following lines to the up() method:

Schema::create('articles', function (Blueprint $table) {
  $table->increments('id');
  $table->timestamps();
  $table->string('title', 100);
  $table->string('author', 50);
  $table->string('body', 1000);
  $table->string('url', 200)->nullable($value = true);
});

A little tip, depending on your MySQL version you might encounter a problem due to the new charset of Laravel, solve it like this (modifing app/Providers/AppServiceProvider.php):

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
  /**
  * Bootstrap any application services.
  *
  * @return void
  */
  public function boot()
  {
    Schema::defaultStringLength(191);
  }

  /**
  * Register any application services.
  *
  * @return void
  */
  public function register()
  {
    //
  }
}

Aftrer that, run the migration like so:

$ php artisan migrate

Add the following fields to your newly created app/Article.php:

protected $title;
protected $author;
protected $body;
protected $url;

Let’s install and prepare our form modules, which are not part of the core anymore:

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

Open then your config/app.php and add the following lines in the correct locations (providers and aliases):

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


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

Let’s create the routes for our application, open routes/web.php and add the following lines of code:

Route::match(['get', 'post'], '/create-article', 'ArticleController@createArticle');

Route::get('/view-article/{id}', 'ArticleController@viewArticle');

Route::get('/show-articles', 'ArticleController@showArticles');

Route::get('/delete-article/{id}', 'ArticleController@deleteArticle');

Route::match(['get', 'post'], '/update-article/{id}', 'ArticleController@updateArticle');

We can now edit app/Http/Controllers/ArticleController.php and add the following content:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\ModelNotFoundException;

use App\Article;


class ArticleController extends Controller {


  public function createArticle(Request $request) {

    if ($request->isMethod('post')) {

      $article = new Article;
      $article->title = $request->input('title');
      $article->author = $request->input('author');
      $article->body = $request->input('body');
      $article->url = $request->input('url');

      $article->save();

      return redirect('/view-article/' . $article->id);
    }

    return view('edit');

  }


  public function viewArticle($id) {

    $article = Article::find($id);

    if (!$article) {
      throw new ModelNotFoundException();
    }

    return view('view', array('article' => $article));

  }


  public function showArticles() {

    $articles = Article::all();;
    return view('show', ['articles' => $articles]);

  }


  public function deleteArticle($id) {

    $article = Article::find($id);

    if (!$article) {
      throw new ModelNotFoundException();
    }

    $article->delete();

    return redirect('/show-articles');

  }


  public function updateArticle(Request $request, $id) {

    $article = Article::find($id);

    if (!$article) {
      throw new ModelNotFoundException();
    }


    if ($request->isMethod('post')) {

      $article->title = $request->input('title');
      $article->author = $request->input('author');
      $article->body = $request->input('body');
      $article->url = $request->input('url');

      $article->save();

      return redirect('/view-article/' . $article->id);
    }

    return view('edit', array('article' => $article));

  }

}

The last thing left to do is to create our views for each controller’s action you can find above, place the three files edit.blade.php, show.blade.php, view.blade.php under resources/views.

You will find them in that order here below:

<style>
th, td {
  padding: 10px;
}
th {
  text-align: right;
}
</style>

<h1>Create or Update Article:</h1>

{{ Form::open(['url' => Request::url()]) }}

<table>
  <tbody>
    <tr>
      <th>Title:</th>
      <td>{{ Form::text('title', $article->title ?? '', array('required' => 'required')) }}</td>
    </tr>
    <tr>
      <th>Author:</th>
      <td>{{ Form::text('author', $article->author ?? '', array('required' => 'required')) }}</td>
    </tr>
    <tr>
      <th>Article Body:</th>
      <td>{{ Form::textarea('body', $article->body ?? '', array('required' => 'required')) }}</td>
    </tr>
    <tr>
      <th>Homepage:</th>
      <td>{{ Form::text('url', $article->url ?? '', array('placeholder' => 'www.example.com')) }}</td>
    </tr>
    <tr>
      <th></th>
      <td>{{ Form::submit('Save') }}</td>
    </tr>
  </tbody>
</table>

{{ Form::close() }}
<style>
th, td {
  padding: 10px;
}
th {
  text-align: left;
}
</style>

<h1>All Articles</h1>

@if (!empty($articles))
<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Author</th>
      <th>Body</th>
      <th>Url</th>
      <th>Delete</th>
      <th>Update</th>
   </tr>
  </thead>
  <tbody>
  @foreach ($articles as $article)
  <tr>
    <td>{{ $article->title }}</td>
    <td>{{ $article->author }}</td>
    <td>{{ str_limit($article->body, 20) }}...</td>
    <td>
    @if ($article->url != "")
     <a href="http://{{ $article->url }}">Visit Url</a>
    @else
      Void Field
    @endif
    </td>
    <td><a href="delete-article/{{ $article->id }}">Delete</a></td>
    <td><a href="update-article/{{ $article->id }}">Update</a></td>
  </tr>
  @endforeach
  </tbody>
</table>
@else
<p>No article found.</p>
@endif

<br/>
<a href="/create-article">Create New</a>
<style>
th, td {
  padding: 10px;
}
th {
  text-align: right;
}
</style>

<h1>Article Created or Modified</h1>

<table>
  <tbody>
    <tr>
      <th>Title:</th>
      <td>{{ $article->title }}</td>
    </tr>
    <tr>
      <th>Author:</th>
      <td>{{ $article->author }}</td>
    </tr>
    <tr>
      <th>Article Body:</th>
      <td>{{ $article->body }}</td>
    </tr>
    <tr>
      <th>Homepage:</th>
      <td>{{ $article->url }}</td>
    </tr>
  </tbody>
</table>

<br/>
<a href="/show-articles">View All</a> -
<a href="/update-article/{{ $article->id }}">Modify</a>

You can now test the app, issue the following command and navigate to /create-article:

$ php artisan serve

If you need to take a look at the full code, you can refer to this GitHub repo: https://github.com/mirkobenedetti/laravel_tutorial.

We can now make a quick comparison with the Symfony way, explained in this previuos tutorial https://www.benedict.cloud/2018/05/02/easy-symfony-tutorial-on-crud-operations.

Far from me to begin a war of opinions, it has to be said that the heavy usage by Laravel of traits and closures makes it more elegant, concise and easier to understand. Symfony is older and has a better documentation.

That’s all for now, in this tutorial we introduced Laravel and made a quick comparison with Symfony. Stay tuned for the next episode.

Did you like this post? Please share it on your preferred social network, thank you!