Laravel(Laradock)を使ってAuth機能を実装してみた

はじめに

ハマったところなどを忘れないように備忘録として書いています。
おかしなところがアレばご指摘頂けると幸いです。

前提

  • Dockerが使えること
  • Gitが使えること

環境

  • macOS High Sierra Ver.10.13.2
  • Laravel Framework 6.12.0

環境構築

1.Laradockをクローンするためのディレクトリの作成
$ mkdir MyApp && cd MyApp
2.LaradockをGitからクローン
$ git clone https://github.com/LaraDock/laradock.git

クローンが終わるとMyApp直下にlaradockディレクトリができています。
laradockのディレクトリに移動して、ls -alするとlaradockに内包されているものが一覧で確認できます。

3.laradock配下にあるenv-exampleを.envにして任意で編集
cp env-example .env

今回、GUIツールのSequel Proでデータベースに繋ぎたかったのでMySQLは5.6を使用しています。
データベース名やユーザ名など、任意で設定してください。

### MYSQL #################################################

MYSQL_VERSION=5.6
MYSQL_DATABASE=default
MYSQL_USER=root
MYSQL_PASSWORD=secret
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d

docker-composeコマンドでコンテナをビルド、起動します。

$ docker-compose up -d nginx mysql php-fpm

初回起動時は結構時間がかかると思います。
起動が終わるとdocker-compose psでコンテナのプロセスを確認します。

           Name                          Command              State                    Ports
--------------------------------------------------------------------------------------------------------------
laradock_docker-in-docker_1   dockerd-entrypoint.sh           Up      2375/tcp, 2376/tcp
laradock_mysql_1              docker-entrypoint.sh mysqld     Up      0.0.0.0:3306->3306/tcp
laradock_nginx_1              /bin/bash /opt/startup.sh       Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
laradock_php-fpm_1            docker-php-entrypoint php-fpm   Up      9000/tcp
laradock_workspace_1          /sbin/my_init                   Up      0.0.0.0:2222->22/tcp

コンテナが立ち上がっていればOKです。

4.プロジェクトの作成

以下のコマンドでコンテナにアクセスします。

$ docker-compose exec workspace bash

コンテナに入れたらまずはパッケージリストを更新します。

$ apt-get update

更新したら以下のコマンドでプロジェクトを作成します。

$ composer create-project --prefer-dist laravel/laravel MyProject

作成が完了したらlaradockと同階層にMyProjectが出来ています。
MyProject配下にあるstorageとcacheのディレクトリのパーミッションを変更します。

$ chmod 777 storage
$ chmod 777 bootstrap/cache
5.プロジェクトの設定

手順通りに進めていれば、現在workspaceのコンテナに入っている状態なのでexitでコンテナから出ます。
コンテナから出た後、立ち上げたコンテナを以下のコマンドで停止します。

$ docker-compose stop

コンテナを停止したらコードのパスを設定するためlaradock配下にある.envを編集します。

### Paths #################################################

# Point to the path of your applications code on your host
APP_CODE_PATH_HOST=../MyProject/

上記の様にしておくことでworkspaceのコンテナに入った時のルートディレクトリの位置が変わってるはずです。

MyProject側の.envも以下のように編集します。
私の場合、DB_HOSTをmysqlにしないとconnection refusedのエラーが出て繋がらなかったです。

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=root
DB_PASSWORD=root

ここまで設定した後、再度コンテナを起動させブラウザでhttp://localhostへアクセスします。

$ docker-compose up -d nginx mysql php-fpm

もし、404の画面になった場合Nginxのドキュメントルートを変更します。
設定ファイルの場所はlaradock配下にあるnginx/sites/default.conf
変更箇所はline:13あたり

root /var/www/public;
6.パッケージリストのインストール

再び、workspaceのコンテナに入ります。

$ docker-compose exec workspace bash

コンテナに入ったらcomposerとnpmをインストールするだけです。

$ composer install
$ npm install
7.ログイン機能の実装

今回、ログイン機能はLaravel標準のものを使用します。
以下のコマンドを実行します。

$ artisan migrate

すると以下のようなエラーが出るかと思います。(※実行後の全文)

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table

   Illuminate\Database\QueryException  : SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))

  at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669
    665|         // If an exception occurs when attempting to run a query, we'll format the error
    666|         // message to include the bindings with SQL, which will make this exception a
    667|         // lot more helpful to the developer instead of just the database's errors.
    668|         catch (Exception $e) {
  > 669|             throw new QueryException(
    670|                 $query, $this->prepareBindings($bindings), $e
    671|             );
    672|         }
    673|

  Exception trace:

  1   PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes")
      /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:463

  2   PDOStatement::execute()
      /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:463

  Please use the argument -v to see more details.

MySQLのリファレンスを見てみると以下のように書かれています。

デフォルトでは、単一カラムインデックスのインデックスキーを最大で 767 バイトにすることができます。

つまり、768バイト以上のカラムに対するインデックスキーは設定できません。
Laravel 5.3まではUTF-8だった為、1文字が3Byteなのでvarchar(255)は、255文字×3Byte=765Byteということでインデックスを設定することができていましたが、
Laravel 5.4以降はUTF-8mb4となり1文字が4Byteとしてあつかわれるため、制限の767Byteを超えてしまいエラーとなります。

ちなみに、MySQL5.6を使っていることも影響しているので5.7で設定していればこのエラーは出ないかと思います。

今回私は絵文字を使用することを諦め、UTF-8として使用することにしました。 修正箇所はconfig/database.phpです。

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

以下のように修正。

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',

中途半端にマイグレーションが実行されている為、MySQLのコンテナに入りMySQLにログイン。一度作られたテーブルを削除してから再度workspaceのコンテナでマイグレーションを実行します。

すると無事に以下4つのテーブルが出来ているはずです。

  • failed_jpbs
  • migrations
  • password_resets
  • users

続いて、以下のコマンドを実行しauth機能を作成します。

$ artisan make:auth

すると次は以下のようなエラーが発生します。

Command "make:auth" is not defined.

Laravel 5系までは使えていたコマンドですが6系になるとなくなってるんですね。 そこで以下のコマンドを実行します。

$ composer require laravel/ui --dev
$ artisan ui vue --auth

これで画面右上に登録・ログインボタンが出来上がったと思います。

実際にLOGIN或いはREGISTERをクリックしてみるとちゃんとページは遷移できます。 しかし、Laravel 6系ではCSS / JSが同梱されなくなっているためJSやCSSがあたっていない状態になっているかと思います。

そこでプロジェクト内で使用したい構成にあわせて以下から選択して実行します。 なお、vue/react/bootstrap以外にも任意のプリセットを用意したい場合、 \Laravel\Ui\UiCommand にマクロを実装することで追加が可能とのことです。

# VueやReactを利用しない、Bootstrap(+jQuery)のみのプリセット 
$ artisan ui bootstrap --auth 
# Bootstrapに加えてVue.jsを利用する 
$ artisan ui vue --auth 
# Vue.jsではなくReactを利用する 
$ artisan ui react --auth

生成したプリセットはコンパイルする必要があるため環境に合わせてビルドします。

# with npm
$ npm i
# 開発用ビルド
$ npm run dev
# 本番用ビルド
$ npm run prod

# with yarn
$ yarn install
# 開発用ビルド
$ yarn dev
# 本番用ビルド
$ yarn prod

画面を確認するとJS、CSSもあたりきれいに表示されていると思います。
登録、ログインが実際に動いていることを確認できれば完成です。

参考

qiita.com larapet.hinaloe.net