laravel + livewire + tailwind で webカンファレンス - admin

(2025-01-04)

admin の導入

admin を導入します。

とりあえず、admin からメンバーの作成をしたいと思います。

php artisan make:middleware AdminMiddleware

編集

app/Http/Middleware/AdminMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Middleware\AdminMiddleware;
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// ユーザーがログインしていない場合、またはロールが admin でない場合
if (Auth::check() && Auth::user()->role !== 'admin') {
return redirect('/'); // ホームページにリダイレクト
}
return $next($request);
}
}

seeder によるデータ挿入

seeder はとても便利なものです。

データベースは sqlite なので混乱してきたら削除して、マイグレーションと seeder によってデータベースを復旧します。

php artisan make:seeder AdminUserSeeder

database/seeders/AdminUserSeeder.php

database/seeders/AdminUserSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
class AdminUserSeeder extends Seeder
{
public function run()
{
// 管理者ユーザーを作成
User::create([
'name' => 'Admin User',
'email' => 'admin@example.com',
'password' => Hash::make('password'), // 管理者のパスワード
'role' => 'admin', // 管理者ロールを設定
]);
}
}

ここでは admin だけを書き込みます。

php artisan db:seed --class=AdminUserSeeder

AdminDashboard の livewire コンポーネント作成

php artisan make:livewire Admin/AdminDashboard

編集

resources/views/livewire/admin/admin-dashboard.blade.php
<div class="p-4">
<h1 class="text-xl font-bold mb-4 border border-gray-500 bg-slate-200 px-4 py-2">管理者ダッシュボード</h1>
<p class="border border-slate-300 p-3 rounded mb-5 shadow-md bg-white">
ここで管理者用の情報を管理できます。<br>
以下のメニューから選びます。
</p>
<a href="{{ route('admin.create-member') }}" class="btn btn-primary px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">メンバー作成</a>
</div>

CreateMember の livewire コンポーネント作成

メンバーを生成する権限は admin にだけ与えられるべきです。

php artisan make:livewire Admin/CreateMember

編集

app/Livewire/Admin/CreateMember.php
<?php
namespace App\Livewire\Admin;
use Livewire\Component;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
class CreateMember extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
public function submit()
{
$this->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:4|confirmed',
]);
User::create([
'name' => $this->name,
'email' => $this->email,
'password' => Hash::make($this->password),
]);
session()->flash('message', 'メンバーが作成されました!');
return redirect()->route('admin.create-member');
}
public function render()
{
$members = User::all(); // 全メンバーを取得
return view('livewire.admin.create-member', ['members' => $members]);
}
}

blade 編集

resources/views/livewire/admin/create-member.blade.php
<div class="p-4">
<h1 class="text-xl font-bold mb-4 border border-gray-500 bg-slate-200 px-4 py-2">メンバー作成</h1>
@if (session()->has('message'))
<div class="p-4 bg-green-200 text-green-800 mb-4">
{{ session('message') }}
</div>
@endif
<form wire:submit.prevent="submit" class="mb-6">
<div class="mb-4">
<label for="name" class="block">名前</label>
<input type="text" id="name" wire:model="name" class="border rounded p-2 w-96">
@error('name') <span class="text-red-600">{{ $message }}</span> @enderror
</div>
<div class="mb-4">
<label for="email" class="block">メールアドレス</label>
<input type="email" id="email" wire:model="email" class="border rounded p-2 w-96">
@error('email') <span class="text-red-600">{{ $message }}</span> @enderror
</div>
<div class="mb-4">
<label for="password" class="block">パスワード</label>
<input type="password" id="password" wire:model="password" class="border rounded p-2 w-96">
@error('password') <span class="text-red-600">{{ $message }}</span> @enderror
</div>
<div class="mb-4">
<label for="password_confirmation" class="block">パスワード確認</label>
<input type="password" id="password_confirmation" wire:model="password_confirmation" class="border rounded p-2 w-96">
</div>
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded">作成</button>
</form>
<h2 class="text-lg font-bold mb-4 border border-gray-300 bg-blue-50 px-4 py-2">メンバー一覧</h2>
<table class="border-collapse border border-gray-600 text-left">
<thead>
<tr>
<th class="border border-gray-300 px-4 py-2 bg-sky-900 text-white">名前</th>
<th class="border border-gray-300 px-4 py-2 bg-sky-900 text-white">メールアドレス</th>
<th class="border border-gray-300 px-4 py-2 bg-sky-900 text-white">ロール</th>
<th class="border border-gray-300 px-4 py-2 bg-sky-900 text-white">作成日</th>
</tr>
</thead>
<tbody>
@foreach ($members as $member)
<tr>
<td class="border border-gray-300 px-4 py-2">{{ $member->name }}</td>
<td class="border border-gray-300 px-4 py-2">{{ $member->email }}</td>
<td class="border border-gray-300 px-4 py-2">{{ $member->role }}</td>
<td class="border border-gray-300 px-4 py-2">{{ $member->created_at->format('Y-m-d') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>

一般の dashboard.php を書き換えます。

/views/dashboard.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">{{ __('Menu') }}</h2>
<ul class="list-disc leading-10 mx-10 px-2">
<li class="text-blue-800 hover:text-orange-800 delay-150"><a href="{{ route('theme.list') }}">テーマ一覧</a></li>
<li class="text-blue-800 hover:text-orange-800 delay-150"><a href="{{ route('theme.create') }}">テーマ作成</a></li>
<li class="text-blue-800 hover:text-orange-800 delay-150"><a href="{{ route('zip.image') }}">画像アップロード</a></li>
<li class="text-blue-800 hover:text-orange-800 delay-150"><a href="{{ route('admin.dashboard') }}">管理者用サイト</a></li>
</ul>
</x-slot>
</x-app-layout>

bootstrap/app.php の編集

今回最もわけがわからないのは、この部分です。

chatGPT は外しまくりました。何回かトライするうちに成功したという感じです。

bootstrap/app.php
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use App\Http\Middleware\AdminMiddleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(at: '*'); // プロキシ設定
// グローバルミドルウェアを登録
$middleware->use([
App\Http\Middleware\AdminMiddleware::class, // 必要であれば追加
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})
->create();

ルーティング

routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Livewire\ThemeCreate;
use App\Livewire\ThemeList;
use App\Livewire\ThemeShow;
use App\Livewire\ZipImage;
use App\Livewire\ThemeImage;
use App\Http\Middleware\AdminMiddleware;
use App\Livewire\Admin\AdminDashboard;
use App\Livewire\Admin\CreateMember;
use App\Http\Controllers\ProfileController;
Route::get('/', function () {
return view('welcome');
})->name('home');
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
Route::middleware('auth')->group(function () {
Route::get('/theme/create', ThemeCreate::class)->name('theme.create');
Route::get('/theme/list', ThemeList::class)->name('theme.list');
Route::get('/theme/{theme_id}', ThemeShow::class)->name('theme.show');
Route::get('/zip-image', ZipImage::class)->name('zip.image');
Route::get('/theme/{theme_id}/images/{folderName?}', ThemeImage::class)->name('theme.image');
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
Route::middleware(['auth', AdminMiddleware::class])->group(function () {
Route::get('/admin/dashboard', AdminDashboard::class)->name('admin.dashboard');
Route::get('/admin/create-member', \App\Livewire\Admin\CreateMember::class)->name('admin.create-member');
});
require __DIR__.'/auth.php';

tailwind のビルドと起動

cd ~/laraconf
php artisan config:clear
php artisan cache:clear
npm run build
php artisan serve

一般 user はメンバー作成はできない

一般メンバーが、admin-dashboard.blade.php にアクセスできないことを確認しておきます。

register の削除

admin が作成されたので、メンバーの登録などはそちらで実行できるようになりました。

なので register 関連を削除します。

まず、welcome.blade.php から register の部分を削除します。

その他、以下のファイルを削除します。

  1. resources/views/auth/register.blade.php
  2. app/Http/Controllers/Auth/RegisteredUserController.php
  3. tests/Feature/Auth/RegistrationTest.php