laravel12 livewire book draft

はじめに
かつてbootcamp.laravel.comというサイトでchiper
というtwitter的に一言だけ残せるwebサービスを作るチュートリアルが掲示されていたのだが、laravel12の内容と適合しなくなったのか消滅してしまった。ここではその内容をwebarchiveより復活させ、さらにはlaravel12 starter kitsをvscodeで編集するというアレンジも加えた内容で再編集した。

gitリポジトリのclone
ある程度laravel12の環境でlivewireを使えるように仕込んでおいたリポジトリを用意したので
https://github.com/catatsumuri/laravel12-livewire-init.git
これをcloneする。
接続までの準備
cloneしたら .env.example を .env にリネームする
さらにcomposer installする。
composer install
これでようやく接続できるようになるので
ここから接続する
ブラウザーからの確認
成功すると、このようにキーのエラーになる。ここでターミナルから
php artisan key:generate
する
リロードするとエラーになる
これはsessionをDBに保存しにいっているのだが、当該テーブルが無い
php artisan migrate
で解決する
あるいは、 .env のSESSION_DRIVER
をfile
にしちゃうのも手っちゃ手だ。開発はこっちの方が楽かも。
ただ、どのみちログインしないといけないのでmigrateは必須
さらにログインしようと思うと
このように
Vite manifest not found at: /var/www/html/public/build/manifest.json
になる。これはターミナルでnpm installして
npm run dev
しないといけない
そうすればログイン画面が見えるはずで、ここで
- test@example.com
- password
でログインするのだが、seedを入れてなかったので
php artisan migrate:fresh --seed
を再実行すればログインできる
ここまで出来ないと次に進めないので、これは何とかして環境構築して欲しい

Chirpの作成
モデルとDBの設定
ターミナルよりartisanを起動する
php artisan make:model -mc Chirp
-mc オプションによりマイクレーションとコントローラも作成される。viewを作成してないあたりがポイントにもなる
migrationとモデルの更新
以下のように作成されたマイグレーションを変更する
ctrl+pを使うとはやいかも
@@ -13,6 +13,8 @@ public function up(): void
{
Schema::create('chirps', function (Blueprint $table) {
$table->id();
+ $table->foreignId('user_id')->constrained()->cascadeOnDelete();
+ $table->string('message');
$table->timestamps();
});
}
さらにリレーションも変更
@@ -7,6 +7,7 @@
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
+use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Authenticatable
{
@@ -57,4 +58,9 @@ public function initials(): string
->map(fn (string $name) => Str::of($name)->substr(0, 1))
->implode('');
}
+
+ public function chirps(): HasMany
+ {
+ return $this->hasMany(Chirp::class);
+ }
}
@@ -3,8 +3,12 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Chirp extends Model
{
- //
+ public function user(): BelongsTo
+ {
+ return $this->belongsTo(User::class);
+ }
}
これでUser<->ChirpにおいてbelongsTo
とhasMany
それぞれの関係が確立された
massアサイメントの対応
Chirpにはmessage
を保存するのでこれをfillable
プロパティにセットする
@@ -7,6 +7,11 @@
class Chirp extends Model
{
+ protected $fillable = [
+ 'user_id',
+ 'message',
+ ];
+
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
この状態で一度migrateし直す
php artisan migrate:fresh --seed
livewireコンポーネントの挿入
今index.blade.phpの中に、livewireコンポーネントを利用してつぶやきのフォームを挿入する。createに移動するタイプではなくindexからそのまま送信するタイプである。
resources/views/chirps/index.blade.php
@@ -1,5 +1,5 @@
<x-layouts.app :title="__('Dashboard')">
<div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8">
- <h1>Chirps Index</h1>
+ <livewire:chirps.create />
</div>
</x-layouts.app>
このように変更すると即座にエラーとなる
chirps.createコンポーネントを作成する
これは make:volt
を利用する
php artisan make:volt chirps/create --class
この時点でエラーが解消されるが、謎の「 // 」が現われる
謎の「 // 」
このコンポーネント自体は resources/views/livewire/chirps/create.blade.php に配置される
<?php
use Livewire\Volt\Component;
new class extends Component {
//
}; ?>
<div>
//
</div>
こんな状態になっているので //
が表示されているというわけだ。これを以下のように修正していく

フロントエンドの開発
ここまででバックエンド側は大体整ったので、いよいよ保存できるようにしていく。今のdashboardは以下のように見えているかと思う
Chirpへの動線
dashboardを取り壊して書けるようにしてもいいのだけど、ここではChirpへ動けるように新たにメニュー作成し、そこで出来るようにする。これは resources/views/components/layouts/app/sidebar.blade.php で定義されているので、これを弄る必要がある。
ここでは折り返されているが、このあたりにメニューの記述がある
ここで以下のようにする
<flux:navlist.group :heading="__('Platform')" class="grid">
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
<flux:navlist.item icon="home" :href="route('chirps')" :current="request()->routeIs('chirps')" wire:navigate>{{ __('Chirp') }}</flux:navlist.item>
</flux:navlist.group>
するとchirps
というrouteがないので即座にエラーとなる
routeの追加
ここでroutes/web.phpに以下を追加する
@@ -1,5 +1,6 @@
<?php
+use App\Http\Controllers\ChirpController;
use Illuminate\Support\Facades\Route;
use Livewire\Volt\Volt;
@@ -19,4 +20,8 @@
Volt::route('settings/appearance', 'settings.appearance')->name('settings.appearance');
});
+Route::get('chirps', [ChirpController::class, 'index'])
+ ->middleware(['auth', 'verified'])
+ ->name('chirps');
+
require __DIR__.'/auth.php';
これで一応は表示されるがアイコンがhomeだ
ここでは https://lucide.dev/icons/message-circle-more これを利用する
まずartisanで
php artisan flux:icon message-circle-more
とかしておいて、
<flux:navlist.item icon="message-circle-more" ...
message-circle-more
に変更すればok
アイコンが変わった
indexの作成
この状態でChirpメニューを押すとやはりエラーとなる
というわけでindexを作成していく
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\View\View;
class ChirpController extends Controller
{
public function index(Request $request): View
{
return view('chirps.index', []);
}
}
このように書いたらchirps.indexが存在しないので views/chirps/index.blade.php を作成する。ディレクトリが無いのでそれは作ること
<x-layouts.app :title="__('Dashboard')">
<div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8">
<h1>Chirps Index</h1>
</div>
</x-layouts.app>
すると、以下のように修正されてくるはずだ
フォームの描画とメッセージの保存
@@ -3,9 +3,39 @@
use Livewire\Volt\Component;
new class extends Component {
- //
+ public string $message = '';
+
+ public function store(): void
+ {
+ dd($this->message);
+ }
}; ?>
-<div>
- //
-</div>
+<div class="flex flex-col gap-6">
+
+ <x-auth-session-status class="text-center" :status="session('status')" />
+
+ <form wire:submit="store" class="flex flex-col gap-6">
+ <flux:textarea
+ wire:model="message"
+ name="message"
+ placeholder="{{ __('What\'s on your mind?') }}"
+ {{-- required --}}
+ class="w-full"
+ />
+
+ <div class="flex items-center justify-end">
+ <flux:button variant="primary" type="submit">
+ {{ __('Chirp') }}
+ </flux:button>
+ </div>
+ </form>
+</div>
とするとフォームが描画される
テスト、と入力するとdd()
により出力がdumpされる
このように、livewireの場合createのコンポーネントの中でstoreしてしまうという事を普通に行うようだ。
validationと保存
今、あえてrequired
をコメントアウトしているが、これでstoreからdd()
を削除し、以下のようにしてみる
@@ -7,8 +7,13 @@
public function store(): void
{
- dd($this->message);
- }
+ $this->validate([
+ 'message' => ['required', 'string', 'max:255'],
+ ]);
+
+ $this->message = '';
+ session()->flash('status', __('Chirp created successfully!'));
+ }
}; ?>
<div class="flex flex-col gap-6">
これはfluxの仕様でlabelが無いとどうやらエラーメッセージを出さないようなのでこれを利用する場合は何とかlabelを逐一書くようにしよう
<flux:textarea
wire:model="message"
name="message"
placeholder="{{ __('What\'s on your mind?') }}"
:label="__('Chirp')"
{{-- required --}}
class="w-full"
/>
エラーメッセージが表示された
実際に保存する
あとは保存するだけ
public function store(): void
{
$validated = $this->validate([
'message' => ['required', 'string', 'max:255'],
]);
// 保存
auth()->user()->chirps()->create($validated);
$this->message = '';
session()->flash('status', __('Chirp created successfully!'));
}
これで保存できる
保存されたようだ
保存を確認する
コンソールでまず
composer dump-autoload
としたのち
php artisan tinker
するとtinkerのシェルに入れるので
Chirp::all()
とすると以下のように保存が確認できる
アトリビュートベースバリデーションへ
一応ほらphpの新しい構文推しみたいなんで、
@@ -1,15 +1,15 @@
<?php
use Livewire\Volt\Component;
+use Livewire\Attributes\Validate;
new class extends Component {
+ #[Validate('required|string|max:255')]
public string $message = '';
public function store(): void
{
- $validated = $this->validate([
- 'message' => ['required', 'string', 'max:255'],
- ]);
+ $validated = $this->validate();
auth()->user()->chirps()->create($validated);
個人的には超絶可読性が悪くなるようにおもえてならないが、ここではbootcampのクローンを目指すので紹介しないわけにはいかない。一応validationが効いている事を確認したらformのrequiredのコメントアウトは取り払っておくこと(後でちゃんとテストも書く)
@@ -28,7 +28,7 @@ public function store(): void
name="message"
placeholder="{{ __('What\'s on your mind?') }}"
:label="__('Chirp')"
- {{-- required --}}
+ required
class="w-full"
/>
次はContinue to start showing Chirps...

Chirp の作成ができるようになったので、次はそれらを画面に表示する
chirps.blade.php を更新して、Chirp の一覧を表示できるように
resources/views/chirps/index.blade.php へ投稿を表示するlivewireコンポーネントを挿入する
@@ -1,5 +1,6 @@
<x-layouts.app :title="__('Dashboard')">
<div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8">
<livewire:chirps.create />
+ <livewire:chirps.list />
</div>
</x-layouts.app>
即座にmake:volt
する
php artisan make:volt chirps/list --class
そうしたらresources/views/livewire/chirps/list.blade.phpを編集する
記事を取ってdd()する
ここではlivewireコンポーネントが最初に実行されるmount()
というメソッドを書いていく
@@ -1,9 +1,22 @@
<?php
use Livewire\Volt\Component;
+use App\Models\Chirp;
+use Illuminate\Database\Eloquent\Collection;
new class extends Component {
- //
+
+ public Collection $chirps;
+
+ public function mount(): void
+ {
+ $this->chirps = Chirp::with('user')
+ ->latest()
+ ->get();
+
+ dd($this->chirps);
+ }
+
}; ?>
<div>
この段階で画面は以下のようになるだろう
ddを解除して、記事をloop表示
以下のようにする
@@ -14,11 +14,25 @@ public function mount(): void
->latest()
->get();
- dd($this->chirps);
}
}; ?>
-<div>
- //
-</div>
+<div class="mt-6 bg-white shadow-sm rounded-lg divide-y">
+ @foreach ($chirps as $chirp)
+ <div class="p-6 flex space-x-2" wire:key="{{ $chirp->id }}">
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-600 -scale-x-100" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
+ <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
+ </svg>
+ <div class="flex-1">
+ <div class="flex justify-between items-center">
+ <div>
+ <span class="text-gray-800">{{ $chirp->user->name }}</span>
+ <small class="ml-2 text-sm text-gray-600">{{ $chirp->created_at->format('j M Y, g:i a') }}</small>
+ </div>
+ </div>
+ <p class="mt-4 text-lg text-gray-900">{{ $chirp->message }}</p>
+ </div>
+ </div>
+ @endforeach
+</div>
すると、なかなかそれっぽいものが出来あがってくる
Livewire イベントを使って、Chirp 作成時に一覧を更新する
ここで新しく投稿するとわかるんだけど
新しい投稿を行っても記事が再描画されない。これを何とかする
resources/views/livewire/chirps/create.blade.php
@@ -14,6 +14,7 @@ public function store(): void
auth()->user()->chirps()->create($validated);
$this->message = '';
+ $this->dispatch('chirp-created');
session()->flash('status', __('Chirp created successfully!'));
}
}; ?>
このようにchirp-created
という名前のイベントをdispatch()
している。この段階では何もおきないのだが、これをlistで受けとる
@@ -3,6 +3,7 @@
use Livewire\Volt\Component;
use App\Models\Chirp;
use Illuminate\Database\Eloquent\Collection;
+use Livewire\Attributes\On;
new class extends Component {
@@ -10,12 +11,15 @@
public function mount(): void
{
- $this->chirps = Chirp::with('user')
- ->latest()
- ->get();
-
+ $this->getChirps();
}
+ #[On('chirp-created')]
+ public function getChirps(): void
+ {
+ $this->chirps = Chirp::with('user')->latest()->get();
+ }
+
}; ?>
<div class="mt-6 bg-white shadow-sm rounded-lg divide-y">
見ての通りアトリビュート使っていたりして非常にクセツヨの構文であるが、、、いずれにせよこれで記事が更新されるようにはなった

編集
ownerとログインuser idが一致している時に編集できるようにする
listの更新
記事のownerとログインuidの比較を書いてdropdownを出している。結構長い
@@ -19,6 +19,12 @@ public function getChirps(): void
{
$this->chirps = Chirp::with('user')->latest()->get();
}
+
+ public function edit(int $chirpId): void
+ {
+ dd('Edit chirp with ID: ' . $chirpId);
+ }
+
}; ?>
<div class="mt-6 bg-white shadow-sm rounded-lg divide-y">
@@ -33,6 +39,22 @@ public function getChirps(): void
<span class="text-gray-800">{{ $chirp->user->name }}</span>
<small class="ml-2 text-sm text-gray-600">{{ $chirp->created_at->format('j M Y, g:i a') }}</small>
</div>
+ @if ($chirp->user->is(auth()->user()))
+ <flux:dropdown position="bottom" align="end">
+ <flux:button variant="ghost" size="sm">
+ <flux:icon name="ellipsis-horizontal" class="h-4 w-4" />
+ </flux:button>
+
+ <flux:menu>
+ <flux:menu.item wire:click="edit({{ $chirp->id }})">
+ {{ __('Edit') }}
+ </flux:menu.item>
+ <flux:menu.item variant="danger" wire:click="delete({{ $chirp->id }})">
+ {{ __('Delete') }}
+ </flux:menu.item>
+ </flux:menu>
+ </flux:dropdown>
+ @endif
</div>
<p class="mt-4 text-lg text-gray-900">{{ $chirp->message }}</p>
</div>
deleteも書いてるけどまだ動作はしない
editを推すとdd()
に移動したことが理解できるようにしてある
実際の編集処理
@@ -8,6 +8,7 @@
new class extends Component {
public Collection $chirps;
+ public ?Chirp $editing = null;
public function mount(): void
{
@@ -20,9 +21,10 @@ public function getChirps(): void
$this->chirps = Chirp::with('user')->latest()->get();
}
- public function edit(int $chirpId): void
+ public function edit(Chirp $chirp): void
{
- dd('Edit chirp with ID: ' . $chirpId);
+ $this->editing = $chirp;
+ $this->getChirps();
}
}; ?>
@@ -56,7 +58,11 @@ public function edit(int $chirpId): void
</flux:dropdown>
@endif
</div>
- <p class="mt-4 text-lg text-gray-900">{{ $chirp->message }}</p>
+ @if ($chirp->is($editing))
+ ここに編集フォームを追加
+ @else
+ <p class="mt-4 text-lg text-gray-900">{{ $chirp->message }}</p>
+ @endif
</div>
</div>
@endforeach
こんな感じにしてEdit
を押すとこんな具合に変化する
ここに編集フォームを追加 を実際のformに置き換える
これもまたlivewireコンポーネントを使う
@@ -59,7 +59,7 @@ public function edit(Chirp $chirp): void
@endif
</div>
@if ($chirp->is($editing))
- ここに編集フォームを追加
+ <livewire:chirps.edit :chirp="$chirp" :key="$chirp->id" />
@else
<p class="mt-4 text-lg text-gray-900">{{ $chirp->message }}</p>
@endif
としたら即座にmake:vold
する
php artisan make:volt chirps/edit --class
resources/views/livewire/chirps/edit.blade.phpが出来るので、これを手直ししていく
まずcancel処理から
@@ -1,11 +1,55 @@
<?php
use Livewire\Volt\Component;
+use App\Models\Chirp;
+use Livewire\Attributes\Validate;
new class extends Component {
- //
+ public Chirp $chirp;
+ public string $message = '';
+
+ public function mount(): void
+ {
+ $this->message = $this->chirp->message;
+ }
+
+ public function cancel(): void
+ {
+ $this->dispatch('chirp-edit-canceled');
+ }
}; ?>
<div>
- //
+ <form wire:submit="update">
+ <flux:textarea
+ wire:model="message"
+ name="message"
+ placeholder="{{ __('What\'s on your mind?') }}"
+ :label="__('Chirp')"
+ required
+ class="w-full"
+ />
+ {{--
+ <button class="mt-4">{{ __('Save') }}</button>
+ --}}
+ <flux:button variant="outline" wire:click.prevent="cancel">
+ {{ __('Cancel') }}
+ </flux:button>
+
+ </form>
</div>
これによりCancel
ボタンが押されると
$this->dispatch('chirp-edit-canceled');
によりchirp-edit-canceled
イベントが発行されるのでこれをlist.blade.phpで掴まえる
resources/views/livewire/chirps/list.blade.php
@@ -27,6 +27,15 @@ public function edit(Chirp $chirp): void
$this->getChirps();
}
+ #[On('chirp-edit-canceled')]
+ public function disableEditing(): void
+ {
+ $this->editing = null;
+
+ $this->getChirps();
+ }
+
}; ?>
<div class="mt-6 bg-white shadow-sm rounded-lg divide-y">
編集処理
ではCancel
がうまくいったのでSave
ボタンを付けて編集できるように
@@ -1,11 +1,50 @@
<?php
use Livewire\Volt\Component;
+use App\Models\Chirp;
+use Livewire\Attributes\Validate;
new class extends Component {
- //
+ public Chirp $chirp;
+
+ #[Validate('required|string|max:255')]
+ public string $message = '';
+
+ public function mount(): void
+ {
+ $this->message = $this->chirp->message;
+ }
+
+ public function update(): void
+ {
+ // $this->authorize('update', $this->chirp);
+ $validated = $this->validate();
+ $this->chirp->update($validated);
+ $this->dispatch('chirp-updated');
+ }
+
+ public function cancel(): void
+ {
+ $this->dispatch('chirp-edit-canceled');
+ }
}; ?>
<div>
- //
+ <form wire:submit="update">
+ <flux:textarea
+ wire:model="message"
+ name="message"
+ placeholder="{{ __('What\'s on your mind?') }}"
+ :label="__('Chirp')"
+ {{-- required --}}
+ class="w-full"
+ />
+
+ <flux:button variant="primary" type="submit">
+ {{ __('Save') }}
+ </flux:button>
+ <flux:button variant="outline" wire:click.prevent="cancel">
+ {{ __('Cancel') }}
+ </flux:button>
+ </form>
</div>
編集するとまたchirp-updated
というイベントが飛ぶのでlistでそのイベントを受信する
@@ -28,6 +28,7 @@ public function edit(Chirp $chirp): void
}
#[On('chirp-edit-canceled')]
+ #[On('chirp-updated')]
public function disableEditing(): void
{
$this->editing = null;
これで更新できるはずだ
authorization
laravelはポリシーの機能で
$this->authorize('update', $this->chirp);
対象のオブジェクトに対してどういう操作が出来るのかというのをモデルに定義できる。これを行うにはmake:policy
する
php artisan make:policy ChirpPolicy --model=Chirp
するとapp/Policies/ChirpPolicy.phpが出来る。defaultは全て拒否なので正しくupdate可能なルールを定義してあげる
@@ -4,7 +4,6 @@
use App\Models\Chirp;
use App\Models\User;
-use Illuminate\Auth\Access\Response;
class ChirpPolicy
{
@@ -37,7 +36,7 @@ public function create(User $user): bool
*/
public function update(User $user, Chirp $chirp): bool
{
- return false;
+ return $chirp->user()->is($user);
}
編集されたかどうかマーカーを付ける
最後に
@@ -48,6 +48,9 @@ public function disableEditing(): void
<div>
<span class="text-gray-800">{{ $chirp->user->name }}</span>
<small class="ml-2 text-sm text-gray-600">{{ $chirp->created_at->format('j M Y, g:i a') }}</small>
+ @unless ($chirp->created_at->eq($chirp->updated_at))
+ <small class="text-sm text-gray-600"> · {{ __('edited') }}</small>
+ @endunless
</div>
@if ($chirp->user->is(auth()->user()))
<flux:dropdown position="bottom" align="end">
これは正直やるならもう少し見た目を詰めてもいいかも

Chirps を削除する
削除ボタンについて
既にlist.blade.phpには削除ボタンが付いてはいるのだが
@if ($chirp->user->is(auth()->user()))
<flux:dropdown position="bottom" align="end">
<flux:button variant="ghost" size="sm">
<flux:icon name="ellipsis-horizontal" class="h-4 w-4" />
</flux:button>
<flux:menu>
<flux:menu.item wire:click="edit({{ $chirp->id }})">
{{ __('Edit') }}
</flux:menu.item>
<flux:menu.item variant="danger" wire:click="delete({{ $chirp->id }})">
{{ __('Delete') }}
</flux:menu.item>
</flux:menu>
</flux:dropdown>
@endif
クリックすると
Method or action [delete] does not exist on component [chirps.list].
となる。そこでdeleteメソッドを実装する
@@ -27,6 +27,14 @@ public function edit(Chirp $chirp): void
$this->getChirps();
}
+ public function delete(Chirp $chirp): void
+ {
+ dd($chirp);
+ }
+
#[On('chirp-edit-canceled')]
#[On('chirp-updated')]
public function disableEditing(): void
deleteを押した結果
よさそうなので実際に削除する
@@ -27,6 +27,13 @@ public function edit(Chirp $chirp): void
$this->getChirps();
}
+ public function delete(Chirp $chirp): void
+ {
+ $chirp->delete();
+ $this->getChirps(); // reload
+ session()->flash('status', __('Chirp deleted successfully!'));
+ }
削除できるようになった
authorize
ここでもdeleteの許可設定を行っておこう。条件はeditと全く同じでよいはずだ
@@ -29,6 +29,7 @@ public function edit(Chirp $chirp): void
public function delete(Chirp $chirp): void
{
+ $this->authorize('delete', $chirp);
$chirp->delete();
$this->getChirps();
session()->flash('status', __('Chirp deleted successfully!'));
@@ -44,7 +44,7 @@ public function update(User $user, Chirp $chirp): bool
*/
public function delete(User $user, Chirp $chirp): bool
{
- return false;
+ return $this->update($user, $chirp);
}
削除のconfirm
@@ -70,7 +70,7 @@ public function disableEditing(): void
<flux:menu.item wire:click="edit({{ $chirp->id }})">
{{ __('Edit') }}
</flux:menu.item>
- <flux:menu.item variant="danger" wire:click="delete({{ $chirp->id }})">
+ <flux:menu.item variant="danger" wire:click="delete({{ $chirp->id }})" wire:confirm="{{ __('Are you sure to delete this chirp?') }}">
{{ __('Delete') }}
</flux:menu.item>
</flux:menu>
wire:confirm=
を付けただけ

Notifications & Eventsは割愛
通知やeventに関して実は最後にいくつか書かれているのだけど、実装面でそこまで有意義と思えなかったので割愛。

git commit
このようにcopilot chatを開いて
Generate a commit message for the currently staged files in English.
とかやって生成してもらったらよい
基本的に Conventional Commitsに沿ってやってくれる
Generate a commit message following the Conventional Commits specification.
とかでもいいかも。まあchatは日本語でもいいすよ

テスト
現在のテストがまず通るか確認
基本的にdevコンテナー使ってる場合は何も考えずtestは通るはず
php artisan test
テストの準備
テストデーターはfactoryで作成する必要がある。ここではUser
のfactoryはdefaultで揃っているのだが、Chirp
のfactoryがないので作成する。
php artisan make:factory ChirpFactory --model=Chirp
するとこんな感じでfactoryが出来るので開いて編集
database/factories/ChirpFactory.php
@@ -2,6 +2,7 @@
namespace Database\Factories;
+use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
@@ -17,7 +18,8 @@ class ChirpFactory extends Factory
public function definition(): array
{
return [
- //
+ 'message' => $this->faker->sentence(),
+ 'user_id' => User::factory(),
];
}
}
ここではfactoryを生成すると自動的にユーザーも生成されるようになっているがまあこれは使い方次第で何とでもなるので、とりあえずこのようにしておく。