- 投稿日:2019-02-27T20:26:39+09:00
MVC 概要
そもそもMVCとは?
MVCは
Model
、View
、Controller
の頭文字をとったもの。
大まかに言うとこれら3役がそれぞれ役割を担っていて、アプリケーションを作っていく上での考え方や概念といった基盤になる。
ここにデータベースやルーティングが絡んできて、アプリケーションの動きによってサイクルができる。なぜMVCを考えなければいけない?
アプリケーションが簡単なうちはどこがどうなっているのかは把握できるかもしれないが、どんどん複雑になっていく上でその管理が難しくなってくる。
そこでMVCという考え方を持っていればそれぞれが役割を担っているためどこに何があるか把握ができ、状態の管理がしやすくなる。Model
既存のデータベースをいじれるメソッドを色々持っている。ビジネスロジックと呼ばれるかも。
ここで書くコードとして、データベース上のどのカラムをいじれるかの設定や、データベースのテーブル同士でリレーションをつけたりする。モデル名.php//いじれるカラム名を指定する、$fillableではなく$guardedを使っていじれないカラムを指定する方法もある。 protected $fillable = [ 'column1', 'column2', ]; //このモデルに付随するテーブルの1要素が、 //Exampleモデルに付随するテーブルの複数要素と関係性をもつことを表している。 //他にも$this->belongsToにしてこのテーブルは指定したテーブルの1要素と関係性をもつことを表すこともできる。 public function examples() { return $this->hasMany('\App\Example'); }Controller
Model
とView
の間に立つものと考える。
ここではモデルをuse
してモデルのメソッドを使ってデータベースから取得したデータをView
に渡したり、View
から入力された値に対してバリデーションをつけたりすることができる。
また、モデルのメソッドを使って新たにデータベースのテーブルに値を追加することもできる。コントローラ名.phpuse App\Example; //Exampleモデルに付随するテーブルから、作られた時期の降順で取得し、 //view関数を使ってpages.indexファイルに取得したデータを連想配列で渡す。 public function index() { $examples = Example::orderBy('created_at', 'desc')->get(); return view('pages.index', ['examples' => $examples]); } //フォームからの入力を新たにデータベースに追加する関数 public function store(Request $request) { //$rulesでバリデーションを指定している。 //'required'は必須項目で、'email'はメール形式を指定してvalidate関数を使う。 $rules = [ 'example1' => ['required'], 'example2' => ['requierd', 'email'], ]; $this->validate($request, $rules); //モデルのcreateメソッドを使ってデータベースに追加する。 Example::create([ 'example1' => $request['example1'], 'example2' => $request['example2'], ]); //トップページに遷移する return redirect('/'); }View
Controller
から受け取ったデータを画面に表示する。ビュー名.blade.php//foreachを使ってコントローラで取得したデータのタイトルを表す。 <div> @foreach($examples as $example) <div> {{ $example->$title }} </div> @endforeach </div>まとめ
MVC
について簡単にまとめました。
Laravelをもっと深く理解したいです。。
- 投稿日:2019-02-27T19:45:52+09:00
macにPHPとapacheをbrewから入れてみた
大変すぎた。元々入ってるphpとapacheが邪魔しまくってきたのでログを取っておく
CakePHPで作ったプロジェクトが動くところはまでは行くかと思います。何はともあれ、まずhomebrewの最新化
$ brew update
PHPインストール
PHPの検索
$ brew search php
php7.1(お好きなバージョン)をインストール
$ brew install php@7.1
インストールしたPHPを使うように設定変更
$ brew link php@7.1
上記で出てきた以下のコマンドを実行する
$ echo 'export PATH="/usr/local/opt/php@7.1/bin:$PATH"' >> ~/.bash_profile
$ echo 'export PATH="/usr/local/opt/php@7.1/sbin:$PATH"' >> ~/.bash_profile
設定変わったか確認
$ which php
/usr/local/opt/php@7.1/bin/php
apacheをインスール
元から入ってるapacheの自動起動を止める
$ sudo apacehctl stop
$ sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist
apacheを検索
$ brew search httpd
apacheをインストール
$ brew install httpd
設定変更
$ vi /usr/local/etc/httpd/httpd.conf
コメントを外す
#LoadModule userdir_module lib/httpd/modules/mod_userdir.so
#Include /usr/local/etc/httpd/extra/httpd-userdir.conf
#LoadModule rewrite_module modules/mod_rewrite.so
LoadModuleしてる辺りに追記
LoadModule php7_module /usr/local/opt/php@7.1/lib/httpd/modules/libphp7.so <IfModule php7_module> AddType application/x-httpd-php .php </IfModule>書き換え
#ServerName www.example.com:8080
↓
ServerName localhost
DirectoryIndex index.html
↓
DirectoryIndex index.php index.html
DocumentRoot "/usr/local/var/www" <Directory "/usr/local/var/www">↓
DocumentRoot "作成しているプロジェクトのディレクトリ" <Directory "作成しているプロジェクトのディレクトリ">上で書き換えたの中を変更
AllowOverride None
↓
AllowOverride All
mysqlをインストール
$ brew search mysql
$ brew install mysql@5.6
$ brew link mysql@5.6
$ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile
mysql起動
$ source ~/.bash_profile
$ mysql.server start
mysql.sockの設定
$ mysqladmin version
UNIX socket っという項目の後に書いてあるmysqld.sockファイルの場所を記録
/usr/local/etc/php/7.1/php.iniに記述する
pdo_mysql.default_socket=[sockファイル]
$ apacehctl start
$ mysql.server start
- 投稿日:2019-02-27T19:12:13+09:00
WordPressで管理バー(wp_admin_bar)で項目別に非表示する方法
WordPressの管理画面の上部に表示される、wp_admin_barですが、管理者で表示されるの良いんですが、実際つかうエンドユーザー(投稿や編集者権限)に表示されるのは、なんとなく嫌なので、いつも非表示にしています。
で、いつも非表示にするときググるのでいい加減メモを残そうと思い、本投稿をします。
早速ですが、サンプルソースを。
サンプルソース
functions.phpに以下を記載する。
/** * wp管理バーの削除します。 */ function my_remove_adminbar_menu( $wp_admin_bar ) { $wp_admin_bar->remove_menu( 'wp-logo' ); // WPロゴ $wp_admin_bar->remove_menu( 'site-name' ); // サイト名 $wp_admin_bar->remove_menu( 'view-site' ); // サイト名 -> サイトを表示 $wp_admin_bar->remove_menu( 'dashboard' ); // サイト名 -> ダッシュボード (公開側) $wp_admin_bar->remove_menu( 'themes' ); // サイト名 -> テーマ (公開側) $wp_admin_bar->remove_menu( 'customize' ); // サイト名 -> カスタマイズ (公開側) $wp_admin_bar->remove_menu( 'comments' ); // コメント $wp_admin_bar->remove_menu( 'updates' ); // 更新 $wp_admin_bar->remove_menu( 'view' ); // 投稿を表示 $wp_admin_bar->remove_menu( 'new-content' ); // 新規 $wp_admin_bar->remove_menu( 'new-post' ); // 新規 -> 投稿 $wp_admin_bar->remove_menu( 'new-media' ); // 新規 -> メディア $wp_admin_bar->remove_menu( 'new-link' ); // 新規 -> リンク $wp_admin_bar->remove_menu( 'new-page' ); // 新規 -> 固定ページ $wp_admin_bar->remove_menu( 'new-user' ); // 新規 -> ユーザー $wp_admin_bar->remove_menu( 'my-account' ); // マイアカウント $wp_admin_bar->remove_menu( 'user-info' ); // マイアカウント -> プロフィール $wp_admin_bar->remove_menu( 'edit-profile' ); // マイアカウント -> プロフィール編集 $wp_admin_bar->remove_menu( 'logout' ); // マイアカウント -> ログアウト $wp_admin_bar->remove_menu( 'search' ); // 検索 (公開側) } add_action('admin_bar_menu', 'my_remove_adminbar_menu', 201);サンプルソース(管理者権限を除く)
functions.phpに以下を記載する。
なんとなく、管理者権限(自分ですよね)は、すべて表示された方が気持ちいいです。
/** * wp管理バーの削除します。 */ function my_remove_adminbar_menu( $wp_admin_bar ) { if ( current_user_can( 'administrator' ) ) { return; // リターンさせちゃいましょう } // 以下、省略 } add_action('admin_bar_menu', 'my_remove_adminbar_menu', 201);まとめ
これでコピペでいける。ググる時間短縮です!
参考URL
【WordPress】管理バー(admin bar)のメニュー項目を削除する方法 | よしあかつき
https://yosiakatsuki.net/blog/remove-menu-admin-bar/
- 投稿日:2019-02-27T17:55:23+09:00
【laravel5.7】 Multi Authログイン
laravelの機能、MultiAuthログインの実装メモ。
環境
MacOS 10.14.3
VisualStudio
laravel 5.7やりたいこと
Admin、Userページそれぞれでログイン、ログアウトさせる
準備
1. プロジェクトの作成
terminalcomposer create-project laravel/laravel multiauth_test
2. DBの作成
3. .envを編集.envDB_DATABASE=作ったDB名 DB_USERNAME=ユーザ名 DB_PASSWORD=パスワード
User認証
認証機能のインストール
terminalphp artisan make:auth
テーブル作成
terminalphp artisan migrate
usersはデフォルトでファイルが用意されているので、これだけでOK
auth.php
config/auth.php'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', 'hash' => false, ], + 'user' => [ + 'driver' => 'session', + 'provider' => 'users', + ], ],
Handler.php
認証エラーだった時の処理をカスタマイズ。
オーバーライドで書き込みます。app/Exceptions/Handler.php<?php namespace App\Exceptions; use Exception; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Request; +use Response; +use Illuminate\Auth\AuthenticationException; 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 (in_array('user', $exception->guards())) { + return redirect()->guest('user/login'); + } + return redirect()->guest(route('login')); + } }Controllerの作成
make:authで生成されたものをコピーして利用。
直下のAuthフォルダ+Controller.php+HomeController.phpをコピーします。app/Http/Controllers/Userディレクトリを作りペースト。
app/Http/ControllersControllers ├── Auth │ ├── ForgotPasswordController.php │ ├── LoginController.php │ ├── RegisterController.php │ ├── ResetPasswordController.php │ └── VerificationController.php ├── Controller.php ├── HomeController.php └── User ├── Auth │ ├── ForgotPasswordController.php │ ├── LoginController.php │ ├── RegisterController.php │ ├── ResetPasswordController.php │ └── VerificationController.php ├── Controller.php └── HomeController.phpこんな階層になってればOK
Controller/Usersの編集
HomeController.php
app/Http/Controllers/User/HomeController.php<?php +namespace App\Http\Controllers\User; use Illuminate\Http\Request; +use App\User; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('auth:user'); } /** * Show the application dashboard. * * @return \Illuminate\Contracts\Support\Renderable */ public function index() { + return view('user.home'); } }Controller.php
app/Http/Controllers/User/Controller.php<?php +namespace App\Http\Controllers\User; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; }
LoginController.php
app/Http/Controllers/User/Auth/LoginController.php<?php +namespace App\Http\Controllers\User\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; +use Illuminate\Http\Request; 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 = '/user/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:user')->except('logout'); } + public function showLoginForm() + { + return view('user.auth.login'); + } + public function guard() + { + return \Auth::guard('user'); + } + public function logout(Request $request) + { + $this->guard('user')->logout(); + return redirect('/'); + } }RegisterController.php
app/Http/Controllers/User/Auth/RegisterController.php<?php +namespace App\Http\Controllers\User\Auth; use App\User; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Http\Request; 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 = '/user/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:user'); } + public function showRegisterForm() + { + return view('user.auth.register'); + } /** * 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'], ]); } /** * 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']), ]); } + protected function guard() + { + return \Auth::guard('user'); + } }Viewsの編集
viewsはmake:authをしてるので、下記のような改装になっていると思います。
├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ ├── register.blade.php │ └── verify.blade.php ├── home.blade.php ├── layouts │ └── app.blade.php └── welcome.blade.phpControllerの時と同じように、user専用のviewsを作成します。
以下のディレクトリを作成。recources/views/layouts/user/app.blade.php
→layouts/app.blade.phpをコピペ
resources/views/user
→views直下のauthフォルダ+home.blade.phpをコピペ下記のような階層になるかと思います。 ├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ ├── register.blade.php │ └── verify.blade.php ├── home.blade.php ├── layouts │ ├── app.blade.php │ └── user │ └── app.blade.php ├── user │ ├── auth │ │ ├── login.blade.php │ │ ├── passwords │ │ │ ├── email.blade.php │ │ │ └── reset.blade.php │ │ ├── register.blade.php │ │ └── verify.blade.php │ └── home.blade.php └── welcome.blade.phpapp.blade.php
resources/views/layouts/user/app.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="{{ asset('js/app.js') }}" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" 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 --> @guest <li class="nav-item"> + <a class="nav-link" href="{{ route('user.login') }}">{{ __('Login') }}</a> </li> @if (Route::has('register')) <li class="nav-item"> + <a class="nav-link" href="{{ route('user.register') }}">{{ __('Register') }}</a> </li> @endif @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('user.logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} </a> + <form id="logout-form" action="{{ route('user.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>login.blade.php
resources/views/layouts/user/login.blade.php+@extends('layouts.user.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('user.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{{ $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> @if (Route::has('password.request')) + <a class="btn btn-link" href="{{ route('user.password.request') }}"> {{ __('Forgot Your Password?') }} </a> @endif </div> </div> </form> </div> </div> </div> </div> </div> @endsectionルーティングの設定
/user以下で画面が表示されるように設定します。
ひとまず、最低限のページルートのみ設定。
他のページも利用するときはその都度同じように設定すればOK。routes/web.php<?php +use Illuminate\Http\Request; Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); +// User +Route::group(['namespace' => 'User','prefix'=>'user'],function(){ + Route::get('/',function(){ + return redirect()->to('user/home'); + })->name('user'); + // home + Route::get('home','HomeController@index')->name('user.home'); + // login lgoout + Route::get('login','Auth\LoginController@showLoginForm')->name('user.login'); + Route::post('login','Auth\LoginController@login')->name('user.login'); + Route::post('logout','Auth\LoginController@logout')->name('user.logout'); + // register + Route::get('register','Auth\RegisterController@showRegisterForm')->name('user.register'); + Route::post('register','Auth\RegisterController@register')->name('user.register');Admin認証
adminはuserの手順とほぼ同じです。
テーブル・モデルの作成
terminalphp artisan make:model Admin -m
下記のテーブルとモデルができたかと思います。
app/Admin.php
database/201x_xx_xx_xxxxxx_create_admins_table.phpテーブル編集
userテーブルと同じ内容にします。
create_admins_table.phppublic function up() { Schema::create('admins', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); }Admin.php
これもUser.phpとほぼ同じで、Authenticatableを継承
Admin.php<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Model; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class Admin extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password','api_token' ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; }auth.php
config/auth.php<?php return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], 'user' => [ 'driver' => 'session', 'provider' => 'users', ], + 'admin' => [ + 'driver' => 'session', + 'provider' => 'admins' + ] ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], + 'admins' => [ + 'driver' => 'eloquent', + 'model' => App\Admin::class, + ], ], 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], + 'admins' => [ + 'provider' => 'admins', + 'table' => 'password_resets', + 'expire' => 60, + ], ], ];Handler.php
app/Exceptions/Handler.phpprotected function unauthenticated($request, AuthenticationException $exception) { if($request->expectsJson()){ return response()->json(['error' => 'Unauthenticated.'],401); } if(in_array('user',$exception->guards())){ return redirect()->guest('user/login'); } + if(in_array('admin',$exception->guards())){ + return redirect()->guest('admin/login'); + } return redirect()->back()->withInput(Input::all()); }
Controller
さっき作った”app/Http/Controller/User”フォルダを同じ階層にコピペしてAdminにリネームします。
Controller・Adminの編集
HomeController.php
app/Http/Controllers/Admin/HomeController.php<?php +namespace App\Http\Controllers\Admin; use Illuminate\Http\Request; use App\User; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('auth:admin'); } /** * Show the application dashboard. * * @return \Illuminate\Contracts\Support\Renderable */ public function index() { + return view('admin.home'); } }Controller.php
app/Http/Controllers/Admin/Controller.php<?php +namespace App\Http\Controllers\Admin; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; }
LoginController.php
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; 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 = '/admin/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:admin')->except('logout'); } public function showLoginForm() { + return view('admin.auth.login'); } public function guard() { + return \Auth::guard('admin'); } public function logout(Request $request) { + $this->guard('admin')->logout(); return redirect('/'); } }RegisterController.php
app/Http/Controller/Admin/Auth/RegisterController.php<?php +namespace App\Http\Controllers\Admin\Auth; use App\User; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Http\Request; +use App\Admin; 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 = '/admin/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:admin'); } public function showRegisterForm() { + return view('admin.auth.register'); } /** * 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:admins'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } /** * Create a new user instance after a valid registration. * * @param array $data * @return \App\Admin */ protected function create(array $data) { + return Admin::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } protected function guard() { + return \Auth::guard('admin'); } }Views
Controllerと同様、userで作成したファイルをコピペして、adminにリネームします。
app.blade.php
layouts/admin/app.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="{{ asset('js/app.js') }}" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="https://fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" 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 --> @guest <li class="nav-item"> + <a class="nav-link" href="{{ route('admin.login') }}">{{ __('Login') }}</a> </li> <li class="nav-item"> @if (Route::has('register')) + <a class="nav-link" href="{{ route('admin.register') }}">{{ __('Register') }}</a> @endif </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>login.blade.php
views/admin/login.blade.php+@extends('layouts.admin.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('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{{ $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> @if (Route::has('password.request')) + <a class="btn btn-link" href="{{ route('admin.password.request') }}"> {{ __('Forgot Your Password?') }} </a> @endif </div> </div> </form> </div> </div> </div> </div> </div> @endsectionルーティングの設定
userと同様。
userのルーティングの下に追加します。php/routes/web.php// Admin Route::group(['namespace' => 'Admin','prefix'=>'admin'],function(){ Route::get('/',function(){ return redirect()->to('admin/home'); })->name('admin'); // home Route::get('home','HomeController@index')->name('admin.home'); // login logout Route::get('login','Auth\LoginController@showLoginForm')->name('admin.login'); Route::post('login','Auth\LoginController@login')->name('admin.login'); Route::post('logout','Auth\LoginController@logout')->name('admin.logout'); // register Route::get('register','Auth\RegisterController@showRegisterForm')->name('admin.register'); Route::post('register','Auth\RegisterController@register')->name('admin.register');動作確認
php artisan serveUser
http://127.0.0.1:8000/user/login
Admin
http://127.0.0.1:8000/admin/loginそれぞれで、ログイン・ログアウトできるか確認します。
別々に動作していれば成功です。
- 投稿日:2019-02-27T17:55:23+09:00
laravel5.7 Multi Authログイン
laravelの新機能、MultiAuthログインの実装メモ。
環境
MacOS 10.14.3
VisualStudio
laravel 5.7やりたいこと
Admin、Userページそれぞれでログイン、ログアウトさせる
準備
1. プロジェクトの作成
terminalcomposer create-project laravel/laravel multiauth_test
2. DBの作成
3. .envを編集.envDB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=作ったDB名 DB_USERNAME=ユーザ名 DB_PASSWORD=パスワード
User認証
認証機能のインストール
terminalphp artisan make:auth
テーブル作成
terminalphp artisan migrate
usersはデフォルトでファイルが用意されているので、これだけでOK
auth.php
config/auth.php'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', 'hash' => false, ], + 'user' => [ + 'driver' => 'session', + 'provider' => 'users', + ], ],
Handler.php
認証エラーだった時の処理をカスタマイズ。
オーバーライドで書き込みます。app/Exceptions/Handler.php<?php namespace App\Exceptions; use Exception; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Request; +use Response; +use Illuminate\Auth\AuthenticationException; 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 (in_array('user', $exception->guards())) { + return redirect()->guest('user/login'); + } + return redirect()->guest(route('login')); + } }Controllerの作成
make:authで生成されたものをコピーして利用。
直下のAuthフォルダ+Controller.php+HomeController.phpをコピーします。app/Http/Controllers/Userディレクトリを作りペースト。
app/Http/ControllersControllers ├── Auth │ ├── ForgotPasswordController.php │ ├── LoginController.php │ ├── RegisterController.php │ ├── ResetPasswordController.php │ └── VerificationController.php ├── Controller.php ├── HomeController.php └── User ├── Auth │ ├── ForgotPasswordController.php │ ├── LoginController.php │ ├── RegisterController.php │ ├── ResetPasswordController.php │ └── VerificationController.php ├── Controller.php └── HomeController.phpこんな階層になってればOK
Controller/Usersの編集
HomeController.php
app/Http/Controllers/User/HomeController.php<?php +namespace App\Http\Controllers\User; use Illuminate\Http\Request; +use App\User; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('auth:user'); } /** * Show the application dashboard. * * @return \Illuminate\Contracts\Support\Renderable */ public function index() { + return view('user.home'); } }Controller.php
app/Http/Controllers/User/Controller.php<?php +namespace App\Http\Controllers\User; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; }
LoginController.php
app/Http/Controllers/User/Auth/LoginController.php<?php +namespace App\Http\Controllers\User\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; +use Illuminate\Http\Request; 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 = '/user/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:user')->except('logout'); } + public function showLoginForm() + { + return view('user.auth.login'); + } + public function guard() + { + return \Auth::guard('user'); + } + public function logout(Request $request) + { + $this->guard('user')->logout(); + return redirect('/'); + } }RegisterController.php
app/Http/Controllers/User/Auth/RegisterController.php<?php +namespace App\Http\Controllers\User\Auth; use App\User; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Http\Request; 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 = '/user/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:user'); } + public function showRegisterForm() + { + return view('user.auth.register'); + } /** * 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'], ]); } /** * 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']), ]); } + protected function guard() + { + return \Auth::guard('user'); + } }Viewsの編集
viewsはmake:authをしてるので、下記のような改装になっていると思います。
├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ ├── register.blade.php │ └── verify.blade.php ├── home.blade.php ├── layouts │ └── app.blade.php └── welcome.blade.phpControllerの時と同じように、user専用のviewsを作成します。
以下のディレクトリを作成。recources/views/layouts/user/app.blade.php
→layouts/app.blade.phpをコピペ
resources/views/user
→views直下のauthフォルダ+home.blade.phpをコピペ下記のような階層になるかと思います。 ├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ ├── register.blade.php │ └── verify.blade.php ├── home.blade.php ├── layouts │ ├── app.blade.php │ └── user │ └── app.blade.php ├── user │ ├── auth │ │ ├── login.blade.php │ │ ├── passwords │ │ │ ├── email.blade.php │ │ │ └── reset.blade.php │ │ ├── register.blade.php │ │ └── verify.blade.php │ └── home.blade.php └── welcome.blade.phpapp.blade.php
resources/views/layouts/user/app.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="{{ asset('js/app.js') }}" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" 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 --> @guest <li class="nav-item"> + <a class="nav-link" href="{{ route('user.login') }}">{{ __('Login') }}</a> </li> @if (Route::has('register')) <li class="nav-item"> + <a class="nav-link" href="{{ route('user.register') }}">{{ __('Register') }}</a> </li> @endif @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('user.logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} </a> + <form id="logout-form" action="{{ route('user.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>login.blade.php
resources/views/layouts/user/login.blade.php+@extends('layouts.user.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('user.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{{ $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> @if (Route::has('password.request')) + <a class="btn btn-link" href="{{ route('user.password.request') }}"> {{ __('Forgot Your Password?') }} </a> @endif </div> </div> </form> </div> </div> </div> </div> </div> @endsectionルーティングの設定
/user以下で画面が表示されるように設定します。
routes/web.php<?php +use Illuminate\Http\Request; Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); +// User +Route::group(['namespace' => 'User','prefix'=>'user'],function(){ + Route::get('/',function(){ + return redirect()->to('user/home'); + })->name('user'); + // home + Route::get('home','HomeController@index')->name('user.home'); + // login lgoout + Route::get('login','Auth\LoginController@showLoginForm')->name('user.login'); + Route::post('login','Auth\LoginController@login')->name('user.login'); + Route::post('logout','Auth\LoginController@logout')->name('user.logout'); + // register + Route::get('register','Auth\RegisterController@showRegisterForm')->name('user.register'); + Route::post('register','Auth\RegisterController@register')->name('user.register');Admin認証
adminはuserの手順とほぼ同じです。
テーブル・モデルの作成
terminalphp artisan make:model Admin -m
下記のテーブルとモデルができたかと思います。
app/Admin.php
database/201x_xx_xx_xxxxxx_create_admins_table.phpテーブル編集
userテーブルと同じ内容にします。
create_admins_table.phppublic function up() { Schema::create('admins', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); }Admin.php
これもUser.phpとほぼ同じで、Authenticatableを継承
Admin.php<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Model; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class Admin extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password','api_token' ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; }auth.php
config/auth.php<?php return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], 'user' => [ 'driver' => 'session', 'provider' => 'users', ], + 'admin' => [ + 'driver' => 'session', + 'provider' => 'admins' + ] ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], + 'admins' => [ + 'driver' => 'eloquent', + 'model' => App\Admin::class, + ], ], 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], + 'admins' => [ + 'provider' => 'admins', + 'table' => 'password_resets', + 'expire' => 60, + ], ], ];Handler.php
app/Exceptions/Handler.phpprotected function unauthenticated($request, AuthenticationException $exception) { if($request->expectsJson()){ return response()->json(['error' => 'Unauthenticated.'],401); } if(in_array('user',$exception->guards())){ return redirect()->guest('user/login'); } + if(in_array('admin',$exception->guards())){ + return redirect()->guest('admin/login'); + } return redirect()->back()->withInput(Input::all()); }
Controller
さっき作った”app/Http/Controller/User”フォルダを同じ階層にコピペしてAdminにリネームします。
Controller・Adminの編集
HomeController.php
app/Http/Controllers/Admin/HomeController.php<?php +namespace App\Http\Controllers\Admin; use Illuminate\Http\Request; use App\User; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('auth:admin'); } /** * Show the application dashboard. * * @return \Illuminate\Contracts\Support\Renderable */ public function index() { + return view('admin.home'); } }Controller.php
app/Http/Controllers/Admin/Controller.php<?php +namespace App\Http\Controllers\Admin; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; }
LoginController.php
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; 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 = '/admin/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:admin')->except('logout'); } public function showLoginForm() { + return view('admin.auth.login'); } public function guard() { + return \Auth::guard('admin'); } public function logout(Request $request) { + $this->guard('admin')->logout(); return redirect('/'); } }RegisterController.php
app/Http/Controller/Admin/Auth/RegisterController.php<?php +namespace App\Http\Controllers\Admin\Auth; use App\User; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Http\Request; +use App\Admin; 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 = '/admin/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { + $this->middleware('guest:admin'); } public function showRegisterForm() { + return view('admin.auth.register'); } /** * 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:admins'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } /** * Create a new user instance after a valid registration. * * @param array $data * @return \App\Admin */ protected function create(array $data) { + return Admin::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } protected function guard() { + return \Auth::guard('admin'); } }Views
Controllerと同様、userで作成したファイルをコピペして、adminにリネームします。
app.blade.php
layouts/admin/app.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="{{ asset('js/app.js') }}" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="https://fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" 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 --> @guest <li class="nav-item"> + <a class="nav-link" href="{{ route('admin.login') }}">{{ __('Login') }}</a> </li> <li class="nav-item"> @if (Route::has('register')) + <a class="nav-link" href="{{ route('admin.register') }}">{{ __('Register') }}</a> @endif </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>login.blade.php
views/admin/login.blade.php+@extends('layouts.admin.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('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{{ $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> @if (Route::has('password.request')) + <a class="btn btn-link" href="{{ route('admin.password.request') }}"> {{ __('Forgot Your Password?') }} </a> @endif </div> </div> </form> </div> </div> </div> </div> </div> @endsectionルーティングの設定
userと同様。
userのルーティングの下に追加します。php/routes/web.php// Admin Route::group(['namespace' => 'Admin','prefix'=>'admin'],function(){ Route::get('/',function(){ return redirect()->to('admin/home'); })->name('admin'); // home Route::get('home','HomeController@index')->name('admin.home'); // login logout Route::get('login','Auth\LoginController@showLoginForm')->name('admin.login'); Route::post('login','Auth\LoginController@login')->name('admin.login'); Route::post('logout','Auth\LoginController@logout')->name('admin.logout'); // register Route::get('register','Auth\RegisterController@showRegisterForm')->name('admin.register'); Route::post('register','Auth\RegisterController@register')->name('admin.register');動作確認
php artisan serveUser
http://127.0.0.1:8000/user/login
Admin
http://127.0.0.1:8000/admin/loginそれぞれで、ログイン・ログアウトできるか確認します。
別々に動作していれば成功です。
- 投稿日:2019-02-27T17:29:32+09:00
Laravel インストール
まずは、Composerのインストール
1.windowsの場合
https://getcomposer.org/download/
2.Macの場合
次に、Laravelのインストール
コマンドプロンプトで下記を実行
※インストールまで少し時間がかかります。composer global require "laravel/installer=~1.1"最後に、環境変数passの設定
1.コントロールパネルを開き、『詳細設定』タブの「環境変数」ボタンを押す
2.『システム環境変数』のリスト中から「Path」を探し編集
以下を先頭に追加
※binの後に「;」を加える
※編集ウインドウがリストになっている場合は『新規』ボタンを押し、上記を追加する。以上でインストールは終了です。
誤りなどあればコメントお願いします。
- 投稿日:2019-02-27T16:04:47+09:00
【PHP】count() メモ
PHPの型まわりのメモ
count()
型まわりの注意点まとめ。
$array1 = false; $array2 = 'str'; $array3 = [ 'a', 'b', ]; $array4 = [ ['a'], ['b'], ]; $array5 = null; echo count($array1); // 1 echo count($array2); // 1 echo count($array3); // 2 echo count($array4); // 2 echo count($array5); // 0 echo count((array)$array1); // 1 echo count((array)$array2); // 1
- 投稿日:2019-02-27T14:08:32+09:00
CakePHP3で一つのクエリ結果をネストループさせるときに注意すること
CakePHP3で実装する際に、find()した結果をforeachでネストループさせる時に、
想定外の挙動をしてハマりましたので、tipsとして記録します。背景
Usersテーブルに入っているユーザそれぞれに対して、
そのユーザとその他のユーザの類似度を計算したかった。そのため、Usersテーブルの中身を2重ループするような実装をした。
$users = $this->Users->find()->all(); echo "*START\n"; foreach ($users as $outerUser) { echo "OUTER: {$outerUser->id}\n"; foreach ($users as $innerUser) { echo "INNER: {$innerUser->id}\n"; } } echo "*END\n";問題となる結果
なぜか外側のループが最後まで回らず1回目で終了した。
*START OUTER: 1 INNER: 1 INNER: 2 INNER: 3 INNER: 4 INNER: 5 *END解決策
toArray()
をつかって配列にすることで問題は起きなくなった。
が、ポピュラーで割とやりがちな実装だと思うので要注意だと思いました。$users = $this->Users->find()->toArray();ソース
issueを上げて確認したところ、そういった仕様という認識で良い模様。
https://github.com/cakephp/cakephp/issues/13021
- 投稿日:2019-02-27T13:45:34+09:00
Laravelのマイグレーションではtimestamp型のchangeが出来ない
エラー内容
Laravelのマイグレーションでtimestamp型のカラムに変更を加えようとすると以下のようなエラーが出る。
Unknown column type "timestamp" requested. Any Doctrine type that you use has to be registered with \ Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Ty pes\Type::getTypesMap(). If this error occurs during database introspection then you might have forgo tten to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMap ping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty y ou might have a problem with the cache or forgot some mapping information.理由
Laravel内で利用しているDoctrineというライブラリが対応していないから。ちなみに対応の予定もなさそう。
https://github.com/doctrine/dbal/issues/2558理由としてはtimestamp型はMySQL固有の型だから特定のDBサービス用の型はサポートしないよということ。
ちなみにLaravelのchangeで変更できるカラムの種類は以下に限られている
bigInteger binary boolean date dateTime dateTimeTz decimal integer json longText mediumText smallInteger string text time unsignedBigInteger unsignedInteger unsignedSmallInteger解決策
DBファサードを使って生のSQLを発行する
MySQLのバージョンは5.7.25です。/** * Run the migrations. * * @return void */ public function up() { DB::statement('ALTER TABLE `テーブル名` MODIFY COLUMN `カラム名` TIMESTAMP NULL;'); } /** * Reverse the migrations. * * @return void */ public function down() { DB::statement('ALTER TABLE `テーブル名` MODIFY COLUMN `カラム名` TIMESTAMP NOT NULL;'); }
- 投稿日:2019-02-27T10:44:37+09:00
【Laravel】ModelのFillableの値を取得する
getFillable()を使って取得できる
user.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { protected $fillable = [ 'lastName', 'firstName', 'email', ]; }<?php $user = new User(); dd($user->getFillable());結果
array:4 [ 0 => "lastName" 1 => "firstName" 2 => "email" ]参考
GuardはgetGuarded()で取得できる
- 投稿日:2019-02-27T10:42:10+09:00
Laravel 5.7 パスワードリセットの日本語化
前回、メールアドレスの確認と日本語化したのですが、パスワードリセットでも英文のメールが送られていたので、こちらも日本語化をしたいと思います。
Laravel 5.7 メールアドレスの確認を日本語化も含めて実装する
ユーザー認証は以下のコマンドで実装されているものとします。
php artisan make:authビューの日本語化
まずは、パスワードリセットの画面を日本語化します。
./resources/views/auth ├── passwords │ ├── email.blade.php │ └── reset.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">{{ __('message.password_reset.title') }}</div> <div class="card-body"> @if (session('status')) <div class="alert alert-success" role="alert"> {{ session('status') }} </div> @endif <form method="POST" action="{{ route('password.email') }}"> @csrf <div class="form-group row"> <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('message.user.field.email') }}</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 mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('message.button.send') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection翻訳ファイルも変更します。(./resources/lang/ja/message.php)
<?php return [ // ボタン "button" => [ "send" => ' 送信 ', ], // ユーザ情報 "user" => [ "field" => [ "email" => "メールアドレス", ] ], // パスワードリセット "password_reset" => [ 'title' => 'パスワードリセット' ], ];送信メールの日本語化
まずは、パスワードリセットをしたときにどこでメールを送っているのかを確認します。
UserモデルがAuthenticatable(Illuminate\Foundation\Auth\User)を継承しています。
その中で、CanResetPasswordというtraitを呼び出しています。
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract { use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; }CanResetPasswordの中身を見ると、sendPasswordResetNotificationでメールを送っているので、こちらをカスタマイズしていきます。
trait CanResetPassword { /** * Get the e-mail address where password reset links are sent. * * @return string */ public function getEmailForPasswordReset() { return $this->email; } /** * Send the password reset notification. * * @param string $token * @return void */ public function sendPasswordResetNotification($token) { $this->notify(new ResetPasswordNotification($token)); } }カスタムのNotificationを作成する
artisanを利用して、カスタムのNotificationを作成します。
php artisan make:notification RestPasswordCustom./app/Notifications/にファイルが作成されるので、もともとパスワードリセットで使用されているRestPasswordNotification(Illuminate\Auth\Notifications\ResetPassword)を参考に編集をいたします。
変更箇所はtoMailの中で、英文をセットしている箇所を日本語に置き換えるだけです。
namespace App\Notifications; use Illuminate\Notifications\Notification; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Support\Facades\Lang; class RestPasswordCustom extends Notification { /** * The password reset token. * * @var string */ public $token; /** * The callback that should be used to build the mail message. * * @var \Closure|null */ public static $toMailCallback; /** * Create a notification instance. * * @param string $token * @return void */ public function __construct($token) { $this->token = $token; } /** * Get the notification's channels. * * @param mixed $notifiable * @return array|string */ public function via($notifiable) { return ['mail']; } /** * 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::getFromJson('message.mail.password_reset.title')) ->line(Lang::getFromJson('message.mail.password_reset.line')) ->action(Lang::getFromJson('message.mail.password_reset.action'), url(config('app.url').route('password.reset', $this->token, false))) ->line(Lang::getFromJson('message.mail.password_reset.out_line1', ['count' => config('auth.passwords.users.expire')])) ->line(Lang::getFromJson('message.mail.password_reset.out_line2')); } /** * Set a callback that should be used when building the notification mail message. * * @param \Closure $callback * @return void */ public static function toMailUsing($callback) { static::$toMailCallback = $callback; } }翻訳ファイルは
<?php return [ // メール "mail" => [ // パスワードリセット "password_reset" => [ "title" => "パスワードリセットのお知らせ", "line" => "パスワードリセットの受け付けました。", "action" => "パスワードリセット", "out_line1" => "こちらのパスワードリセットの有効期限は :count 分です。", "out_line2" => "こちらのメールに身に覚えがない場合は、無視をしてください。" ] ], ];以上、パスワードリセットの日本語化は終わりです。
Laravelはtraitを多様していますので、何かあればその中身を調査するようにしています(ーー;
- 投稿日:2019-02-27T10:42:04+09:00
【Laravel】blade Laravel Collective で css クラスを動的に付加する
{{ Form::text('e_mail', null, ['class' => 'mail' . ($errors->has('e_mail') ? ' error':'')]) }}上記のように書くことで、$errors->has('e_mail') が trueの時のみ cssのclass error を付加することができますね
- 投稿日:2019-02-27T10:19:09+09:00
PHP: 関数合成する関数を作る方法【愚直にforeach編】
前回はPHP: 関数合成する関数を作る方法 - Qiitaという投稿をした。そこで紹介した関数合成する関数の実装は次のコードだった。
$composeAll = function (callable $function, callable ...$functions): callable { return array_reduce( $functions, function (callable $f, callable $g): callable { return function (...$arguments) use ($f, $g) { return $g($f(...$arguments)); }; }, $function ); };この関数は、関数の配列をreduceしていってひとつの関数を作る設計になっているが、ものすごく大量の関数を合成することは想定されていない。
試してみると分かるが、2つの関数を合成するたびにメモリが増えていき、memory_limitに達するとFatal Errorが発生する。
$increment = function (int $value): int { return $value + 1; }; // 1,048,576個の関数を合成する $increments1048576 = array_fill(0, 1024 * 1024, $increment); $add1048576 = $composeAll(...$increments1048576); // Fatal Error実行結果:
Terminated due to signal: SEGMENTATION FAULT (11) Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /.../Untitled 3.php on line 11これは、関数合成1回ごとにつなぎの関数のためのメモリが確保されていくから仕方がないところ。イメージとしては、こんなかんじで変数を大量に定義するのと同じ:
$increments1_2 = function (...) { return $increment2($increment1(...)); }; $increments1_2_3 = function (...) { return $increment3($increments1_2(...)); }; $increments1_2_3_4 = function (...) { return $increment4($increments1_2_3(...)); }; $increments1_2_3_4_5 = function (...) { return $increment5($increments1_2_3_4(...)); }; $increments1_2_3_4_5_6 = function (...) { return $increment6($increments1_2_3_4_5(...)); }; ...1048570個くらい略... $increments1_2_3_4_5_6_snip_1048576 = function (...) { return $increment1048576($increments1_2_3_4_5_snip_1048575(...)); };100万個もの関数を合成することはそうそうないので、実際は直面する可能性が低い軽微な問題ではある。
それでも性能上の限界があることは記憶に留めておきたい。そして、限界はメモリだったりと実行時の状況次第で限界点のしきい値が変わるということも。
プログラムの完成度として、できるだけ限界がないようにしておきたいときは、愚直にforeachする方法もある:
$increment = function (int $value): int { return $value + 1; }; $composeAll = function (callable ...$functions): callable { return function ($argument) use ($functions) { foreach ($functions as $function) { $argument = $function($argument); } return $argument; }; }; $increments1048576 = array_fill(0, 1024 * 1024, $increment); $add1048576 = $composeAll(...$increments1048576); echo $add1048576(0); //=> 1048576
- 投稿日:2019-02-27T10:14:56+09:00
PHPでMySQLに接続できない場合の対応
MySQLに接続しようとしたらPDOExceptionが発生した。
PHP Fatal error: Uncaught PDOException: could not find driver in hoge.php:1ドライバが見つからないと言っているので、この場合は
php-mysql
を入れます。sudo apt install php-mysqlおわり
- 投稿日:2019-02-27T09:35:21+09:00
PHPでDOMDocumentがないと言われた場合の対応
下記のようなエラーが出たら
PHP Fatal error: Uncaught Error: Class 'DOMDocument' not found in /hoge.php:8
php-xml
をインストールするsudo apt install php-xmlor
sudo yum install php-xml
- 投稿日:2019-02-27T09:31:55+09:00
php-master-changes 2019-02-26
今日は以前に行ったテスト修正のマージし直し、zend_vm_gen.php のリファクタリングがあった!
2019-02-26
nikic: Fix tests bareword fallback with error suppression
- https://github.com/php/php-src/commit/b4cbf6faca9d44fb569e308e6909497c1da8fadf
- [7.4~]
- 以前に行ったテスト修正のマージし直しっぽいんだけど、パッと見だとなんかよう分からんなこれ
- なんかマージミスとかで消してしまってたのだらうか
beberlei: Make regex replacements in zend_vm_gen.php more obvious
- https://github.com/php/php-src/commit/d303225c3a463cb0a7dabb51234adf684de13fa5
- [7.4~]
- zend_vm_gen.php で、preg_replace() の引数の与え方を変更して何がどう置き換えられるかの対応が分かりやすくなるよう修正
- 対応表から array_keys() と array_values() で引っ張ってくる形に
- 投稿日:2019-02-27T00:15:00+09:00
nginxでlaravelを動かす際にいろいろ詰んだ話
環境
- macOS 10.12.6
- MacBook pro 2016
- VirtualBox 5.2.18
- CentOS 7.6-1810
- PHP 7.0.33
- Laravel Framework 5.5.45
- nginx 1.14.2
前提
nginx, PHP, PHP-FPM(設定済), composer をインストール済み
今回の手順
1.laravelプロジェクトの新規作成
2.nginxの設定ファイルを新規作成
3.nginxの再起動 ←ちょっと詰まった
4.ブラウザ確認 ←結構詰まったlaravelプロジェクトの新規作成
プロジェクトを作りたい場所で、コマンド一発叩きます。
自分は、/home/username/www/
の配下に作りました。# cd ~/www/ # composer create-project --prefer-dist laravel/laravel projectnamenginxの設定ファイルを新規作成
nginxの設定ファイルは
/etc/nginx/conf.d/
配下に作ります。
デフォルトでは、default.conf
がいるので、こいつをコピーして作りましょう。# cd /etc/nginx/conf.d/ # cp default.conf laravel.conf //設定ファイルの名前は好きなように(プロジェクト名にするのが無難かも)設定ファイルは、デフォルトのままでは動きませんので、書き換えます。
自分の場合は、以下のような感じです。laravel.confserver { listen 5000; //ポート番号はお好みで server_name localhost; root /home/username/www/projectname/public/; //先ほどlaravelプロジェクトを作成した場所に設定します。publicに関しては以下で説明 index index.php index.html index.htm; #charset koi8-r; access_log /var/log/nginx/projectname/access.log main; //アクセスログの出力先を指定 error_log /var/log/nginx/projectname/error.log warn;//エラーログの出力先を指定 location / { try_files $uri $uri/ /index.php?$query_string; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; //ここの$document_rootは、ファイルの上の方で設定したrootが代入されています。 fastcgi_max_temp_file_size 0; fastcgi_buffer_size 4K; fastcgi_buffers 64 4k; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }コメントにも記載したが、
root
で指定したものが$document_root
に代入される。
デフォルトでは、location ~ \.php$ {}
内にroot
が宣言されているが、ここでrootを宣言すると、上のroot
を上書きしてしまうみたいなので気を付けましょう。この
root
を、/home/username/www/projectname/public/
としているが、laravelで設定したルーティングを使用するためには、projectname/public/index.php
を最初に見に行かせればいいので、このような設定になっている。nginx用のログディレクトリ作成
今回は、ログの出力場所を
/var/log/nginx/projectname/
配下にしたので、ディレクトリをしっかり作成しておく。# cd /var/log/nginx/ # mkdir projectnameこれでログの置き場所はできた。
ポート開放
あとは、ファイアーウォールの壁に変更したポートの穴を開けてあげなければ外部からのアクセスができないので、ポート開放をしてあげます。
# firewall-cmd --add-port=開けたいポート番号/tcp --zone=public --permanent # firewall-cmd --reload //反映nginxの再起動
まずは、普通に再起動。
# systemctl restart nginx Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.エラーや…と思い、エラーログを確認。
error.log2019/02/24 13:24:50 [error] 4690#4690: *1 "/home/username/www/projectname/public/index.php" is forbidden (13: Permission denied), client: ***.***.***.***, server: localhost, request: "GET / HTTP/1.1", host: "host-name:5000"パーミッション!?と思い
sudo
で実行してもダメ。
詰んだ…と思ったけど、以下の手順で解決できました!SELinuxというクセもの
SELinuxという標準の制御機能があるらしく、そいつの制御に引っかかって弾かれていたみたいです…(そんなの今回のこのエラーだけじゃわからんよ…)
SELinuxの状態は以下で確認できます。# getenforce enforcing・enforcing SELinux有効でありアクセス制御が有効となる
・permissive アクセス制御は無効だが警告メッセージを表示する
・disabled SELinux無効こちらより
なので、今回はSELinuxを
permissive
にしなくてはなりませんね。
変更のやり方はこうです# setenforce 0 //permissiveに変更 # setenforce 1 //enforcingに変更これで、無事にnginxの再起動ができました!(めでたしめでたし。。。ではなかった)
ブラウザ確認
あとは、ブラウザ確認だ!ということで、先ほど設定して開放もしたポートにアクセス。
すると、laravelにアクセスできてはいるものの、laravelからエラーが返ってきました。
こんな感じ↓
エラー内容は以下です。The stream or file "/home/username/www/projectname/storage/logs/laravel.log" could not be opened: failed to open stream: Permission deniedこいつは、
projectname/storage/logs/
を開けないため起きているみたいです。
laravelに最初にアクセスするとき、このprojectname/storage/logs/
配下にlaravel.log
というアプリケーションログファイルを新規で作成しようとするのですが、書き込み権限がないためにエラーが出ているみたいですね。
※ちなみに、最初のアクセス時だけこのエラーが出るので、一回このエラーを解消してしまえば、後にパーミッションを元に戻してもエラーは起こりません。
チャチャっとパーミッションの変更。# cd storage/ # chmod 777 logs //元は775でしたこれで解決だ!!
と思いきやまた別のエラー。。。file_put_contents(/home/username/www/projectname/storage/framework/views/ddedc3f39a1683fbdb7b78fe94e93c581d280345.php): failed to open stream: Permission denied同じく、
projectname/storage/framework/views/
配下がいじれないぞと言われていますね。
同じようにパーミッション変更!# cd storage/framework/ # chmod 777 views //元は775でしたやったぞ!!!アクセス成功!!!
お疲れました…。