WEBOPIXEL

Laravel8でCMSを作るチュートリアル(2) ログイン認証編[2020年版]

Laravelロゴ

Posted: 2020.11.28 / Category: PHP / Tag: 

Laravel8を使用して、コーポレートサイトでよくありそうなのお知らせを管理するCMSを作るチュートリアルの2回目です。
前回はフロント部分を作成したので今回は管理画面に入る為のログイン機能を作ります。

Sponsored Link

作る機能

  1. 投稿一覧&詳細ページ
  2. 管理画面へのログイン機能
  3. 投稿管理(CRUD)機能
  4. ユーザーと投稿の関連付け(多対一:HasMany)
  5. 投稿のタグ分け(多対多:ManyToMany)
  6. ユーザーロール(権限)の設定)

Laravel Fortify のインストールと設定

以前のバージョンではmake:authで認証機能を生成することができたのですが、6からは「laravel/ui」という外部ライブラリとなり、8では「Laravel Jetstream」というライブラリに一新されました。
で、「Laravel Jetstream」のバックエンドの機能が「Laravel Fortify」ということになるようです。

「Laravel Jetstream」を使うことで簡単にベーステンプレートを作ってくれますが、業務で使う場合はオリジナルのテンプレートを使うことが多いと思いますので、今回は「Laravel Fortify」だけを使用することにします。

まずは次のコマンドを実行してライブラリをインストールしましょう。

$ composer require laravel/fortify

必要なファイルを書き出します。

$ php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"

書き出されたファイルを編集します。
(コメントは省略してます。)
今回は管理画面でユーザー管理をするので、ログイン・ログアウト機能だけ使用しますのでfeaturesはすべてコメントアウトしておきます。

config/fortify.php

<?php

return [
	'username' => 'name',

	'email' => 'email',

	'home' => '/admin',

	'limiters' => [
		'login' => 5,
	],

	'features' => [],

	// adminでアクセス
	'path' => 'admin',
];

usernamenameにすることで、ログイン時使用する情報をメールアドレスからnameにしてます。

viewのディレクトリをback/authに変更します。

Providers/FortifyServiceProvider.php

public function boot()
{
	// ...
	
	// Viewのディレクトリを変更
	Fortify::viewPrefix('back.auth.');
}

app.phpprovidersに追加。

config/app.php

'providers' => [
	// Fortify::createUsersUsing(CreateNewUser::class);
	// Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
	// Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
	// Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
	App\Providers\FortifyServiceProvider::class,
],

Fortifyの設定については下記記事も参考にしてください。

Laravel8 Fortify(認証機能)のカスタマイズ方法

ユーザーデータの登録

シーダーファイルを作成します。

$ php artisan make:seeder UserSeeder

作成したファイルを次のように編集します。
パスワードは暗号化されるのでHash::makeで入れるようにしましょう。

database/seeders/UserSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class UserSeeder extends Seeder
{
	/**
	 * Run the database seeds.
	 *
	 * @return void
	 */
	public function run()
	{
		\DB::table('users')->insert([
            [
                'name' => 'admin',
                'email' => 'admin@example.com',
                'email_verified_at' => now(),
                'password' => \Hash::make('123456789'),
                'created_at' => now(),
                'updated_at' => now()
            ],[
                'name' => 'yamada',
                'email' => 'yamada@example.com',
                'email_verified_at' => now(),
                'password' => \Hash::make('123456789'),
                'created_at' => now(),
                'updated_at' => now()
            ],[
                'name' => 'tanaka',
                'email' => 'tanaka@example.com',
                'email_verified_at' => now(),
                'password' => \Hash::make('123456789'),
                'created_at' => now(),
                'updated_at' => now()
            ]
        ]);
	}
}

DatabaseSeederに追加します。

database/seeders/DatabaseSeeder.php

public function run()
{
	$this->call(UserSeeder::class);
	$this->call(PostSeeder::class);
}

Postと同じようにリフレッシュしてもいいですが、シーダーを個別に実行する方法もあります。

$ php artisan db:seed=UserSeeder

管理画面にログイン制限を掛ける

今は誰でも管理画面(/admin)にアクセスできてしまいますので、ログインしないとアクセスできないように制限してみましょう。

RouteServiceProvider.phpmiddlewareauthを追加します。

app/Providers/RouteServiceProvider.php

// 管理画面
Route::prefix('admin')
	->middleware(['web', 'auth'])
	->namespace($this->namespace . '\Back')
	->as('back.')
	->group(base_path('routes/back.php'));

ログイン画面

ログインしてない状態で制限を掛けたページにアクセスするとログイン画面にリダイレクトされるので、ログイン画面を作成しておきましょう。

resources/views/back/auth/login.blade.php

<!doctype html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>ログイン | Laravelチュートリアル</title>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" crossorigin="anonymous">
</head>
<body>
<div id="app">
	<div class="container">
		<div class="row justify-content-center mt-5">
			<div class="col-md-6">
				<div class="card">
					<div class="card-header">ログイン</div>
					<div class="card-body">
						{{ Form::open(['route' => 'login']) }}
							<div class="form-group">
								{{ Form::label('name', 'ユーザー名') }}
								{{ Form::text('name', null, [
									'class' => 'form-control' . ($errors->has('name') ? ' is-invalid' : '')
								]) }}
								@error('name')
									<div class="invalid-feedback">
										{{ $message }}
									</div>
								@enderror
							</div>
							<div class="form-group">
								{{ Form::label('password', 'パスワード') }}
								{{ Form::password('password', [
									'class' => 'form-control' . ($errors->has('password') ? ' is-invalid' : '')
								]) }}
								@error('password')
									<div class="invalid-feedback">
										{{ $message }}
									</div>
								@enderror
							</div>
							<div>
								<button type="submit" class="btn btn-primary">ログイン</button>
							</div>
						{{ Form::close() }}
					</div>
				</div>
			</div>
		</div>
	</div>
</div>
</body>
</html>

/adminにアクセスして/admin/loginにリダイレクトされログイン画面が表示されるのを確認してください。
シーダーファイルで作成した情報「ユーザー名:admin」「パスワード:123456789」でログインできることも確認しましょう。

ログインが成功すると、/adminにリダイレクトされ「back」という文字が表示されることを確認してください。

バリデーションメッセージの日本語化

ログイン画面でためしに何も入力しないで「ログイン」ボタンをクリックしてみてください。
英語でエラ〜メッセージが表示されると思います。
この部分を日本語で表示するようにしてみましょう。

下記ページにアクセスして言語ファイルをダウンロードします。

Laravel-Lang / lang

コンポーザーでインストールしてもいいですが、ここではzipファイルをダウンロードします。
zipファイルを解凍したディレクトリからsrcjaディレクトリをコピーしてプロジェクトディレクトリのresources/langに入れます。

これで文章は日本語になっていますが、カラム名はアプリケーション特有のものになるので個別に設定する必要があります。
validation.phpattributesに次のように追加しましょう。

resources/lang/ja/validation.php

'attributes' => [
	'name' => 'ユーザー名',
	'password' => 'パスワード'
],

ダッシュボード画面とログアウト機能

管理画面のトップページであるダッシュボード画面を作ります。
最初にコントローラーを作成します。
ダッシュボードコントローラーは一つのアクションしかないコントローラーになるので、--invokableオプションを付与して作成します。

$ php artisan make:controller Back/DashboardController --invokable

次のように編集します。

app/Http/Controllers/Back/DashboardController.php

<?php

namespace App\Http\Controllers\Back;

use App\Http\Controllers\Controller;

class DashboardController extends Controller
{
	public function __invoke()
	{
		return view('back.dashboard');
	}
}

ルーターを設定して作成したコントローラーを表示できるようにしましょう。
シングルアクションコントローラーの場合はアクション名は必要ありません。

routes/back.php

Route::get('/', 'DashboardController')->name('dashboard');

フロントと同様に管理画面用のレイアウトファイルを作ります。

resources/views/back/layouts/base.blade.php

<!doctype html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>{{ isset($title) ? $title . ' | ' : '' }}管理画面</title>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" crossorigin="anonymous">
</head>
<body>
<div id="app">
	<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
		<div class="container">
			<a class="navbar-brand" href="{{ route('back.dashboard') }}">
				管理画面
			</a>
			<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false">
				<span class="navbar-toggler-icon"></span>
			</button>

			<div class="collapse navbar-collapse" id="navbarSupportedContent">
				<ul class="navbar-nav ml-auto">
					<li class="nav-item"><a class="nav-link" href="{{ route('back.dashboard') }}">ダッシュボード</a></li>
					<li class="nav-item">
						<a href="#" class="nav-link" onClick="(function(){
							document.getElementById('logout-form').submit();
							return false;
						})();">ログアウト</a>
						{{ Form::open(['route' => 'logout', 'id' => 'logout-form']) }}
						{{ Form::close() }}
					</li>
				</ul>
			</div>
		</div>
	</nav>
	<main class="py-4">
		<div class="container">
			<div class="row justify-content-center">
				<div class="col-md-12">
					<div class="card">
						@yield('content')
					</div>
				</div>
			</div>
		</div>
	</main>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" crossorigin="anonymous"></script>
</body>
</html>

24〜30行目がログアウトの為のボタンです。

最後にダッシュボードのビューを作成します。
今のところこの画面では何もしてませんが、管理画面用のレイアウトを読み込むことでログアウトのリンクが表示されクリックできるようになります。

resources/views/back/dashboard.blade.php

<?php
$title = 'ダッシュボード';
?>
@extends('back.layouts.base')

@section('content')
<div class="card-header">{{ $title }}</div>
@endsection

ログアウトボタンをクリックしてログアウトが機能するか試してください。

これでログイン・ログアウトの認証機能を作成することができました。
次回は管理画面で投稿のCRUD機能を作っていきます。

ソースコードはGitHubに置いてます。

LaravelMiniCMS2020