- 投稿日:2020-09-06T21:33:59+09:00
Laravel で array 型のリクエストパラメータのバリデーション
Laravel で array 型として扱われるようなリクエストパラメータのバリデーションの記述に関するメモです。
実装
下記の例の Request Parameter にはリクエストパラメータを
$request->all()で取得したときに得られる array を記述します。
Validation にはとバリデーションルールを表す array を記述します。それぞれの変数
$dataと$rulesに対してValidator::validate($data, $rules)を Tinker 等で実行すればバリデーションが効いているか試すことができます。例1. key を省略した array
- Request Parameter
$data = [ 'article_ids' => [1, 23, 456], ]
- Validation
$rules = [ 'article_ids' => 'required|array', 'article_ids.*' => 'int', ];例2. key と value の組で構成された array
- Request Parameter
$data = [ 'ingredients' => [ 'egg' => true, 'peanuts' => false, 'others' => 'water' ], ];
- Validation
$rules = [ 'ingredients' => 'required|array', 'ingredients.egg' => 'required|boolean', 'ingredients.peanuts' => 'required|boolean', 'ingredients.others' => 'string', ];例3. ネストした array
- Request Parameter
$data = [ 'person' => [ ['first_name' => 'Taro', 'last_name' => 'Tanaka'], ['first_name' => 'Hanako', 'last_name' => 'Yamada'], ], ];
- Validation
$rules = [ 'person' => 'required|array', 'person.*.first_name' => 'required_with:person.*.last_name|string', 'person.*.last_name' => 'required_with:person.*.first_name|string', ];参考
- 投稿日:2020-09-06T21:31:32+09:00
【Laravel】ファイルをアップロードしたい
アップロードフォームの作成
index.balde.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <form method="POST" action="/upload" enctype="multipart/form-data"> {{ csrf_field() }} <input type="file" id="file" name="file" class="form-control"> <button type="submit">アップロード</button> </form> </body> </html>引用:Laravelでファイルをアップロードする方法を詳細解説
ポイント
ファイルアップロード時はenctype=”multipart/form-data”を必ず指定する
ルート情報
通常表示のために適当にアドレスを書く
Route::get('/','コントローラ名@index');アップロードファイルの受け取り
function store(Request $request) { print_r($request->all()); }引用:Laravelでファイルをアップロードする方法を詳細解説
また以下のように書けばファイルのみを見ることができる
print_r($request->file('file'));fileメソッドの引数として
fileが入っているのはフォームのinput要素のnameプロパティに設定している値。ルート情報
このメソッドを書いたらpost送信されるときに呼ばれるようにルート情報を書く
Route::post('/','コントローラ名@store');アップロードされたファイルの保存
public function store(Request $request){ $request->file('file')->store(''); }引用:Laravelでファイルをアップロードする方法を詳細解説
名前をつけて保存
パスとファイル名、ディスク名を指定して好きな名前をつけられる
$request->file('file')->storeAs('','image.jgp');引用:リクエストの取得
複数ファイルのアップロード
input要素を以下に修正
index.blade.php<input type="file" id="file" name="file[]" class="form-control" multiple>変更点は以下の2つ
- nameを
"file"から"file[]"に変更multipleを追加受け取り
前と同じで
$request->file('file')で受け取れ、配列となっている。参考
- 投稿日:2020-09-06T21:02:54+09:00
【laravel+mysql】新規でアプリケーションを立上げ、初めてのphp artisan migrateで詰まった件
どんな問題?
初めてPHP言語を使用して、Webアプリケーションを作成するためにlaravelとmysqlで開発環境を整え、新規作成したテーブルをmigrateした際にエラーが発生し、正常にテーブルが作成できない。
エラーの内容
ターミナルで $ php artisan migrateコマンドを入力したところ、以下のようなエラーが発生しました。
6行目の通り、1050 Table 'users' already exists...とあるように「既にuserテーブルは存在あるよ」ということです。ターミナル$ php artisan migrate Migrating: 2014_10_12_000000_create_users_table Illuminate\Database\QueryException SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists (SQL: create table `users` (`id` bigint unsigned not null auto_increment primary key, `name` varchar(255) not null, `email` varchar(255) not null, `email_verified_at` timestamp null, `password` varchar(255) not null, `remember_token` varchar(100) null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci') at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671 667| // If an exception occurs when attempting to run a query, we'll format the error 668| // message to include the bindings with SQL, which will make this exception a 669| // lot more helpful to the developer instead of just the database's errors. 670| catch (Exception $e) { > 671| throw new QueryException( 672| $query, $this->prepareBindings($bindings), $e 673| ); 674| } 675| +9 vendor frames 10 database/migrations/2014_10_12_000000_create_users_table.php:24 Illuminate\Support\Facades\Facade::__callStatic("create") +22 vendor frames 33 artisan:37 Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))前提
macOS ver10.15.4
laravel ver4.0.0導入済み
mysql ver5.6.47導入済み
sequelproに接続済みエラー発生までの流れ
ターミナル上で
ターミナル$ laravel new [プロジェクト名]コマンドで新規プロジェクト作成した際、userテーブルも自動生成されます。(password_resetsテーブルも自動生成されます。)
今回、追加でitemテーブルを作ろうと思い、
ターミナル$ php artisan make:migration create_items_tableでitemテーブルのマイグレーションファイルを作成し、
ターミナル$ php artisan migrateを実行したところ、上記の通り1050 Table 'users' already exists...というエラーが出て、itemテーブルが作成できませんでした。
対処方法
userマイグレーションファイルを以下のように変更しました。
変更前
userマイグレーションファイル〈上段省略〉 class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } 〈以下省略〉変更後
userマイグレーションファイル〈上段省略〉 class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { if (Schema::hasTable('users')) { // usersテーブルが存在していればリターンする return; } Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } 〈以下省略〉userのマイグレーションファイルのpublic function up() の中身に
userマイグレーションファイルif (Schema::hasTable('users')) { // usersテーブルが存在していればリターンする return;の記述を入れて存在しているテーブルをリターンさせたところ、migrateが通りました。
なお、userを解決した後、password_resetsテーブルについても同様の現象が発生したため、同じ要領で対応しました。
最後に
phpに関しては初学者のため、まだまだ解っていないことが多いので、他に最善な解決方法等がありましたらご指摘いただけますと幸いです。
- 投稿日:2020-09-06T18:17:26+09:00
laravel/jetstreamが気になりすぎたのでLaravel8をフライングゲットしてみた
はじめに
Laravel8が2020/09/09にリリースされます。開発するときはLTSを選択する保守的な自分にとっては、7.x以降のバージョンにはあまり興味がなかったのですが、今回はlaravel/jetstreamというフロントエンドスタックが導入されたことで気になり始め、リリース日を待たずにインストールして使ってみることにしました。
開発版のLaravel8をインストールする
composer create-project --prefer-dist laravel/laravel laravel8 dev-develop起動してみる
php artisan serveちゃんと画面右下に
Build v8.x-devて出てますね。modelの格納先を確認する
Laravel8では、modelは
app直下ではなくapp/Modelsに格納されます。単純なMVCモデルで開発するとき、いちいちapp/Modelsになるよう設定を変更していた身としてはありがたいです。
route:cache使ってみる
laravel8では、クロージャーで書かれていても
route:cacheが通るようになったので、試してみます。web.php<?php use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); });こういう書き方は、7.xまではcacheできなくて、
route:cacheするとエラーになっていました。しかし、laravel8.xからは。php artisan route:cache Route cache cleared! Routes cached successfully!このように、エラーになることなく実行できます。
さらに改善されたメンテナンスモード
Laravelでは
artisan downを実行することでメンテナンスモードに切り替えることができました。ただ、メンテンスモード中も、開発者はテスト等の為にアクセスする必要があり、laravel6.x系リリース時にIPアドレスによるホワイトリスト形式が採用されました。しかしそれも煩雑だということで、8.x系からはCookie方式が採用されたようです。php artisan down --secret=HOGE
--secretで指定したディレクトリにアクセスするとトップページにリダイレクトされ、かつlaravel_maintenanceという名前のCookieが発行されます。例えば、--secret=HOGEならhttp://127.0.0.1:8000/HOGEにアクセスします。これにより、メンテナンス中でも、メンテナンスモードを回避してサイトにアクセスできます。IPアドレスのホワイトリスト形式より格段に便利ですね。
さらに、
artisan down時に、--renderと、--statusというオプションが指定できるようになりました。何も指定していないと以下のように503エラー画面がレンダリングされ、statusは503で返りますが……。
例えば、
php artisan down --render="errors::404" --status=200というように指定することで、404画面をレンダリング、statusは200を返すというようなことが簡単にできるようです。
もちろん
--renderには、レンダリング可能なbladeテンプレートを自由に指定できるので、例えば、welcome.blade.phpを読み込むようにphp artisan down --render="welcome"と指定すると……。welcome画面をレンダリングしつつ、statusは503を返すみたいなことができるわけです。
laravel/jetstream!
さて、本命のjetstreamを使ってみます。実は調べてみて気づいたのですが、デフォルトではjetstreamは同梱されないようです(下記のcomposer.json参照)。
laravel/installerを使った場合のみlaravel new project-name --jetというように--jetオプションを指定することで同梱されるようです。composer.json"license": "MIT", "require": { "php": "^7.3", "fideloper/proxy": "^4.2", "fruitcake/laravel-cors": "^2.0", "guzzlehttp/guzzle": "^7.0.1", "laravel/framework": "^8.0", "laravel/tinker": "^2.0" }, "require-dev": { "facade/ignition": "^2.3.6", "fzaninotto/faker": "^1.9.1", "mockery/mockery": "^1.3.1", "nunomaduro/collision": "^5.0", "phpunit/phpunit": "^9.3" }, "config": { "optimize-autoloader": true, "preferred-install": "dist", "sort-packages": true },なので、仕方なくcomposerでインストールしました。ぐぬぬ……。
composer require laravel/jetstreaminstallした後はartisanコマンドでセットアップを行います。
php artisan jetstream:install [stack]stackには、Livewire か inertiaを指定します。この辺りはプロダクトの要件次第です。SEO必須ならLivewire、特にそういった制約はなく、かつvueやreactなどのメジャーなjsフレームワークに馴染みがあるなら
inertiaが良いでしょう。ちなみにイナーシャと読みます。今回は、inertiaを選択します。php artisan jetstream:install inertia npm install && npm run devこれでセットアップは完了しました。しかし、このままだとDBのセットアップができていないので、
http://127.0.0.1:8000/にアクセスしてもエラーになります。SQLSTATE[HY000] [2002] Connection refused (SQL: select * from `sessions` where `id` = x7v2PAHVtjL9uktGtbuedgx1bP3glsWwgbqFI3ZS limit 1)なので、vesselをサクッと入れてみます。
composer require shipping-docker/vessel --dev php artisan vendor:publish --provider="Vessel\VesselServiceProvider" bash vessel init ./vessel startその上でmigrateを実行します。
./vessel art migrateうまくセットアップできたように見えます。早速
/registerに移動してユーザー登録してみます。
登録が完了すると、ログイン状態になり
/dashboardにリダイレクトされます。
ここまでは、従来のログイン/ユーザー登録のスカフォールドと同じ機能群となります。しかし今回からは
/profileが追加され、非常にモダンなプロフィール画面が追加されていることがわかります。
なんと2要素認証の設定が。ここをENABLEにすると2要素認証が利用可能になります。
上記の画面のQRコードをGoogle Authenticatorなどで読み込ませておき、ログインします。ちゃんとコード入力を求められます。
Google Authenticatorで表示される値を入力すると、無事dashboard画面が表示されました。
加えて、APIトークンを使った認証も最初から提供されているようです。
以上。jetstreamのスカフォールドに注目してみました。他に
--teamsオプションのようなものもあるようですが一旦今までと同じ使い方さえできたら良かったので検証はこれで十分。また、今回からフロントエンドの技術スタックに TALL-stackとして注目されていたLivewireとtailwindCSSの組み合わせが簡単に導入できるようになったのも大きいです。この辺りは、バックエンド開発にしか馴染みのない人間にとっては特に恩恵が大きいと思いますので、この機会にぜひ色々チャレンジしてみてください。
さいごに
Laravel8では、プロジェクトを作った直後に自分で行なっていたmodelやrouteの設定変更が不要になったこと、またスカフォールドで提供される機能がよりモダンになり、登録制のサイト開発が簡単になったことが印象的です。他に、ジョブ実行でエクスポネンシャルバックオフを簡単に実装できたり、Schema Dumpにより開発環境での初期migrateを簡単にできるようになったとも聞いています。このため開発を実践する上での課題に対して、多くのソリューションを提供してくれているのがlaravel8なのかなと。今後新規開発では、LTSの6を使うか8を使うか実に悩ましいところです。
参考
- 投稿日:2020-09-06T17:58:54+09:00
LaravelでFormクラスのインストールメモ
・Class ‘Form’ not found
Laravelで開発したときにFormクラスでデータ送信をしようとしたら、ありませんとのことだったのでインストールしたときのメモ。Laravelのverは7.27.0
composer.jsonのrequireのセクションに以下を追加。
composer.json"require": { "php": "^7.2.5", "doctrine/dbal": "^2.10", "fideloper/proxy": "^4.2", "fruitcake/laravel-cors": "^2.0", "guzzlehttp/guzzle": "^6.3", "laravel/framework": "^7.24", "laravel/tinker": "^2.0", "laravelcollective/html": "^6.1.0" //ここを追加 },追加後、下記でcomposerを更新
composer updateこれで無事Formクラスが使えるようになった。
- 投稿日:2020-09-06T16:28:34+09:00
laravelのメール本文のテスト
Mailtrapを使った方法と
メールの受け取り先を共通にする方法の2つを紹介しますMailtrapを使った方法
.envファイルの修正
Mialtrapの設定を見ながらsmtpサーバの設定をenvファイルに反映する
MAIL_DRIVER=smtp MAIL_USERNAME=xxxxxxxxxxxxxx MAIL_PASSWORD=xxxxxxxxxxxxx MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525phpunit.xml
一時的にphpunitを使ったメール送信をMailtrapでキャッチしたい場合は
MAIL_DRIVERの値が上書きされてしまうので注意
MAIL_DRIVERの値をsmtpにする
ただ戻しておかないとCircleCIとかでテストを回すたびにMailtrapにメールが飛んでMailtrapの制限にいっちゃうので注意<?xml version="1.0" encoding="UTF-8"?> <phpunit backupGlobals="false" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false"> <testsuites> <testsuite name="Unit"> <directory suffix="Test.php">./tests/Unit</directory> </testsuite> <testsuite name="Feature"> <directory suffix="Test.php">./tests/Feature</directory> </testsuite> </testsuites> <filter> <whitelist processUncoveredFilesFromWhitelist="true"> <directory suffix=".php">./app</directory> </whitelist> </filter> <php> <server name="APP_ENV" value="local"/> <server name="BCRYPT_ROUNDS" value="4"/> <server name="CACHE_DRIVER" value="redis"/> <server name="MAIL_DRIVER" value="smtp"/> <server name="QUEUE_CONNECTION" value="sync"/> <server name="SESSION_DRIVER" value="array"/> </php> </phpunit>宛先のメールアドレスを変えて自分のメールボックスでメールを受けて確認する方法
config/mail.phpにtoを設定すると全てのメールが指定されたアドレスに送信されます
'to' => [ 'address' => 'example@example.com', 'name' => 'Example' ],
- 投稿日:2020-09-06T15:21:45+09:00
How to make delete button in laravel (File Upload Site #3)
- ルートを作成
web.phpRoute::delete('files/{id}', 'FilesController@destroy')->name('deletefile');
- View ファイルにフォームを追加する
home.blade.php<th> <form action="{{ route('deletefile', $file->id) }}" method="POST"> @csrf @method('DELETE') <button type="submit" class="btn btn-outline-danger btn-delete"><i class="fa fa-trash"></i>Delete</button> </form> </th>@csrf はクロスサイトリクエストフォージェリからの防蟻です。
3.コントローラーにfunction追加
filescontroller.phppublic function destroy($id) { $del = File::find($id); Storage::delete($del->path); $del->delete(); return redirect('/home'); }
- 投稿日:2020-09-06T14:46:28+09:00
Laravelでフォームのデータを処理する(2/2)DBのデータをトップページに表示する
はじめに
この記事はLaravelでフォームのデータを処理する(1/2)フォームで送信されたデータを取得しDBに挿入するの続きです。
今、掲示板のようなWebサービスを作成していて、Laravelで下記のような機能を実装したいです。
(1)フォームで送信されたデータを取得し、DBにデータとして挿入する。
(2)DBのデータをトップページに並べて表示する。こんな初歩的な機能ですが、頭を抱えまくったのでメモしておきます。Laravelでこれを実現するには、色々な方法があるみたいですが、初心者の時速40kmの走行方法(教習所内)をメモしておきたいと思います。今回は(2)を実装していきます。
環境:Laravel 7、MAMP 5.7
MAMP以外をご利用の方はそこだけ貴方の環境に合わせて変換していただければと思います。1)DBにデータが入っていることを確認する
言わずもがなですが、DBが空だと何も表示できないので、ダミーでいいのでデータを入れます。
2)トップページを用意し、プログラムを埋め込む
今回はBladeテンプレートを使用し、/resources/views直下に置いています。。(非常に簡略化しています)
例はライブの感想を投稿する掲示板なので、ライブの日付(live_date)や、ミュージシャン(musician)、会場(venue)、感想(text)などを表示したいです。index.blade.php<div> @foreach ($items as $item) <p>{{$item->live_date}}</p> <p>{{$item->musician}}</p> <p>{{$item->venue}}</p> <p>{{$item->text}}</p> @endforeach </div>ポイント↑:
- いきなり
{{$item->live_date}}みたいなプログラムを埋め込んでしまっていますが、最初は普通にHTMLだけで静的なサイトを準備して、ダミーでデータも書き込んでおいて、あとでその部分をプログラムで書き換えるのがいいと思います。- @はディレクティブと呼ばれ、Blade内でここに構文(ifなど)的なプログラムを書くよーという合図です。
- foreachで
$itemsという配列変数を受け取り、それを$itemとして一つずつ抜き出していきます。- その$itemは
{{$item->live_date}}で使用されます。- が、ここに$itemsという変数を渡して上げないといけません。それが次のコントローラの役割です。
3)コントローラ
2で作ったページに渡す変数を定義し、そのページ自体を返すという設定をします。第1話で作ったControllerで、/app/Http/Controllersフォルダに配置しています。
PostController<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; //DB接続のクラス class PostController extends Controller { //こちらを追加 public function index(Request $request) { $items = DB::select('select * from reviews'); return view('index', ['items' => $items]); }ポイント↑:
- DB::selectでDBの全てのデータ
*を呼び出し、index.blade.phpに渡す変数$itemsに代入します。- Viewsフォルダ直下にあるindex(.blade.php)を呼び出し、第二パラメータで$itemsを渡しています。(正直、その前の
'items' =>の意味がわかってません...)- あとはこのコントローラとアクションメソッドを呼び出す設定をしてあげればよくて、それをRoutingで行います。
4)ルーティング
web.php<?php use Illuminate\Support\Facades\Route; //デフォルトで書いてあるクラス Route::get('/', 'PostController@index'); //こちらを追加ポイント↑:
- 第1パラメータは
'/'、つまり、トップページ(=Document Rootを設定しているアドレス)にアクセスがあったらという条件設定- 第2パラメータ、PostControllerを呼び出し、そこにあるindexメソッドアクションを、、
- 呼び起こしなさい(=Route::get)という命令文
5)成功
この状態でドキュメントルートに設定しているページにアクセスすると、DBの情報が存在しているだけ全てトップページに表示されるはずです。
うまく行かない場合のヒント
- 私は当初、ルーティングのRoute::getをRoute::postにするという、ブレーキとアクセスを踏み間違えるようなミスで、エラーを起こしていました。
$itemsや$itemなどの複数形のsのあるなし、$の付け忘れ、その他スペルミスはないか。最後に
もし何かご指摘などありましたら、コメント欄などで頂戴できますと幸いです。
- 投稿日:2020-09-06T13:53:50+09:00
Docker × Laravel コードを自動整形するコンテナを構築する
PHP CS Fixer とは
PHP CS Fixer (PHP Coding Standards Fixer) とは、その名の通りPHPのコードをコーディング規約に沿うよう修正してくれるツールです。
前提
当記事は上記の記事の補足になる記事です。
docker-compose.ymlの編集
docker-compose.ymlservices: cs: image: herloct/php-cs-fixer volumes: - ./backend:/project
services.csを追記します。コマンド
# 自動整形しない(差分表示のみ) $ docker-compose run cs fix --dry-run -v --diff --diff-format udiff . # 自動整形する $ docker-compose run cs fix -v --diff --diff-format udiff .Makefile
コマンドが長いのでMakefileを用意しておくと良いです。
dry-cs: docker-compose run cs fix --dry-run -v --diff --diff-format udiff . fix-cs: docker-compose run cs fix -v --diff --diff-format udiff .下記のコマンドで実行できるようになります。
$ make dry-cs $ make fix-cs参考
- 投稿日:2020-09-06T13:09:20+09:00
Laravel で CRUD をコマンド一つで出力するライブラリ
とにかく、マスター管理機能や、CRUDを書くのがめんどくさいと感じていたので、artisan コマンドを拡張して一発で必要なファイルを出力するライブラリを書きました。
使い方などは readme にも書いているのですが、github では英語で書いているので、日本語原文をここに公開しておきます。
laravel-crud-command
前もって作成されたデータベースから情報を取得し、artisan コマンドで CRUD に必要なファイルを一括で出力します。
特徴
- MySQLのテーブルコメント、およびカラムコメントから翻訳用のファイルを生成します。
- resourcees/lang/{locale}/tables.php
- resourcees/lang/{locale}/columns.php
- MySQLのテーブル定義からバリデーションルール作成します。
- rules/{model}.php
- モデル作成
- テーブルのカラムからプロパティを自動生成します。
- 外部キー制約から belongsTo と hasMany、belongsToMany メソッド を出力します。
- コントローラー作成
- CRUDに必要なメソッドを全て出力します。
- グローバルスコープ作成
- 各モデルに対して一つのグローバルスコープクラスを作成します。
- フォームリクエスト・クラス作成
- テーブル定義から自動的にルールを出力します。
- ビュー・コンポーザー作成
- 外部キーの定義からフォーム部品をビューに渡すロジックを自動的に生成します。
- ビュー作成
- 一覧、詳細、新規作成、更新 を自動で生成します。
- パンくずリスト作成
- CRUDで生成したファイルには自動的にパンくずリストを出力します。
- テンプレートのカスタマイズ
- プロジェクトによっては、出力するテンプレートをカスタマイズする必要があると思います。その場合は、stub をお好みの形で編集しておくことが可能です。
インストール
composer require shibuyakosuke/laravel-crud-commandセットアップ
1. 何よりも先に、マイグレーションファイルを作成することから始めます。例示のように、コメントと外部キーの設定を必ず行ってください。
- モデルを生成するテーブルには必ず、テーブルコメントをつけてください。
- 多対多の中間テーブルにはコメントをつけてはいけません。
テーブルコメント機能については、diplodocker/comments-loader を利用しています。
use Illuminate\Database\Schema\Blueprint; Schema::create('users', function (Blueprint $table) { $table->id()->comment('ID'); $table->unsignedBigInteger('role_id')->nullable()->comment('ロールID'); $table->unsignedBigInteger('company_id')->nullable()->comment('会社ID'); $table->string('name')->comment('氏名'); $table->string('email')->unique()->comment('メールアドレス'); $table->timestamp('email_verified_at')->nullable()->comment('メール認証日時'); $table->string('password')->comment('パスワード'); $table->rememberToken()->comment('リメンバートークン'); $table->timestamp('created_at')->nullable()->comment('作成日時'); $table->timestamp('updated_at')->nullable()->comment('更新日時'); $table->softDeletes()->comment('削除日時'); $table->tableComment('ユーザー'); // Table comment helps you to make language files. // Foreign key helps you to make belongsTo methods, hasMany methods and views . $table->foreign('role_id')->references('id')->on('roles'); $table->foreign('company_id')->references('id')->on('companies'); });2. マイグレーションを実行する
php artisan migrate3. config/app.php を編集して言語を設定する
'locale' => 'ja',4. リソースを出力します
php artisan crud:setup5. CRUDファイルを全て出力します
php artisan make:crud usersオプション
--force
ファイルが存在しても、上書きして出力します。--api
通常のコントローラを出力せず、REST用のコントローラのみを出力します。--with-api
通常のコントローラとREST用のコントローラを出力します。--apiと同時に指定はできません。--sortable
テーブルのソート機能を合わせて出力します。--with-export
テーブルのエクスポート機能を合わせて出力します。--with-filter
テーブルのフィルタ機能を合わせて出力します。--with-trashed
テーブルのエクスポート機能を合わせて出力します。その他コマンド
出力するファイルをカスタマイズする場合、以下のコマンドを実行すると、/stubs ディレクトリに .stub を拡張子に物ファイルが複数出力されます。
出力したファイルをカスタマイズしてください。php artisan stub:publish
- 投稿日:2020-09-06T11:57:08+09:00
laravel Class ‘Form’ not found の対処法
調べてみると、composer.jsonでlaravelcollective/htmlを追記してcomposer updateするって書いてあるけど、やってみるとエラーでうまくインストールできなかったので以下をやってみたらすんなりFormファサードを読み込めた
・composer.jsonは編集せずそのまま
・ターミナルから composer require laravelcollective/html ←version指定しない
...これだけ。
すると、composerが自動でlaravelのバージョンに合わせたlaravelcollectiveをインストールしてくれる$ composer require laravelcollective/html #version指定しない Using version ^6.1 for laravelcollective/html ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing laravelcollective/html (v6.1.2): Downloading (100%) Package jakub-onderka/php-console-color is abandoned, you should avoid using it. Use php-parallel-lint/php-console-color instead. Package jakub-onderka/php-console-highlighter is abandoned, you should avoid using it. Use php-parallel-lint/php-console-highlighter instead. Package phpunit/php-token-stream is abandoned, you should avoid using it. No replacement was suggested. Writing lock file Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: laravelcollective/html Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully.
- 投稿日:2020-09-06T02:51:24+09:00
AWSで割とモダンな技術使う大学生日記①
前置き
terraformで構成しようとしたが、まずはAWSを理解するためコンソールから構築
本記事は私自身が少し悩んだ、ネットワークの構成やトラブルシューティングについて重点的に記載されております。ハンズオン形式の記事はQiita等にも多くございますのでそちらを参照しつつ、こちらの記事でより理解を深めていただければな、と思います。
使用技術 Laravel6.x AWS ECS(Fargate), RDS, ElasticCache Docker, docker-compose ネットワーク構成
VPCは10.1.0.0/16を利用。
サブネットの利用感は下記みたいな感じ
サブネット 用途 10.1.0.0/24, 10.1.1.0/24 Publicサブネット。LBに使うサブネット 10.1.2.0/24, 10.1.3.0/24 Privateサブネット。LBからECSに行くサブネット 10.1.4.0/24, 10.1.5.0/24 ECS~RDS間のサブネット。ECSからDBに接続するサブネット 10.1.6.0/24 EC2~RDS間のサブネット。EC2からDBに接続するサブネット migrationはDockerfileには置かないのでDB接続用のEC2インスタンスを用意する。
(userのデータとかも取得できるので)ルートテーブルでInternetGatewayと接続するのはLBとDB接続用のEC2インスタンスのみ。
appサーバーとDBサーバー(RDS)はローカルでしか接続できないように設定する。
※ネットワークの軽い知識があれば上記のサブネットや、CIDRを理解できます。
30分とかで理解できると思うのでYouTubeとかでおさらいしておいてください。
Fargateタイプにおいてのコンテナ間通信について
webコンテナは
Nginx(読み方はエンジンエックスっていうらしい、最近までエヌジンクスって読んでた)を利用していてappコンテナはPHPでフレームワークはLaravel。
そのためwebコンテナからappコンテナへの通信が必要。
ローカル内では下記のように.confファイルを記述する。
ポートはwebはHTTP通信のため80、appは9000。
(docker-compose.ymlで名前をそれぞれwebとappで指定しておく)default.conf01:server { 02: listen 80; 03: root /work/public; 04: index index.php; 05: charset utf-8; 06: 07: location / { 08: root /work/public; 09: try_files $uri $uri/ /index.php$is_args$args; 10: } 11: 12: location ~ \.php$ { 13: fastcgi_split_path_info ^(.+\.php)(/.+)$; 14: fastcgi_pass app:9000; 15: fastcgi_index index.php; 16: include fastcgi_params; 17: fastcgi_param SCRIPT_FILENAME /work/public/index.php; 18: fastcgi_param PATH_INFO $fastcgi_path_info; 19: } 20:}上記のような設定だとAWS ECSのFargate起動タイプだとヘルスチェックで
Taskが実行できません。
というエラーが出ます。そこで14行目を下記のように変更します。default.conf14: fastcgi_pass localhost:9000;上記のようにする理由としては、Fargate起動タイプは同じローカルネットワーク内でtaskが実行されるためlocalhostは共有している。そのためコンテナ間通信は
localhost:ポート番号で指定する。トラブルシューティング
ヘルスチェックが通らない。
ECSを起動する際に、ヘルスチェックが通らず、taskが実行できなかったとき。
Dockerfileへの知見が甘かったため、
待つポート番号やコピーするディレクトリを間違えていたりした。
Dockerfileの最後の行にEXPOSE <ポート番号>を指定すること。
また、ローカルでコンテナを起動し期待するディレクトリにソースが入っているかを確認するといい。ヘルスチェックは通るがLBのDNSに接続してもログインページが表示されない
ECS起動後にヘルスチェックが通るがログインページは表示されない場合。
ヘルスチェックは通っている ↓ ローカル内での通信はできている ↓ ネットワークの構成を確認し、落ちているところを確認主に原因はネットワーク。
SGのインバウンドルールは適切か。ルートテーブルは適切か。再度確認する。
この過程が割と大事でCloudFomationとかで構成すると割と曖昧になりがちなネットワーク構成を理解できる。私の場合は、LBのターゲットグループを複数作成しており、利用したいターゲットグループの優先順位が一番ではなかったため、ログインページが表示されていなかった。セッションの共有
可用性のために、複数のタスクを実行し、AutoScallingをオンにしていると思うので
セッションの共有をしておかなければいけない。
Laravelのセッションはデフォルトでfileを選択しておりProject/storage/sessionsに保存されている。実行されるタスクが複数でセッションの保存先がfileの場合、それぞれのappコンテナの中に保存されてしまうので、セッションの共有をしなければいけない。
今回は、AWSのマネージドサービスであるElasticCacheを利用する。
※実装の工数上、現状(2020/09/06)では未構築のため後日追記する。
その際には上記のネットワーク構成にも修正を加える予定。
Dockerfileとdocker-compose.yml
いや、GitHub載せろよ。って思うよね。
僕的に、Qiita見ながらコピペできるのが理想なのでDockerfileとdocker-compose.ymlはここに書きます。default.confは上記に記載済み。Fargate起動タイプの時はlocalhost指定してください。
ディレクトリ構成も載せておきます。| ├── docker | | │ ├── nginx | | ├── Dockerfile │ │ └── default.conf │ └── php │ ├── Dockerfile │ └── php.ini ├── docker-compose.yml | ├── .env | ├── .gitignore | └── livedocker-compose.ymlversion: "3" services: app: build: context: . dockerfile: ./docker/php/Dockerfile args: - TZ=${TZ} ports: - ${APP_PORT}:9000 volumes: - ./live:/work - ./logs:/var/log/php - ./docker/php/php.ini:/usr/local/etc/php/php.ini working_dir: /work environment: # ここは要設定 - DB_CONNECTION={DB_CONNECTION} - DB_HOST=${DB_HOST} - DB_DATABASE=${DB_DATABASE} - DB_USERNAME=${DB_USERNAME} - DB_PASSWORD=${DB_PASSWORD} - TZ=${TZ:-Asia/Tokyo} web: build: context: . dockerfile: ./docker/nginx/Dockerfile depends_on: - app ports: - ${WEB_PORT:-80}:80 volumes: - ./live:/work - ./logs:/var/log/nginx - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf environment: - TZ=${TZ:-Asia/Tokyo} volumes: db-store:docker/nginx/DockerfileFROM nginx:1.19-alpine COPY ./docker/nginx/default.conf /etc/nginx/conf.d/default.conf COPY ./live /work EXPOSE 80dokcer/php/DockerfileFROM php:7.4-fpm-alpine ARG PSYSH_DIR=/usr/local/share/psysh ARG PHP_MANUAL_URL=http://psysh.org/manual/ja/php_manual.sqlite ARG TZ ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer RUN set -eux && \ apk update && \ apk add --update --no-cache --virtual=.build-dependencies \ autoconf \ gcc \ g++ \ make \ tzdata && \ apk add --update --no-cache \ icu-dev \ oniguruma-dev \ libzip-dev && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ echo ${TZ} > /etc/timezone && \ pecl install xdebug && \ apk del .build-dependencies && \ docker-php-ext-install intl pdo_mysql mbstring zip bcmath && \ docker-php-ext-enable xdebug && \ mkdir $PSYSH_DIR && wget $PHP_MANUAL_URL -P $PSYSH_DIR && \ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer && \ composer config -g repos.packagist composer https://packagist.jp && \ composer global require hirak/prestissimo RUN apk add --no-cache freetype libpng libjpeg-turbo freetype-dev libpng-dev libjpeg-turbo-dev && \ docker-php-ext-configure gd \ --with-jpeg=/usr/include/ \ --with-freetype=/usr/include/ && \ NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ docker-php-ext-install -j${NPROC} gd && \ apk del --no-cache freetype-dev libpng-dev libjpeg-turbo-dev ADD ./live /work WORKDIR /work RUN chmod -R 777 /work/storage \ /work/bootstrap/cache RUN composer install RUN php artisan key:generate RUN php artisan config:clear RUN php artisan config:cache # RUN php artisan migrate # RUN php artisan db:seed EXPOSE 9000php.iniは自分で検索してください。笑
.envファイルがないと起動できないので各々の用途に合わせて記述してください。
一応下記に書いておきます。TZ=Asia/Tokyo APP_PORT=9000 DB_CONNECTION=mysql DB_HOST=<RDSのエンドポイント> DB_PORT=3306 DB_DATABASE=<DB名> DB_USERNAME=<username, rootでもいい> DB_PASSWORD=<セキュアなやつにしてね>以上です。
まだ、CI/CDとかできていないので別記事にでも書こうと思っております。
AWS第一弾でした。
docker/php/Dockerfileは割と書きすぎてる気がするのでこれいらんよ、とかあったら教えて欲しいです。未熟者の記事ですが読んでいただいてありがとうございます。
- 投稿日:2020-09-06T00:12:44+09:00
Laravel6 ユーザと管理者の認証を分けて管理者の認証情報のみ名前とパスワードだけにする
目的
- ユーザと管理者とで認証を分ける方法をまとめる。
実施環境
- ハードウェア環境
項目 情報 OS macOS Catalina(10.15.5) PC MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2 GHz クアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB
- ソフトウェア環境
項目 情報 備考 PHP バージョン 7.4.3 Homwbrewを用いて導入 Laravel バージョン 6.18.35 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- 先の実施環境に近い環境が整っていること。
- Laravelは最新バージョン用に構築しているがアプリ作成コマンド実行時に5.6を指定して作成する。
前提情報
- DockerやAWSなどは使用せずにMacのローカル環境に直接Laravelアプリを作成する。
- 若干難易度が高い作業であるためなるべくわかりやすい様に丁寧に記載する。
- 本記事の内容を最初から実施していけば誰でもユーザと管理者別々での認証を行えることを目指す。
- 管理者認証情報は管理者名、メールアドレス、パスワードとする。
- 作業複雑化を避けるため管理者用のパスワードはアプリ側から変更できる様にしない。
- 既存のAuth認証コントローラを追記編集して管理者の認証機能を作成する。
- 下記のドキュメントを参考に必要名部分のみを抜粋して実装する。また、説明をより分かりやすくするために若干実装の順番を変更する。
読後感
- Laravel5.6のでユーザ認証と管理者認証機能のついたアプリを作成することができる。
概要
- データベースの作成
- Laravelアプリの作成と初期設定
- ユーザ認証機能作成
- 管理者情報用テーブルの準備
- ガードとプロバイダの追加
- コントローラの修正
- 認証用ページの作成
- 認証後遷移ページの作成
- ルーティングの記載と認証後遷移ページの設定と例外時の処理の記載
- 確認
詳細
データベースの作成
下記コマンドを実行してMySQLにターミナルからログインする。(MySQLのrootユーザのパスワードを忘れてしまった方はこちら→Mac ローカル環境の MySQL 8.x のrootパスワードを忘れた時のリセット方法)
$ mysql -u root -p下記SQLを実行して「multi_auth_laravel_6」データベースを作成する。
create database multi_auth_laravel_6;下記SQLを実行してデータベース一覧を出力して「multi_auth_laravel_6」が含まれていることを確認する。確認後、MySQLをログアウトする。
show databases;Laravelアプリの作成と初期設定
- Laravelアプリを作成する任意のディレクトリに移動する。
下記コマンドを実行して「multi_auth_laravel_6」というLaravel6のアプリを作成する。(完了まで時間がかかる可能性があるので少し待機する。)
$ composer create-project laravel/laravel multi_auth_laravel_6 "6.*"下記コマンドを実行して作成されたアプリ名ディレクトリに移動する。以後のコマンドは特に記載がない場合、このmulti_authディレクトリ内部で実行する物とする。
$ cd multi_auth下記コマンドを実行して.envファイルを開く。
$ vi .env下記の様に.envファイルのデータベースの記述を修正する。
multi_auth_laravel_6/.envDB_DATABASE=multi_auth_laravel_6 DB_USERNAME=root DB_PASSWORD=mysql -u root -pコマンドを実行した際に入力したパスワード修正後の.envファイルの全体の内容を記載する。
multi_auth_laravel_6/.envAPP_NAME=Laravel APP_ENV=local APP_KEY=アプリキーの記載は各個人で異なります。 APP_DEBUG=true APP_URL=http://localhost LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=multi_auth_laravel_6 DB_USERNAME=root DB_PASSWORD=皆さんの環境のMySQLのrootユーザのパスワード BROADCAST_DRIVER=log CACHE_DRIVER=file QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}" AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"下記コマンドを実行して初期マイグレーションファイルをマイグレートする。
$ php artisan migrate下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスしてLaravelの初期画面が表示されることを確認する。
ユーザ認証機能作成
下記コマンドを実行してユーザ認証機能を作成する。
$ composer require laravel/ui "^1.0" --dev $ php artisan ui vue --auth $ npm install && npm run dev下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスしてLaravelの初期画面を開く。
右上の「REGISTER」をクリックする。
各種情報を入力して「Register」をクリックする。
「Register」をクリック後角の画面に遷移することを確認する。
管理者情報用テーブルの準備
下記コマンドを実行してAdminモデルファイルとadminsテーブル作成用マイグレーションファイルを作成する。
$ php artisan make:model Admin -m下記コマンドを実行して先に作成したマイグレーションファイルを開く。(YYYY_MM_DD_XXXXXXの部分はマイグレーションファイル作成日により異なる。)
$ vi database/migrations/YYYY_MM_DD_XXXXXX_create_admins_table.php開いたマイグレーションファイルを下記の様に追記する。
multi_auth_laravel_6/database/migrations/YYYY_MM_DD_XXXXXX_create_admins_table.php<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateAdminsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('admins', function (Blueprint $table) { $table->increments('id'); //下記から追加 $table->string('name'); $table->string('email')->unique(); $table->string('password'); $table->boolean('is_super')->default(false); $table->rememberToken(); //上記までを追加 $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('admins'); } }下記コマンドを実行して今記載したマイグレーションファイルをマイグレートする。
$ php artisan migrate下記コマンドを実行して先に作成したモデルファイルを開く。
$ vi app/Admin.php開いたモデルファイルの内容を全て削除し、下記の内容をコピーアンドペーストで記載する
multi_auth_laravel_6/app/Admin.php<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class Admin extends Authenticatable { use Notifiable; protected $guard = 'admin'; protected $fillable = [ 'name', 'email', 'password', ]; protected $hidden = [ 'password', 'remember_token', ]; }ガードとプロバイダの追加
下記コマンドを実行しガードとプロバイダを定義しているファイルを開く。
$ vi config/auth.phpガードの記載を下記の様に追記する。
multi_auth_laravel_6/config/auth.php/* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you | here which uses session storage and the Eloquent user provider. | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | Supported: "session", "token" | */ 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], //下記を追記 'admin' => [ 'driver' => 'session', 'provider' => 'admins', ], //上記までを追記 ],同ファイル内のプロバイダの記載も追記を行う。
multi_auth_laravel_6/config/auth.php/* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], //下記を追記する 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], //上記までを追記する // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ],追記後の
multi_auth_laravel_6/config/auth.phpのファイルの全体を下記に記載する。multi_auth_laravel_6/config/auth.php<?php return [ /* |-------------------------------------------------------------------------- | Authentication Defaults |-------------------------------------------------------------------------- | | This option controls the default authentication "guard" and password | reset options for your application. You may change these defaults | as required, but they're a perfect start for most applications. | */ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], /* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you | here which uses session storage and the Eloquent user provider. | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | Supported: "session", "token" | */ 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], //下記を追記する 'admin' => [ 'driver' => 'session', 'provider' => 'admins', ], //上記までを追記する ], /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], //下記を追記する 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], //上記までを追記する // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* |-------------------------------------------------------------------------- | Resetting Passwords |-------------------------------------------------------------------------- | | You may specify multiple password reset configurations if you have more | than one user table or model in the application and you want to have | separate password reset settings based on the specific user types. | | The expire time is the number of minutes that the reset token should be | considered valid. This security feature keeps tokens short-lived so | they have less time to be guessed. You may change this as needed. | */ 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ], ];コントローラの修正
- 下記の二つのコントローラを修正する。
multi_auth_laravel_6/app/Http/Controllers/Auth/LoginController.phpmulti_auth_laravel_6/app/Http/Controllers/Auth/RegisterController.php下記コマンドを実行してログインを司るコントローラファイルを開く。
$ vi app/Http/Controllers/Auth/LoginController.php開いたコントローラファイルを下記の様に修正する。
multi_auth_laravel_6/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; use Auth; // 上記までを追記する class LoginController extends Controller { /* |-------------------------------------------------------------------------- | Login Controller |-------------------------------------------------------------------------- | | This controller handles authenticating users for the application and | redirecting them to your home screen. The controller uses a trait | to conveniently provide its functionality to your applications. | */ 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'); //下記を追記する $this->middleware('guest:admin')->except('logout'); } // 下記を追記する public function showAdminLoginForm() { return view('auth.login', ['url' => 'admin']); } public function adminLogin(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'password' => 'required|min:6' ]); if (Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password], $request->get('remember'))) { return redirect()->intended('/admin'); } return back()->withInput($request->only('email', 'remember')); } // 上記までを追記 }下記コマンドを実行してログインを司るコントローラファイルを開く。
$ vi app/Http/Controllers/Auth/RegisterController.php開いたコントローラファイルを下記の様に修正する。
multi_auth_laravel_6/app/Http/Controllers/Auth/RegisterController.php<?php namespace App\Http\Controllers\Auth; //下記を追記する use App\Admin; use Illuminate\Http\Request; //上記までを追記する 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 { /* |-------------------------------------------------------------------------- | Register Controller |-------------------------------------------------------------------------- | | This controller handles the registration of new users as well as their | validation and creation. By default this controller uses a trait to | provide this functionality without requiring any additional code. | */ 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'); //下記を追記する $this->middleware('guest:admin'); } /** * 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:6|confirmed', ]); } /** * 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']), ]); } //下記を追記する public function showAdminRegisterForm() { return view('auth.register', ['url' => 'admin']); } protected function createAdmin(Request $request) { $this->validator($request->all())->validate(); $admin = Admin::create([ 'name' => $request['name'], 'email' => $request['email'], 'password' => Hash::make($request['password']), ]); return redirect()->intended('login/admin'); } //上記までを追記する }管理者ログインページのビューファイルの修正
下記コマンドを実行してログインページのビューファイルを開く。
$ vi resources/views/auth/login.blade.php開いたビューファイルを下記の様に修正する。
multi_auth_laravel_6/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"> {{ isset($url) ? ucwords($url) : ""}} {{ __('Login') }}</div> <div class="card-body"> @isset($url) <form method="POST" action='{{ url("login/$url") }}' aria-label="{{ __('Login') }}"> @else <form method="POST" action="{{ route('login') }}" aria-label="{{ __('Login') }}"> @endisset @csrf <!-- 上記までを修正する --> <div class="form-group row"> <label for="email" class="col-sm-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required autofocus> @if ($errors->has('email')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('email') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required> @if ($errors->has('password')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('password') }}</strong> </span> @endif </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"> {{ __('Remember Me') }} </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"> {{ __('Login') }} </button> <a class="btn btn-link" href="{{ route('password.request') }}"> {{ __('Forgot Your Password?') }} </a> </div> </div> </form> </div> </div> </div> </div> </div> @endsection管理者登録ページのビューファイルの修正
下記コマンドを実行してログインページのビューファイルを開く。
$ vi resources/views/auth/register.blade.php開いたビューファイルを下記の様に修正する。
multi_auth_laravel_6/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"> {{ isset($url) ? ucwords($url) : ""}} {{ __('Register') }}</div> <div class="card-body"> @isset($url) <form method="POST" action='{{ url("register/$url") }}' aria-label="{{ __('Register') }}"> @else <form method="POST" action="{{ route('register') }}" aria-label="{{ __('Register') }}"> @endisset @csrf <!-- 上記までを修正する --> <div class="form-group row"> <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label> <div class="col-md-6"> <input id="name" type="text" class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}" name="name" value="{{ old('name') }}" required autofocus> @if ($errors->has('name')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('name') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required> @if ($errors->has('email')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('email') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required> @if ($errors->has('password')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('password') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label> <div class="col-md-6"> <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required> </div> </div> <div class="form-group row mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Register') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection認証後遷移ページの作成
下記コマンドを実行してビューファイルを作成する。
$ touch resources/views/layouts/auth.blade.php $ touch resources/views/admin.blade.php下記コマンドを実行して先に作成したビューファイルを開く。
$ vi resources/views/layouts/auth.blade.php下記の内容をコピーアンドペーストで貼り付ける。
multi_auth_laravel_6/resources/views/layouts/auth.blade.php<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }}</title> <!-- Scripts --> <script src="{{ asset('js/app.js') }}" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="https://fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600" rel="stylesheet" type="text/css"> <!-- Styles --> <link href="{{ asset('css/app.css') }}" rel="stylesheet"> </head> <body> <div id="app"> <nav class="navbar navbar-expand-md navbar-light navbar-laravel"> <div class="container"> <a class="navbar-brand" href="{{ url('/') }}"> {{ config('app.name', 'Laravel') }} </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <!-- Left Side Of Navbar --> <ul class="navbar-nav mr-auto"> </ul> <!-- Right Side Of Navbar --> <ul class="navbar-nav ml-auto"> <!-- Authentication Links --> <li class="nav-item dropdown"> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> Hi There <span class="caret"></span> </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} </a> <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;"> @csrf </form> </div> </li> </ul> </div> </div> </nav> <main class="py-4"> @yield('content') </main> </div> </body> </html>下記コマンドを実行して先に作成したビューファイルを開く。
$ vi resources/views/admin.blade.php下記の内容をコピーアンドペーストで貼り付ける。
multi_auth_laravel_6/resources/views/admin.blade.php@extends('layouts.auth') @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"> Hi boss! </div> </div> </div> </div> </div> @endsection下記コマンドを実行して先に作成したビューファイルを開く。
$ vi resources/views/layouts/home.blade.phpすでに記載されている内容を削除し下記の内容をコピーアンドペーストで貼り付ける。
multi_auth_laravel_6/resources/views/layouts/home.blade.php@extends('layouts.auth') @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"> Hi there, regular user </div> </div> </div> </div> </div> @endsectionルーティングの記載と認証後遷移ページの設定と例外時の処理の記載
下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php下記の様に追記する。
multi_auth_laravel_6/routes/web.php<?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); //下記を追記する Route::get('/login/admin', 'Auth\LoginController@showAdminLoginForm'); Route::get('/register/admin', 'Auth\RegisterController@showAdminRegisterForm'); Route::post('/login/admin', 'Auth\LoginController@adminLogin'); Route::post('/register/admin', 'Auth\RegisterController@createAdmin'); Route::view('/home', 'home')->middleware('auth'); Route::view('/admin', 'admin'); //上記までを追記するリダイレクトの設定
下記コマンドを実行してリダイレクトを司るミドルウェアファイルを開く
$ vi app/Http/Controllers/Middleware/RedirectIfAuthenticated.php下記の様に修正する。
multi_auth_laravel_6/app/Http/Controllers/Middleware/RedirectIfAuthenticated.php<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class RedirectIfAuthenticated { public function handle($request, Closure $next, $guard = null) { // 下記を追記する if ($guard == "admin" && Auth::guard($guard)->check()) { return redirect('/admin'); } // 上記までを追記する if (Auth::guard($guard)->check()) { return redirect('/home'); } return $next($request); } }例外時の設定
下記コマンドを実行してハンドラーファイルを開く。
$ vi app/Exceptions/Handler.php下記のようにハンドラーファイルを修正する。
multi_auth_laravel_6/app/Exceptions/Handler.php<?php namespace App\Exceptions; use Exception; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; //下記を追記する use Illuminate\Auth\AuthenticationException; use Auth; //上記までを追記する class Handler extends ExceptionHandler { /** * A list of the exception types that are not reported. * * @var array */ protected $dontReport = [ // ]; /** * A list of the inputs that are never flashed for validation exceptions. * * @var array */ protected $dontFlash = [ 'password', 'password_confirmation', ]; /** * Report or log an exception. * * @param \Exception $exception * @return void */ public function report(Exception $exception) { parent::report($exception); } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $exception * @return \Illuminate\Http\Response */ public function render($request, Exception $exception) { return parent::render($request, $exception); } //下記を追記する protected function unauthenticated($request, AuthenticationException $exception) { if ($request->expectsJson()) { return response()->json(['error' => 'Unauthenticated.'], 401); } if ($request->is('admin') || $request->is('admin/*')) { return redirect()->guest('/login/admin'); } return redirect()->guest(route('login')); } //上記までを追記する }確認
下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスしてLaravelの初期画面が表示されることを確認する。
下記にアクセスし必要情報を入力後「Registar」をクリックする。
下記の画面にリダイレクトすることを確認する。一つ前の手順で入力した管理者登録時の情報を入力し「Login」をクリックする。
下記のページ「Hi boss!」が表示されれば管理者としてのログインは完了である。
参考文献


























