laravelでユーザー・管理者を作ってみる
laravelでユーザ、管理者を作ったのでまとめてみる。
seederでのユーザ作成、登録・ログインの実装、ユーザー認証について記載します
バージョン
- laravel 12.0.1
マイグレーションとモデルファイル
Userテーブルの詳細は以下の通り
カラム | 詳細 |
---|---|
name | ユーザーの名前 |
ユーザーのメールアドレス | |
password | ユーザーのパスワード |
icon | ユーザーのアイコン |
is_admin | 管理者かどうか |
マイグレーションファイルは以下の通り
return new class extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('icon')->nullable();
$table->boolean('is_admin')->default(false);
$table->rememberToken();
$table->timestamps();
});
public function down(): void
{
Schema::dropIfExists('users');
}
};
モデルファイルの設定
class User extends Authenticatable
{
use HasFactory, Notifiable;
// カラムの追加
protected $fillable = [
'name',
'email',
'password',
'icon',
];
// 管理者チェック
public function isAdmin():bool
{
return $this->is_admin;
}
}
$fillable
によりカラムを追加することが可能になります
isAdmin()
で管理者ユーザーかどうかをチェックします
以下を実行してマイグレーション
php artisan migrate
seederからのユーザー作成
ファクトリ
次にseederとfactoryでデモユーザーと管理者ユーザを作ってみる
まずはデモユーザーから
以下のコマンドでシーダー、ファクトリの作成
php artisan make:seeder UsersTableSeeder
php artisan make:factory UserFactory
ファクトリではユーザの名前やemailなどのダミーを作成してくれます
iconはシーダーで追加するのでパス
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'password' => Hash::make('password'),
];
}
fake()
の主要なメソッドをchatgptに書いてもらいました
メソッド | 内容 | 例 |
---|---|---|
name | フルネームを生成 | John Doe |
firstName | 名のみを生成 | John |
lastName | 姓のみを生成 | Doe |
メールアドレスを生成 | john.doe@example.com | |
safeEmail | 安全なドメイン付きメールアドレス | jane.doe@example.org |
unique()->email | 重複しないメールアドレスを生成 | user123@example.com |
userName | ユーザー名を生成 | johndoe92 |
password | パスワードを生成(文字列) | secret123 |
sentence | 一文のテキストを生成 | Lorem ipsum dolor sit amet. |
paragraph | 複数文の段落を生成 | Lorem ipsum dolor sit amet... |
text | 任意長のテキストを生成 | Lorem ipsum dolor sit amet... |
numberBetween | 指定範囲の整数を生成 | faker->numberBetween(1, 100) → 57 |
randomDigit | 0〜9のランダムな数字を生成 | 7 |
randomFloat | ランダムな小数を生成 | faker->randomFloat(2, 1, 100) → 42.67 |
boolean | 真偽値を生成 | true / false |
date | 日付(Y-m-d)を生成 | 2025-04-29 |
dateTime | DateTimeオブジェクトを生成 | 2025-04-29 14:23:10 |
dateTimeBetween | 指定範囲内のDateTimeを生成 | faker->dateTimeBetween('-1 year', 'now') |
uuid | UUIDを生成 | 550e8400-e29b-41d4-a716-446655440000 |
url | URLを生成 | https://example.com |
imageUrl | ダミー画像URLを生成 | https://lorempixel.com/640/480/ |
phoneNumber | 電話番号を生成 | 090-1234-5678 |
address | 住所全体を生成 | 1234 Main St, Tokyo |
postcode | 郵便番号を生成 | 123-4567 |
city | 市区町村名を生成 | Shibuya |
company | 会社名を生成 | Acme Inc. |
jobTitle | 職業名を生成 | Software Engineer |
word | ランダムな単語を生成 | apple |
words | 複数単語の配列を生成 | ['apple', 'banana', 'cherry'] |
slug | スラッグ形式の文字列を生成 | example-post-title |
regexify | 正規表現にマッチする文字列を生成 | faker->regexify('[A-Z]{5}[0-4]{3}') |
seederの作成
まずはDatabaseSeeder.php
に作成したseederを登録します
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call(UsersTableSeeder::class); //追加
}
}
これでseederを実行したときにUsersTableSeederが呼び出されるようになりました
UsersTableSeederには以下のように記載
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// userのシーダー作成。アイコンを追加
User::factory()->count(5)->create(['icon' => 'icon.png']);
// 管理者ユーザーの作成 存在しなかったら第二引数をデフォで使用
User::create([
'name' => env('ADMIN_USER','root'),
'email' => env('ADMIN_EMAIL','root@sample.com'),
'password' => Hash::make(env('ADMIN_PASSWORD','password')),
'icon' => 'icon.png',
'is_admin' => true,
]);
}
}
User::factory()->count()
で指定した数のダミーデータを作れるようになります
また管理者ユーザーはenvファイルで指定したものを使います。
存在しなかった場合は第二引数を参照します。
最後に以下を実行してユーザー情報を登録します
php artisan config:clear #envファイルを設定した場合
php artisan migrate:refresh --seed
これで管理者、デモユーザーは作れました
ユーザー登録
バリデーション(フォームリクエスト)
次にユーザー登録の実装をします
まずは作成フォームのバリデーションを作ります
以下のコマンドでファイルを作成
php artisan make:request RegisterRequest
次に以下の内容をファイルに記載
use Illuminate\Validation\Rules\Password;
class RegisterRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => 'required|string|min:1|max:10',
'email' => 'required|email|string|unique:users',
'password' => [
'required',
'confirmed',
Password::min(8)->mixedCase()->numbers(),
],
'icon' => 'nullable|image|mimes:jpeg,png,gif,jpg|max:2048',
];
}
public function messages(): array
{
return[
'name.required' => '名前は必須です',
'name.min' => '名前は1文字以上で入力してください',
'name.max' => '名前は10文字以内で入力してください',
'email.required' => 'メールアドレスは必須です',
'email.email' => 'メールアドレスの形式が正しくありません',
'email.unique' => '既に存在しているメールアドレスです',
'password.required' => 'パスワードは必須です',
'password.confirmed' => 'パスワードが一致しません',
'password.min' => 'パスワードは8文字以上で入力してください',
'password.mixed_case' => 'パスワードには大文字・小文字を含めてください',
'password.numbers' => 'パスワードには数字を含めてください',
'icon.image' => 'アイコンは画像ファイルを選択してください',
'icon.mimes' => 'アイコンはjpeg,png,gif,jpgのいずれかの形式にしてください',
'icon.max' => 'アイコンのサイズは2MB以下にしてください'
];
}
}
authorize()
はフォームを送信できる権限についてです。(デフォルトはfalseになっているので注意)
rules()
にバリデーションについて定義します
基本的にはパラメータ => ルール1|ルール2|ルール3|...
という感じ。
messages()
でエラーを起こしたときのメッセージを返します
バリデーションルールについては以下を参照
コントローラ
次にコントローラを実装。
以下のコマンドでファイルを作成
php artisan make:controller RegisterController
次に以下の内容をファイルに記載
class RegisterController extends Controller
{
public function register(RegisterRequest $request):RedirectResponse
{
// ユーザの作成。ファイルをアップロードしない場合、デフォルトで登録
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
'icon' => $request->file('icon') ? $request->file('icon')->store('icons','public') : 'images/default-icon.png'
]);
// ユーザーイベントの発火。メール認証などしたいときに使う
event(new Registered($user));
// ユーザをログイン状態にする
Auth::login($user);
// ホームページにリダイレクト
return redirect()->route('app.home');
}
}
先ほどのモデルファイルで$fillable
をつけておかないとエラーになります
viewは省略しますがpasswordについては以下のようにする
<div>
<label for="password">パスワード</label>
<input type="password" name="password" id="password">
</div>
<div class="mb-4 flex flex-col sm:flex-row items-center gap-2">
<label for="password_confirmation">パスワード再確認</label>
<input type="password" name="password_confirmation" id="password_confirmation">
</div>
バリデーションでパスワードについてはconfirmed
をつけたのでパスワードが一致する必要がありますがその際の確認用のパスワードのname属性はpassword_confirmation
をつけてください
これで以下のようにユーザ登録ができるようになりました
ログイン・ログアウト機能
バリデーション
次にログイン機能を実装します。
先ほど同様にまずはフォームリクエストから
ファイルを作成した後、以下を記載
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'email' => 'required|email',
'password' => [
'required',
Password::min(8)->mixedCase()->numbers(),
]
];
}
public function messages(): array
{
return[
'email.required' => 'メールアドレスは必須です',
'email.email' => 'メールアドレスの形式が正しくありません',
'password.required' => 'パスワードは必須です',
'password.min' => 'パスワードは8文字以上で入力してください',
'password.*' => 'パスワードは8文字以上、大文字・小文字・数字を含めてください',
];
}
コントローラの作成
同様にファイルを作成した後に以下を記載
まずはログインのコントローラー
public function login(LoginRequest $request)
{
// emailとpasswordを取得
$credentials = $request->only('email','password');
// 受け取ったパラメータから認証する
if (Auth::attempt($credentials)) {
// セッションを再度生成し、リダイレクト
$request->session()->regenerate();
return redirect()->route('app.home');
}
// ログインに失敗した時
return back()->withErrors([
'email' => 'メールアドレスまたはパスワードが違います'
]);
}
Auth::attempt()
でログインを試みます。
withErrors()
でログイン失敗時のメッセージを表示
次にログアウトのコントローラー
public function logout(Request $request):RedirectResponse
{
// ログアウト
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('auth.login');
}
ログアウトとログインは両方ともPOST
を使ってルーティングしてください
これでユーザー登録、ログイン、ログアウトのすべてを作りました
ユーザー認証
一般ユーザー
最後にユーザー認証について。
まずは一般ユーザーの認証について
以下のコマンドでミドルウェアを作成します
php artisan make:middleware UserIsAuthenticated
php artisan make:middleware UserIsAdmin
次に以下の内容をミドルウェアに記載します
public function handle(Request $request, Closure $next): Response
{
// ユーザがログインしていない場合はloginフォームにリダイレクト
if (!Auth::check()) {
return redirect()->route('auth.login');
}
// ログイン済みの人はそのままアクセス
return $next($request);
}
Auth::check()
でユーザーがログイン状態かチェックします
認証に失敗した場合はログイン画面へリダイレクトします
管理者認証
管理者かどうかチェックします
UserIsAdmin
に以下を記載
public function handle(Request $request, Closure $next): Response
{
// 管理者でない場合はログインは認証されているのでhomeへリダイレクト!
if (!Auth::user()->isAdmin()) {
return redirect()->route('app.home');
}
return $next($request);
}
Userモデルに追加したisAdmin()
で管理者かどうかをチェックします
adminミドルウェアはauthミドルウェアの後に通過するので認証に失敗した場合はhomeへリダイレクトしときます。
ミドルウェアの追加
次にミドルウェアを登録します
laravel-11以前はKernel.php
というファイルらしい
現バージョンではbootstrap
フォルダのapp.php
に記載します
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'auth' => UserIsAuthenticated::class,
'admin' => UserIsAdmin::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
withMiddleware
の中に登録したファイルを記載します。
また、エイリアスでミドルウェアの名前を登録しときます
ルーティング
最後にミドルウェアを利用したルーティングの例です
// 下は未認証でも行けるページ
Route::prefix('auth')->group(function(){
Route::get('/register',[RegisterController::class,'showRegisterView'])->name('auth.register');
Route::post('/register',[RegisterController::class,'register']);
Route::get('/login',[LoginController::class,'showLoginForm'])->name('auth.login');
Route::post('/login',[LoginController::class,'login']);
});
// ユーザー認証を突破したひとが入れるページ
Route::middleware('auth')->prefix('app')->group(function(){
Route::get('home',[HomeController::class,'showHomeView'])->name('app.home');
});
// ユーザー認証を突破し、管理者認証も突破したユーザーが入れるページ
Route::middleware('auth','admin')->prefix('admin')->group(function(){
Route::get('/',[PartController::class,'showPartsView'])->name('admin.home');
});
最後に
これにて終了です
ユーザー認証、登録について自分なりにまとめてみました
ユーザ認証がバージョン11で大きく変わっていて調べるのに苦労しました🥹
Discussion