Laravel 9 CRUD app using Splade

In Laravel landscape, Blade templating engine has been the tool of choice when it comes to developing frontends of traditional webapps. However, with the explosion of Single Page Applications (SPAs) more and more options came into play in Laravel frontend development; people have been coming up with a number of smart solutions like Livewire, Inertia.js etc in order to provide SPA functionality with minimum headache. Another fresh entry into this foray is Splade which makes it a breeze to get SPA look and feel while remaining within Blade templating engine.

Splade employs Vue components behind the scenes and provide a comforting way to embed most of the dynamic functionality with minimum efforts. So, let’s create a Laravel 9 CRUD app using Splade to understand its mechanics.

Laravel 9.x requires a minimum PHP version of 8.0. This tutorial assumes that you are using Linux, MacOS or WSL on Windows and Node.js, Composer and PHP 8 along with required modules i.e bcmatch, sqlite, mbstring, xml, zip, gd, mcrypt are properly installed. Also make sure that SQLite is installed as we’ll be using SQLite to keep things simple and quick; you may use MySQL or PostgreSQL as you like, however make sure the corresponding PHP module is installed too.

Using Composer, enter following command in terminal to install Laravel 9;

composer create-project laravel/laravel app 9.*

Execute following command to go inside app folder:

cd app

Now add Splade by executing following command:

composer require protonemedia/laravel-splade-breeze

Then execute following command to install the package:

php artisan breeze:install

Run Vite dev server by executing following command:

npm run dev

The above command will start the Vite dev server which will provide hot reload functionality for any change in source code. Therefore, open another terminal window to enter further commands. When you are done, you’d finally execute ‘npm run build’ in order to get production ready build.

Next, setup database and Laravel environment file. Here, I’m configuring SQLite database for simplicity purposes. Being inside parent directory (app), execute following command to create new SQLite database file;

touch database/database.sqlite

Then find .env config file in the parent directory (app), open it and change DB_CONNECTION line as follows;

DB_CONNECTION = sqlite

Remove DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD from .env since we are using SQLite database.

Since, initial setup of Laravel app is complete, we can move towards MVC (Model, View, Controller). First enter the following command in parent directory to create Post model along with the migration:

php artisan make:model Post -m

Open newly created migration file database/migrations/(date_stamp)_create_posts_table.php and then insert the table fields as follows;

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('posts');
    }
};

Enter following command in parent directory to migrate the above migration;

php artisan migrate

Now, open app/Models/Post.php model file and insert protected fillable array as follows;

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = [
        'title', 'content'
    ];
}

Having done with the Model part of our app, we move onto Controller. Execute following command in parent folder to create PostController.php;

php artisan make:controller PostController --resource

Go ahead and open this controller file which is located at app/Http/Controllers/PostController.php and amend it as follows in order to define basic CRUD (Create, Read, Update, Delete) functions;

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Request;
use App\Models\Post;
use ProtoneMedia\Splade\SpladeTable;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();
        return view('posts.index', [
            'posts' => SpladeTable::for(Post::class)
                ->defaultSort('id')
                ->column(key: 'id', sortable: true)
                ->column(key: 'title', searchable: true, sortable: true)
                ->column(key: 'content', searchable: true, sortable: true)
                ->column(label: 'Actions')
                ->paginate(5),
            ]);
    }

    public function create()
    {
        return view('posts.create');
    }

    public function store()
    {
        Post::create(
            Request::validate([
            'title' => ['required', 'max:50'],
            'content' => ['required'],
            ])
        );
        return redirect()->route('posts.index')->with('message', 'Post created.');
    }

    public function edit(Post $post)
    {
        return view('posts.edit', compact('post'));
    }

    public function update(Post $post)
    {
        $post->update(
            Request::validate([
            'title' => ['required', 'max:50'],
            'content' => ['required'],
            ])
        );

        return redirect()->route('posts.index')->with('message', 'Post updated.');
    }

    public function destroy(Post $post)
    {
        $post->delete();
        return redirect()->route('posts.index')->with('message', 'Post deleted.');
    }
}

Next, open routes/web.php and put the following line at the upper side of it;

use App\Http\Controllers\PostController;

And then insert PostController resource route inside auth middleware group as given below;

//...
Route::middleware('auth')->group(function () {
    //...
    Route::resource('posts', PostController::class);
});

We’re done with the Model and Controller parts of the app. Now let’s create Views using Blade templates.

First, create folder posts inside resources/views. Remaining in parent directory, you may execute following command to create this folder;

mkdir resources/views/posts 

Now, create following three files inside resources/views/posts folder:

  1. index.blade.php
  2. create.blade.php
  3. edit.blade.php

You can execute following command inside parent directory to create these files in one go;

touch resources/views/posts/{index,create,edit}.blade.php

Now, insert following code inside index.blade.php;

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Posts') }}
        </h2>
    </x-slot>
    <x-splade-flash>
        <p v-if="flash.has('message')" v-text="flash.message" />
    </x-splade-flash>
    <div>
        <div class="m-2">
            <div class="p-2">
                <Link modal href="{{ route('posts.create') }}" class="px-4 py-1 bg-gray-100 border border-gray-400 rounded-md text-gray-600 hover:bg-gray-200">New Post</Link>
            </div>
        </div>
    </div>
    <x-splade-table :for="$posts">
        <x-splade-cell actions>
            <Link modal href="{{ route('posts.edit', $item->id) }}" class="px-4 py-1 bg-indigo-100 border border-indigo-400 rounded-md text-indigo-600 hover:bg-indigo-200 mr-4"> Edit </Link>
            <Link href="{{ route('posts.destroy', $item->id) }}" method="DELETE" class="px-4 py-1 bg-red-100 border border-red-400 rounded-md text-red-600 hover:bg-red-200"> Delete </Link>
        </x-splade-cell>
    </x-splade-table>
</x-app-layout>

Then, insert following code inside create.blade.php;

<x-splade-modal>
    <x-splade-form>
        <x-splade-input name="title" placeholder="title" :label="__('Title')"/>
        <x-splade-input name="content" placeholder="type here" :label="__('Content')"/>
        <x-splade-submit class="mt-3" :label="__('Add Post')" />
    </x-splade-form>
</x-splade-modal>

And then insert following code inside edit.blade.php;

<x-splade-modal>
    <x-splade-form :default="$post" action="{{ route('posts.update', $post->id) }}" method="PUT">
        <x-splade-input name="title" :label="__('Title')"/>
        <x-splade-input name="content" :label="__('Content')"/>
        <x-splade-submit class="mt-3" :label="__('Submit')" />
    </x-splade-form>
</x-splade-modal>

Finally, enter following command to start PHP development server;

php artisan serve

Enter following URL in the browser:

http://localhost:8000

Then register a new user and after login, enter following URL in the browser and test CRUD functions;

http://localhost:8000/posts

2 thoughts on “Laravel 9 CRUD app using Splade”

  1. Thank you so much for sharing, I have a question,
    Let´s pretend that there is a show.blade

    I would like to send certain value with an event like “Onclick” button to the controller

    In the controller, I have the method:
    public function UpdateStatus(){
    // $request->status etc..
    }

    I tried using axios, either with x-splade-script, x-splade-emit, also with a function in my js file imported to Bootstrap.
    Without Succes..
    How could I send a post request with data included and receive the response using Splade?

    Reply
    • Thank you for comments.
      Data can be passed to controller by using :data attribute in x-splade-link e.g.,

      … href=”/updatestatus” method=”POST” :data=”[‘status’ => ‘done’]” …

      Don’t forget ‘:’ before ‘data’, otherwise data would be parsed by Vue instead of PHP.
      For further explanation, please visit:
      https://splade.dev/docs/x-link

      Reply

Leave a Comment