Let's try to create a simple CRUD for Tasks with two fields (for now): name
and is_completed
.
In this lesson, we'll manage the Model/Migration, Routes, and Controllers and add a navigation link in the top menu.
Preparing the Database
First, we create the DB structure with factories to create some fake records:
php artisan make:model Task -mf
The table structure is in Migration.
database/migrations/xxxx_create_tasks_table.php:
public function up(): void{ Schema::create('tasks', function (Blueprint $table) { $table->id(); $table->string('name'); $table->boolean('is_completed')->default(false); $table->timestamps(); });}
In the Model, we just make the fields fillable and cast is_completed
to boolean.
use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model; class Task extends Model{ use HasFactory; protected $fillable = [ 'name', 'is_completed' ]; protected function casts(): array { return [ 'is_completed' => 'boolean' ]; }}
Then, the Factory with the rules.
database/factories/TaskFactory.php:
class TaskFactory extends Factory{ public function definition(): array { return [ 'name' => fake()->words(asText: true), 'is_completed' => fake()->boolean(), ]; }}
Finally, that Factory should be used in the main seeder to create 10 fake task records.
database/seeders/DatabaseSeeder.php:
use App\Models\Task;use App\Models\User;// use Illuminate\Database\Console\Seeds\WithoutModelEvents;use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder{ public function run(): void { User::factory()->create([ 'name' => 'Test User', ]); Task::factory()->count(10)->create(); }}
And then we run the command:
php artisan migrate --seed
As a result, we have 10 records in the DB.
Livewire Component and Routes
We will create a Livewire component to manage the tasks with this command:
php artisan make:livewire Tasks/Index
Then, we assign that Component to the Routes.
routes/web.php:
use App\Livewire\Tasks; // ... Route::middleware(['auth'])->group(function () { Route::redirect('settings', 'settings/profile'); Route::get('settings/profile', Profile::class)->name('settings.profile'); Route::get('settings/password', Password::class)->name('settings.password'); Route::get('settings/appearance', Appearance::class)->name('settings.appearance'); Route::get('tasks', Tasks\Index::class)->name('tasks.index'); }); require __DIR__.'/auth.php';
Now, what's inside that Component?
We will fill it with the CRUD actions in the upcoming lessons. For now, Component only returns a View.
app/Livewire/Tasks/Index.php:
use Livewire\Component;use Illuminate\View\View; class Index extends Component{ public function render(): View { return view('livewire.tasks.index'); }}
In the View we need some dummy text.
resources/views/livewire/tasks/index.blade.php:
<section> The list will be here.</section>
Great, now how do we test if it works?
Let's add a menu item leading to the tasks.index
route.
Navigation Item
First, in order to add an icon to the navigation item we need import it using an Artisan command provided by Flux.
php artisan flux:icon briefcase
Now, we can add a link to the navigation and provide published icon.
resources/views/components/layouts/app/header.blade.php:
// ... <flux:navbar class="-mb-px max-lg:hidden"> <flux:navbar.item icon="layout-grid" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate> {{ __('Dashboard') }} </flux:navbar.item> <flux:navbar.item icon="briefcase" :href="route('tasks.index')" :current="request()->routeIs('tasks.*')" wire:navigate> {{ __('Tasks') }} </flux:navbar.item></flux:navbar> // ...
As a result, we have a menu on top, and if we click it, we see our component, with static text for now:
Great, we've created our first route and page outside the default starter kit!
In the next lesson, we will build the actual CRUD with all the Livewire components for it.
The repository for this starter kit project section is here on GitHub.
No comments yet…