■目次
Vagrantを準備Ansibleで環境構築LaravelをインストールLaravelでプログラム作成保留トラブル
■Vagrantを準備
VagrantでCentOS7を新規にインストールし、そこに開発環境を構築する 作業フォルダは、ここでは cd C:\vagrant\laravel6 とする VagrantのIPアドレスは、ここでは 192.168.33.10 とする ■ボックスの追加 以下のコマンドで公式のCentOS7を追加 vagrant box add centos/7 vagrant box list で確認すると「centos/7 (virtualbox, 1905.1)」が追加されている ■Vagrantfile
Vagrant.configure(2) do |config| config.vm.box = "centos/7" config.vm.box_check_update = false config.vm.network "forwarded_port", guest: 80, host: 8080 config.vm.network "private_network", ip: "192.168.33.10" config.vm.synced_folder "C:/vagrant/laravel6/code", "/var/www" end
■起動 cd C:\vagrant\laravel6 vagrant up ■終了する場合 cd C:\vagrant\laravel6 vagrant halt ■破棄する場合 cd C:\vagrant\laravel6 vagrant destroy ■初期起動時にエラーになった場合 vagrant plugin install vagrant-vbguest vagrant halt vagrant up
■Ansibleで環境構築
■SELinuxを無効化 ※nginxの動作に支障をきたすため無効化 CentOSのバージョンによっては、はじめから無効になっている # getenforce Enforcing … SELinuxが有効 # setenforce 0 … SELinuxを無効化 # getenforce Permissive … SELinuxが無効 # vi /etc/sysconfig/selinux
SELINUX=enforcing SELINUX=disabled … システム起動時にSELinuxを無効化
■Ansibleをインストール Ansibleを手動でインストールする $ sudo su - # yum -y install ansible Playbookは以下の場所に配置するものとする(GitからPULLする) C:\vagrant\laravel6\code\ansible つまり、Vagrant内の以下に同期される /var/www/ansible ■Ansibleを実行 Ansibleのhostsファイルの最後に設定を追加 # vi /etc/ansible/hosts
[localhost] 127.0.0.1
# exit 接続をテスト $ ansible localhost -m ping --connection=local Playbookの場所へ移動して実行 $ cd /var/www/ansible $ ansible-playbook site.yml --connection=local ブラウザから以下にアクセスして確認 http://192.168.33.10/ ■データベースを作成 データベースと接続ユーザを作成 $ mysql -u root -p mysql> GRANT ALL PRIVILEGES ON main.* TO webmaster@localhost IDENTIFIED BY '1234'; mysql> FLUSH PRIVILEGES; mysql> CREATE DATABASE main DEFAULT CHARACTER SET utf8mb4; mysql> QUIT; ■データベースへの接続をテスト # mysql -u webmaster -p 1234 以下でPHPからアクセスできる
<?php try { $pdo = new PDO( 'mysql:dbname=main;host=localhost', 'webmaster', '1234' ); $stmt = $pdo->query('SELECT NOW() AS now;'); $data = $stmt->fetch(PDO::FETCH_ASSOC); echo "<p>" . $data['now'] . "</p>\n"; } catch (PDOException $e) { exit($e->getMessage()); } $pdo = null;
■Laravelをインストール
インストール 6.x Laravel https://readouble.com/laravel/6.x/ja/installation.html ■配置 C:\vagrant\laravel6\code\main を C:\vagrant\laravel6\code\main_backup に変更する # su -s /bin/bash - nginx $ cd /var/www $ composer create-project --prefer-dist "laravel/laravel=6.0.*" main ブラウザから以下にアクセスして確認 http://192.168.33.10/ ■hostsを設定 Vagrant に laravel6.local でアクセスできるようにする C:\Windows\System32\drivers\etc\hosts
192.168.33.10 laravel6.local
ブラウザから以下にアクセスして確認 http://laravel6.local/ ■プログラムの調整 環境によってはマイグレーションがエラーになるので、app/Providers/AppServiceProvider.php を以下のように修正する - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Schema; … 追加 〜中略〜 public function boot() { Schema::defaultStringLength(191); … 追加 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ■初期設定 .env の設定を以下のように編集する - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - APP_URL=http://laravel6.local DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=main DB_USERNAME=webmaster DB_PASSWORD=1234 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ■動作確認 http://laravel6.local/
■Laravelでプログラム作成
■言語ファイルを配置 validation.php言語ファイル 6.x Laravel https://readouble.com/laravel/6.x/ja/validation-php.html $ php -r "copy('https://readouble.com/laravel/6.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');" $ php -f install-ja-lang.php $ php -r "unlink('install-ja-lang.php');" ■タイムゾーンとロケールを変更 config/app.php でタイムゾーンとロケールを変更
'timezone' => 'Asia/Tokyo', 'locale' => 'ja',
■デフォルトのマイグレーションを調整 不要なマイグレーションを削除 database/migrations/2019_08_19_000000_create_failed_jobs_table.php デフォルトのマイグレーションを調整 database/migrations/2014_10_12_000000_create_users_table.php
public function up() { Schema::create('users', function (Blueprint $table) { $table->engine = 'InnoDB'; $table->bigIncrements('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->timestamps(); }); DB::statement('ALTER TABLE users COMMENT \'ユーザ\''); }
database/migrations/2014_10_12_100000_create_password_resets_table.php
public function up() { Schema::create('password_resets', function (Blueprint $table) { $table->engine = 'InnoDB'; $table->string('email')->index()->comment('メールアドレス'); $table->string('token')->comment('トークン'); $table->timestamp('created_at')->nullable(); }); DB::statement('ALTER TABLE password_resets COMMENT \'パスワードリセット\''); }
マイグレーションを実行 $ php artisan migrate ■認証機能を作成 ※「php artisan make:auth」はLaravel6では使えない ※「composer require laravel/ui --dev」もLaravel7が出たからかLaravel6ではエラーになるようになった $ composer require laravel/ui 1.* $ php artisan ui vue --auth 画面の右上に「LOGIN」「REGISTER」が表示されていて、ここからログインと登録ができる この時点ではCSSとJavaScriptがコンパイルされていないので、見た目は質素なものになるが動作はする 認証処理の流れはLaravel5から大きく変わっていないようなので、「Laravel.txt」の「認証」にある処理の流れを参考にする 認証 6.x Laravel https://readouble.com/laravel/6.x/ja/authentication.html 更新! Laravel6/7「make:Auth」が無くなった 〜Laravel6/7でのLogin機能の実装方法〜MyMemo - Qiita https://qiita.com/daisu_yamazaki/items/a914a16ca1640334d7a5 Laravel6 ログイン機能を実装する - Qiita https://qiita.com/ucan-lab/items/bd0d6f6449602072cb87 [PHP]Laravel6でmake:authするには - Qiita https://qiita.com/kusumoto-t/items/fc6ef3f5bf1dbe5dc579 Laravel 6でユーザー登録機能・ログイン機能を実装する https://www.no-title.com/programming/laravel/authentication ■CSSとJavaScriptをコンパイルしない代わりにBootstrapを導入 https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css resources/views/layouts/app.blade.php
<title>{{ config('app.name', 'Laravel') }}</title> <!-- Scripts --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet"> <!-- Styles --> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
■Userモデルの配置場所を変更 app/User.php を app/Models/User.php に変更し、ファイル内の以下を調整
namespace App; ↓ namespace App\Models;
それに伴い、以下も調整 config/auth.php
'model' => App\User::class, ↓ 'model' => App\Models\User::class,
app/Http/Controllers/Auth/RegisterController.php
use App\User; ↓ use App\Models\User;
■メールの送信 「MAIL_DRIVER=sendmail」での対応だと、ローカルではメール送信にかなりタイムラグがある? いったんGmailのSMTPで送信してみる .env
MAIL_DRIVER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=465 MAIL_USERNAME=xxxxx@gmail.com MAIL_PASSWORD=xxxxx MAIL_ENCRYPTION=ssl
パスワードリセット機能でメール送信を試す メールで以下のようなリンクが送られてきて、ここからリセットできる http://laravel6.local/password/reset/dc56b315b5cd842e1ae6b888897bf62e8739902d35186fd02d542f942dd6fc0... ■パスワードリセット メール本文の変更は以下が参考になりそう Laravel6.xでパスワードリセットメールをカスタマイズする - Qiita https://qiita.com/daijin/items/8bc658c9b14cdd15260c 通知クラスを作成 $ php artisan make:notification ResetPasswordNotification 以下にパスワードリセットの実際のクラスがあるので、これを参考に上記クラスを調整する vendor/laravel/framework/src/Illuminate/Auth/Notifications/ResetPassword.php 完成した ResetPassword.php は以下のとおり。ここではメールの件名のみカスタマイズしている(実際は変数化してconfigなどで管理するといい) なお、「['text' => 'emails.password_reset']」部分を「'emails.password_reset'」にするとHTMLメールとして送信される
<?php namespace App\Notifications; use Illuminate\Auth\Notifications\ResetPassword; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Lang; class ResetPasswordNotification extends ResetPassword { use Queueable; /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $this->token); } return (new MailMessage) /* ->subject(Lang::get('Reset Password Notification')) ->line(Lang::get('You are receiving this email because we received a password reset request for your account.')) ->action(Lang::get('Reset Password'), url(config('app.url').route('password.reset', ['token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset()], false))) ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')])) ->line(Lang::get('If you did not request a password reset, no further action is required.')); */ ->subject('パスワードリセット通知') ->view(['text' => 'emails.password_reset'], [ 'reset_url' => url(config('app.url').route('password.reset', ['token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset()], false)) ]); } }
メール本文は resources/views/emails/password_reset.blade.php に作成する 文字列に「&」が入るとエスケープされるため、URLをテキストで表示する場合は「!!」を使っておくと無難(この機能に限れば「&」は入らないので問題無いが)
パスワードリセット通知 {{!! $reset_url !!}}
app/Models/User.php に sendPasswordResetNotification メソッドを追加する このメソッドの実態は vendor/laravel/framework/src/Illuminate/Auth/Passwords/CanResetPassword.php にある CanResetPassword クラスは vendor/laravel/framework/src/Illuminate/Foundation/Auth/User.php 経由で呼ばれている 使用するクラスは、上で作成した ResetPasswordNotification にする
use App\Notifications\ResetPasswordNotification; /** * Send the password reset notification. * * @param string $token * @return void */ public function sendPasswordResetNotification($token) { $this->notify(new ResetPasswordNotification($token)); }
パスワードリセットを行い、「パスワードリセット通知」という件名で通知が来ることを確認する 本文も上で指定したものになっていることを確認する ★以下引き続き検証する C:\Users\Yamano\Dropbox\技術\Laravel.txt の「Homesteadにサブドメインと作業ディレクトリを追加」と https://github.com/refirio/laravel-blog/commits/master を参考に進める ■マイページと編集機能を実装 routes/web.php にルーティングを追加
// 認証後のコンテンツ Route::group(['middleware' => 'auth'], function () { // マイページ Route::group(['as' => 'mypage'], function () { // マイページ Route::get('/mypage', 'MypageController@index')->name('.index'); // 基本情報編集画面 Route::get('/mypage/basis', 'MypageController@basis')->name('.basis'); // 基本情報編集 Route::post('/mypage/basis_update', 'MypageController@basisUpdate')->name('.basis.update'); }); });
app/Http/Controllers/Auth/LoginController.php app/Http/Controllers/Auth/RegisterController.php app/Http/Controllers/Auth/ResetPasswordController.php app/Http/Controllers/Auth/VerificationController.php を編集
protected $redirectTo = '/home'; ↓ protected $redirectTo = '/mypage';
app/Http/Middleware/RedirectIfAuthenticated.php を編集
return redirect('/home'); ↓ return redirect('/mypage');
resources/lang/ja/validation.php を編集
'attributes' => [], ↓ 'attributes' => [ 'name' => '名前', 'email' => 'メールアドレス', 'password' => 'パスワード', ],
app/Http/Controllers/MypageController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Hash; use App\Http\Controllers\Controller; use App\Models\User; class MypageController extends Controller { /** * インスタンス作成 * * @return void */ public function __construct() { } /** * マイページ * * @param Request $request * @return \Illuminate\Contracts\Support\Renderable */ public function index(Request $request) { return view('mypage/index'); } /** * 基本情報編集画面 * * @param Request $request * @return \Illuminate\Contracts\Support\Renderable */ public function basis(Request $request) { // ユーザー情報取得 $user = Auth::guard()->user(); return view('mypage/basis', [ 'user' => $user, ]); } /** * 基本情報編集 * * @param Request $request * @return \Illuminate\Http\RedirectResponse */ public function basisUpdate (Request $request) { // 入力内容をチェック $validator = Validator::make($request->all(), [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255'], 'password' => ['nullable', 'string', 'min:8', 'confirmed'], ]); if ($validator->fails()) { return redirect('mypage/basis')->withErrors($validator)->withInput(); } // 編集 $userId = Auth::guard()->user()->id; $user = User::find($userId);; $user->name = $request->name; $user->email = $request->email; if (!empty($request->password)) { $user->password = Hash::make($request->password); } $user->save(); return redirect('mypage/basis')->with('message', '基本情報を編集しました。');; } }
resources/views/mypage/index.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">マイページ</div> <div class="card-body"> <ul> <li><a href="{{ route('mypage.basis') }}">基本情報編集</a></li> <li><a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">ログアウト</a></li> </ul> </div> </div> </div> </div> </div> @endsection
resources/views/mypage/basis.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">基本情報編集</div> <div class="card-body"> <form method="POST" action="{{ route('mypage.basis.update') }}"> @csrf @if (session('message')) <div class="box"> <div class="alert alert-success"> {{ session('message') }} </div> </div> @endif <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 @error('name') is-invalid @enderror" name="name" value="{{ old('name', $user->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">{{ __('E-Mail Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email', $user->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">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" 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">{{ __('Confirm Password') }}</label> <div class="col-md-6"> <input id="password-confirm" type="password" class="form-control" name="password_confirmation" 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"> {{ __('Register') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
バリデーション 6.x Laravel https://readouble.com/laravel/6.x/ja/validation.html Laravel|【保存版】バリデーションルールのまとめ - わくわくBank https://www.wakuwakubank.com/posts/376-laravel-validation/ Laravel ログイン中、ログイン画面にアクセスした際のリダイレクト先変更 - Qiita https://qiita.com/Ioan/items/551d379fe99ffcbd06b4 ■マルチ認証 database/migrations/2020_04_08_000000_create_admins_table.php
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateAdminsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('admins', function (Blueprint $table) { $table->engine = 'InnoDB'; $table->bigIncrements('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->timestamps(); }); DB::statement('ALTER TABLE admins COMMENT \'管理者\''); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('admins'); } }
database/seeds/AdminsTableSeeder.php
<?php use Illuminate\Database\Seeder; class AdminsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { if (DB::table('admins')->count() > 0) { return; } DB::table('admins')->insert([ 'name' => 'admin', 'email' => 'admin@example.com', 'password' => Hash::make('abcd1234'), 'remember_token' => Str::random(10), ]); } }
database/seeds/DatabaseSeeder.php
// $this->call(UsersTableSeeder::class); ↓ $this->call(AdminsTableSeeder::class);
マイグレーションとシーダーを実行 Seederを追加した直後に「php artisan db:seed」を実行すると、AdminsTableSeederクラスが見つからないとなった 「composer dump-autoload」を実行すれば解決した $ composer dump-autoload $ php artisan migrate $ php artisan db:seed main/app/Models/Admin.php
<?php namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class Admin extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * 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', ]; }
config/auth.php にある guards の設定に以下を追加
'admin' => [ 'driver' => 'session', 'provider' => 'admins', ],
同ファイルにある providers の設定に以下を追加
'admins' => [ 'driver' => 'eloquent', 'model' => App\Models\Admin::class, ],
同ファイルにある passwords の設定に以下を追加
'admins' => [ 'provider' => 'admins', 'table' => 'password_resets', 'expire' => 60, ],
app/Http/Middleware/Authenticate.php に admin 用の分岐を追加
use Illuminate\Support\Facades\Route; if (! $request->expectsJson()) { if (Route::is('admin.*')) { return route('admin.login'); } else { return route('login'); } }
app/Http/Middleware/RedirectIfAuthenticated.php に admin 用の分岐を追加
if (Auth::guard($guard)->check() && $guard === 'user') { return redirect('/mypage'); } elseif (Auth::guard($guard)->check() && $guard === 'admin') { return redirect('/admin/home'); }
routes/web.php に admin 用のルーティングを追加
// 管理者 Route::namespace('Admin')->prefix('admin')->name('admin.')->group(function () { // ログイン認証関連 Auth::routes([ 'register' => false, 'reset' => false, 'verify' => false ]); // 認証後のコンテンツ Route::middleware('auth:admin')->group(function () { // ダッシュボード Route::get('/home', 'HomeController@index')->name('.home'); }); });
app/Http/Controllers/Admin/HomeController.php
<?php namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use Illuminate\Http\Request; class HomeController extends Controller { public function __construct() { $this->middleware('auth:admin'); } public function index() { return view('admin.home'); } }
app/Http/Controllers/Admin/Auth/LoginController.php
<?php namespace App\Http\Controllers\Admin\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { use AuthenticatesUsers; protected $redirectTo = '/admin/home'; public function __construct() { $this->middleware('guest:admin')->except('logout'); } protected function guard() { return Auth::guard('admin'); } public function showLoginForm() { return view('admin.auth.login'); } public function logout(Request $request) { Auth::guard('admin')->logout(); return $this->loggedOut($request); } public function loggedOut(Request $request) { return redirect(route('admin.login')); } }
resources/views/layouts/admin.blade.php
<!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <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="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet"> <!-- Styles --> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"> </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="{{ 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 --> @guest <li class="nav-item"> <a class="nav-link" href="{{ route('admin.login') }}">{{ __('Login') }}</a> </li> @else <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> {{ Auth::user()->name }} <span class="caret"></span> </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{{ route('admin.logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} </a> <form id="logout-form" action="{{ route('admin.logout') }}" method="POST" style="display: none;"> @csrf </form> </div> </li> @endguest </ul> </div> </div> </nav> <main class="py-4"> @yield('content') </main> </div> </body> </html>
resources/views/admin/auth/login.blade.php
@extends('layouts.admin') @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('admin.login') }}"> @csrf <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 @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">{{ __('Password') }}</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"> {{ __('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> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
resources/views/admin/home.blade.php
@extends('layouts.admin') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">管理者用ページ</div> <div class="card-body"> <ul> <li><a href="{{ route('admin.logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">ログアウト</a></li> </ul> </div> </div> </div> </div> </div> @endsection
Laravel6でマルチ認証を実装する(UserとAdminの階層を分ける) - Qiita https://qiita.com/namizatop/items/5d56d96d4c255a0e3a87 Laravelマルチ認証でセッション用テーブル、設定を分ける(Laravel6で確認済み) - Qiita https://qiita.com/lixwork/items/11f7463d6cf35cb46553 Laravel6.7でマルチログインをできる限り自分好みに実装したはなし - Qiita https://qiita.com/wasipo/items/b06be610bb7ba95954df Laravel6x マルチ認証(userとadmin)の実装でハマった事|Makoto|note https://note.com/makoto0419/n/n9d0e1c1dc90d ■バリデーションをリクエストに移行 ※リクエスト用のクラスを作って、そちらでバリデーションチェックを行うべきか 上の対応は、同じキー名で別の名前を指定したりが難しい? 要検証 ■更新する場合 SSHで接続して以下を実行 $ sudo su -s /bin/bash - nginx $ cd /var/www/main $ composer install $ php artisan migrate $ php artisan db:seed $ php artisan config:clear $ php artisan view:clear
■保留
■ユーザ登録時に確認画面を追加 ※検証中。登録の瞬間に重複などでエラーが発生した場合、正しくエラー表示できない? 処理の流れを変える場合、デフォルトの登録機能は使わずに一から作成するほうが無難か 要検証 routes/web.php に以下を追加
Route::get('register_confirm', 'Auth\RegisterController@register_confirm')->name('register_confirm');
resources/views/auth/register.blade.php で以下を変更
<form method="POST" action="{{ route('register') }}"> ↓ <form method="POST" action="{{ route('register_confirm') }}">
app/Http/Controllers/Auth/RegisterController.php に以下を追加
use Illuminate\Http\Request; /** * 確認画面 * * @param Request $request * @return \Illuminate\Contracts\Support\Renderable */ protected function register_confirm(Request $request) { $this->validator($request->all())->validate(); $user = new User($request->all()); return view('auth.register_confirm', [ 'user' => $user, ]); }
resources/views/auth/register_confirm.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 <input type="hidden" name="name" value="{{ old('name', $user->name ?? '') }}"> <input type="hidden" name="email" value="{{ old('email', $user->email ?? '') }}"> <input type="hidden" name="password" value="{{ old('password', $user->password ?? '') }}"> <input type="hidden" name="password_confirmation" value="{{ old('password', $user->password ?? '') }}"> <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"> {{ old('name', $user->name ?? '') }} @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">{{ __('E-Mail Address') }}</label> <div class="col-md-6"> {{ old('email', $user->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">{{ __('Password') }}</label> <div class="col-md-6"> {{ old('password', $user->password ?? '') }} @error('password') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </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
■トラブル
■Laravelインストール時に「GitHub API limit (0 calls/hr) is exhausted」と表示される composerでGitHub apiのアクセス制限対処法 - Qiita https://qiita.com/ma_me/items/7d1823c27d6ef45cdf9f $ curl -u 'refirio' -d '{"scopes":["repo"],"note":"Help example"}' https://api.github.com/authorizations $ Enter host password for user 'refirio': { "message": "Bad credentials", "documentation_url": "https://developer.github.com/v3" } -bash-4.2$ Enter host password for user 'refirio': { "id": 401877446, "url": "https://api.github.com/authorizations/401877446", "app": { "name": "Help example", "url": "https://developer.github.com/v3/oauth_authorizations/", "client_id": "00000000000000000000" }, "token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "hashed_token": "8175101dd3d26e7217010770ef6df4a35d9681c10572b46cd51cb29137937e96", "token_last_eight": "27a14caf", "note": "Help example", "note_url": null, "created_at": "2020-03-26T01:58:26Z", "updated_at": "2020-03-26T01:58:26Z", "scopes": [ "repo" ], "fingerprint": null } $ composer config -g github-oauth.github.com XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX $ composer create-project --prefer-dist "laravel/laravel=6.0.*" main ■CSSやJavaScriptを作成(解決できず) 実行すると以下が表示されるので、それぞれインストールする Please run "npm install && npm run dev" to compile your fresh scaffolding. $ npm install でインストールすると以下のエラーになる EPROTO: protocol error, symlink '../@babel/parser/bin/babel-parser.js' -> '/var/www/main/node_modules/.bin/parser' $ npm install --no-bin-links でインストールすると通った $ npm run dev で実行すると以下のエラーになる sh: cross-env: コマンドが見つかりません C:\vagrant\laravel6\code\main\package.json にある「cross-env」をすべて「cross-env」に置換して再度実行する node.js が無い場合、あらかじめ以下でインストールしておく インストールしたユーザが使えるようになるようなので、nginxユーザのままで作業する $ cd $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash $ . ~/.nvm/nvm.sh $ nvm install stable $ node -v v13.11.0 AWSのEC2インスタンスにNode.jsを入れる - Qiita https://qiita.com/knxrvb/items/1edcf2bab47f4b238ea2 Windows環境でnpm installでエラーが発生する場合の対処法 - Qiita https://qiita.com/sansaisoba/items/0fd5c77c9fbbfe61a629 MACにLaravel6をインストール | アールエフェクト https://reffect.co.jp/laravel/install-laravel6-in-mac Vue環境作る時のnpmで出るエラーの対処 覚書 | だいぢんのアイドル日記ブログ https://ameblo.jp/minister0926/entry-12463135199.html laravelでnpm run devを実行すると「cross-env: not found」というエラーが出る件対応したった - Qiita https://qiita.com/Yorinton/items/fd9dae33c6748abcdfbc 以下にyumでのインストール手順がある 基本的にこの方がいいかも?でも複数バージョンの切り替えを考えるなら上の手順?要確認 CentOS 7 Node.js のインストール手順 (yum を利用) - Qiita https://qiita.com/daskepon/items/16a77868d38f8e585840