PHPフレームワーク『Laravel』入門 #7 ログイン機能とカスタマイズ方法

ログイン機能とカスタマイズ方法

Laravelにはこれまで紹介した便利なコマンドのほかに、Webアプリケーションを作るのに欠かせない認証・認可に関する機能が最初から用意されています。

その一つが、ユーザー登録を行った利用者だけがWebアプリケーションを閲覧・利用できるようにする「ログイン機能」です。
ログイン機能は、会員制のWebアプリケーションに欠かせません。それ以外にも、管理者ユーザーを作って、一般ユーザーにはできない操作をWeb上でさせたい場合に有用です。

一から作れば1~2日かかってしまうログイン機能ですが、Laravelでは初めから用意されているので最短10分で導入できるのが強みです。

カスタマイズも簡単でとても便利ですので、ぜひ活用してください。

 

目次

 

  1. ログイン機能
    1.1 ログイン機能の有効化
    1.2 ログイン画面
    1.3 ユーザー登録画面
  2. ログイン機能のカスタマイズ
    2.1 ログインフォーム、ユーザー登録フォームの日本語化
    2.2 ユーザーIDでログインできるようにする
    2.3 ユーザー登録画面に項目を追加する
  3. 最後に

 

1. ログイン機能

 

Laravelで初めから用意されているログイン機能は、利用者のメールアドレスとパスワードを入力するだけの簡単なものです。
入力したメールアドレスがデータベースのUsersテーブルに存在し、かつパスワードが一致した場合にログイン成功となります。開発者は、ログインに成功したユーザーだけが見られるページや、押せるボタンなどを設置することができます。

これだけでも機能的には十分ですが、もっと使いやすくするためのカスタマイズも可能です。
カスタマイズの方法は後述しますので、まずはデフォルトのままでログイン機能を有効化してみましょう。

 

1.1 ログイン機能の有効化

Laravelのログイン機能を有効化するには、Artisan make:auth コマンドを実行します。

# Laravelプロジェクト(PROJECT_NAME)に移動
cd ~/html/laravel/PROJECT_NAME
# ログイン機能を有効化する
php-7.1 artisan make:auth

Authentication scaffolding generated successfully.

というメッセージが表示されればコマンドは成功です。
驚くべきことに、たったこれだけでログイン機能に必要なファイルがプロジェクトに追加されます。

※データベースにUserテーブルがまだ作成されていない場合はエラーになりますので、先にデータベースのマイグレーションを実行してください。

php-7.1 artisan migrate

生成されたログイン機能関係のクラスをWebアプリケーションに即座に反映させるため、以下のコマンドでキャッシュクリアを実行してください。

php-7.1 artisan clear-compiled
php-7.1 artisan optimize
php-7.1 artisan view:clear

artisan optimizeの実行後に以下のようなエラーメッセージが表示されますが、無視をしても問題ありません。

LogicException  : Unable to prepare route [api/user] for serialization. Uses Closure.

キャッシュクリアの実行後、Webアプリケーションのトップページにアクセスすると、ヘッダー部分に「LOGIN」「REGISTER」というボタンが追加されているのが確認できます。

http://<サーバの公開URL>/laravel/PROJECT_NAME/public/

 width=

 

1.2 ログイン画面

ヘッダー部分に追加された「LOGIN」をクリックすると、ログイン画面が表示されます。

 width=

E-Mail Address:ユーザーのメールアドレス
Password:パスワード
Remember Meにチェックを入れてログインするとログイン情報がブラウザに記録されて、次回以降のログインが省略されます。
Forgot Your Password? は利用者がパスワードを忘れた際にパスワード再設定用リンクをメールで送る機能です。こちらもはじめから用意されていますので、とても便利です。

 

1.3 ユーザー登録画面

ヘッダー部分に追加された「REGISTER」をクリックすると、ユーザー登録画面が表示されます。
利用者はまずこの画面で自分のユーザー情報(認証情報)を登録します。

 width=

Nameは利用者が希望するユーザーIDを入力します。
E-Mail Address は利用者が自身のメールアドレスを入力します。
Password は利用者が希望する、ログインの際に入力するパスワードを入力します。
Confirm Password は誤入力防止用で、再度希望するパスワードを入力します。

Laravelのログイン機能がデフォルトで取り扱うユーザー情報(認証情報)は上記のとおりです。
他に項目を増やしたい場合は、カスタマイズ方法を後述しますのでそちらをご参考ください。

実際にテストユーザーの登録を行ってみます。

 width=

同一のメールアドレスがすでに登録されている場合は、エラーメッセージが表示されます。
テストユーザーを複数作成する際には、ユーザーごとに別のメールアドレスを用いてください。

ユーザーの登録が成功すると、自動的にダッシュボードページに移動します。

 width=

ヘッダーメニューのLogoutをクリックすると、ログアウトされてトップページに戻ります。

 

2. ログイン機能のカスタマイズ

前章ではLaravelのログイン機能について導入方法をご説明しました。
デフォルトの状態でも十分利用できますが、もっと使いやすく、Webアプリケーションの用途に合わせた内容にカスタマイズすることができます。

ここからカスタマイズの例をいくつかご紹介しますので、自分が開発するWebアプリケーションにも導入したいと思うものがあれば、ぜひ手順を参考に導入してみてください。

 

2.1 ログインフォーム、ユーザー登録フォームの日本語化

ログインフォーム、ユーザー登録フォームの項目はすべて英語で書かれています。
このままですとユーザーに不親切ですので、日本語に変更します。

まずログイン画面の入力フォームを日本語に変更します。

resources/views/auth/login.blade.php

extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">メールアドレス</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">パスワード</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <div class="col-md-6 offset-md-4">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>

                                    <label class="form-check-label" for="remember">ログイン情報を保存する</label>
                                </div>
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">ログイン</button>

                                @if (Route::has('password.request'))
                                    <a class="btn btn-link" href="{{ route('password.request') }}">パスワードを忘れましたか?</a>
                                @endif
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

次に、ユーザー登録画面の入力フォームを日本語に変更します。

resources/views/auth/register.blade.php

 extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Register') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('register') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">ご希望のユーザーID</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>

                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">メールアドレス</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">パスワード</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-right">パスワード(確認のため再度入力してください)</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">登録する</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

2.2 ユーザーIDでログインできるようにする

Laravelのログイン機能はデフォルトではメールアドレスとパスワードの組み合わせで認証を行います。
これですとメールアドレスが長い場合に入力が面倒ですので、ユーザーIDとパスワードでログインが可能になるようカスタマイズします。

まずはログイン機能のコントローラーに以下の記述を追加します。

app/Http/ Controllers/Auth/LoginController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

use Illuminate\Http\Request;

class LoginController extends Controller
{
  
    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';
 

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
  
    public function username()
    {
      return 'name';
    }
}

usernameという関数を追加して、戻り値にログインに利用したいカラムの名前(今回はユーザーIDなのでname)を文字列で指定します。

次に、ログイン画面の画面項目を変更します。

resources/views/auth/login.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf
                        <!-- メールアドレスの入力項目をコメントアウトする -->
                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">メールアドレス</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
                        -->
                       <!-- 新しくユーザーIDの入力項目を追加する -->
                       <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">ユーザID</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>

                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
 ~略~

ログイン画面の入力フォームのうち、メールアドレスの入力フォームを削除します。(今回は分かりやすいようにコメントアウトしています。)
そのかわりに、ユーザーIDの入力フォーム( input name=“name” )を新たに追加しています。


これでログインに用いる項目がメールアドレスからユーザーIDに変更されます。

 

2.3 ユーザー登録画面に項目を追加する

最後に、ユーザー登録画面に氏名や住所、電話番号などの独自の項目を追加する方法です。

少し複雑ですが、実際のWebアプリケーションでは会員登録を行う際にこれらの情報も登録させることが多いので、ぜひ覚えてご活用ください。

 

2.3.1 Usersテーブルのカラム追加

まず、Usersテーブルに氏名と電話番号のカラムを増やすためのマイグレーションファイルを作成します。

php-7.1 artisan make:migration update_user_table --table=users

database/migrations/日付_update_user_table.php

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class UpdateUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
          $table->string('fullname'); // 氏名カラムを追加
          $table->string('phone');  // 電話番号カラムを追加
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {

        });
    }
}

マイグレーションファイルの作成が終わったら、マイグレーションを実行します。

php-7.1 artisan migrate

成功するとデータベース上のUsersテーブルに「fullname」「phone」のカラムが追加されます。

 width=

 

2.3.2 Userモデルの変更

続いて、テーブルの変更にあわせてUserモデルの内容を変更します。

app/User.php

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',’fullname’,’phone’,
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

フィールドの$fillable配列に新しく追加したカラム名「fullname」「phone」を追加しています。

この変更を忘れると、入力された氏名と電話番号をUsersテーブルに登録する際にエラーになりますのでご注意ください。

 

2.3.3 入力フォームの変更

次に、ユーザー登録画面の入力フォームに氏名と電話番号の項目を追加します。

resources/views/auth/register.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Register') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('register') }}">
                        @csrf

~略~
                      
                        <div class="form-group row">
                            <label for="fullname" class="col-md-4 col-form-label text-md-right">氏名</label>

                            <div class="col-md-6">
                                <input id="fullname" type="text" class="form-control @error('fullname') is-invalid @enderror" name="fullname" value="{{ old('fullname') }}" required >

                                @error('fullname')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>     
                      
                        <div class="form-group row">
                            <label for="phone" class="col-md-4 col-form-label text-md-right">電話番号</label>

                            <div class="col-md-6">
                                <input id="phone" type="text" class="form-control @error('phone') is-invalid @enderror" name="phone" value="{{ old('phone') }}" required>

                                @error('phone')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div> 
                      
~略~

 

2.3.4 コントローラーの変更

最後に、ユーザー作成用のコントローラーファイルに、新しい項目のバリデーションルール(入力規則)と登録処理を追加します

app/Http/ Controllers/Auth/RegisterController.php

<?php

namespace App\Http\Controllers\Auth;

use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;

class RegisterController extends Controller
{
    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'fullname' => ['required', 'string', 'max:255'],
            'phone' => ['required', 'string', 'max:50'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
            'fullname' => $data['fullname'],
            'phone' => $data['phone'],
        ]);
    }
}

validator関数の戻り値に設定されているValidator::makeは、それぞれの入力項目に対してどのようなチェックを行うかを記述します。

細かいバリデーションルールなどの説明は省略しますが、requiredを設定すると入力が必須になります。逆に何も定義しないと、任意入力の項目になります。

create関数のUser::createでUsersテーブルへの登録を行っています。
ここに氏名と電話番号の代入処理を追加してください。

 

2.3.5 ユーザー情報の登録、確認

以上でユーザー登録フォームの項目追加カスタマイズの手順は完了です。

それでは、実際に登録をしてみます。

 width=

登録が完了したらダッシュボード画面に新しく追加した氏名と電話番号を表示して、正しく登録ができているか確認してみましょう。

resources/views/home.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Dashboard</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    <h2>ようこそ、{{ Auth::user()->fullname }}さん!</h2>
                    <h3>連絡先:<a href="tel:{{ Auth::user()->phone }}">{{ Auth::user()->phone }}</a></h3>
                    
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

ログイン中のユーザーの情報はAuth::userで呼び出すことができます。

 width=

画像のように、氏名と電話番号が表示されていればカスタマイズ成功です。

 

3. 最後に

今回はLaravelの認証・認可機能のうちログイン機能についてご紹介しました。

Webアプリケーションを作成するうえで、ログイン機能は欠かせないものですので、ぜひLaravelのログイン機能を使いこなして開発のスピードアップを実現させてください。

カスタマイズの方法は今回ご紹介したもの以外にもたくさんありますので、自分が作りたいWebアプリケーションに最適なカスタマイズ方法を探してみてください。

関連タグ:

この記事をシェアする

次へ
前へ