LOGv:20171214

Laravel5備忘録

この記事を書いたときの環境
日時18/05/06
PHP7.2.5
Laravel5.6

関連記事

Artisan

Laravelを操作するCLI
クラスの作成やDBマイグレーション、キャッシュの削除などLaravelアプケーションの管理が行える。

$ php artisan list

Service

おそらくLaravelのServiceなんちゃらのServiceとはサービスプログラムのこと。
サービスプログラムとはOSなどに最初から用意されている操作の手助けやシステム運用の為に定期的に実行されるようなプログラムのことでユーティリティと呼ばれることもある。

Service Provider

Providerは供給者、調達者という意味なのでサービスプログラムを供給するクラスという認識で合っていると思う。
Laravelではアプリケーション全体の起動処理のタイミングでService Providerを利用してService Containerでのサービスのバインド(結合)や、Event Listener、filter、Routingの登録など、初期起動処理を行う。

Laravel 5.6 サービスプロバイダ

Service Container

サービスのインスタンス化を管理するコンテナのこと。
つまりDIコンテナ。
サービスにラベルを付けてコンテナに結合することでサービスの差し替えなどが容易になる。
DIとDIコンテナに関しては以下のサイトが大変わかりやすい。

Service Containerの結合をバインドと言い、
コンテナからサービスのインスタンスを取り出すことをリゾルヴという。

つまり使い方は・・・
Service Providerのregisterメソッド内でService Containerのbindメソッドやsingletonメソッドを使いサービスにラベルを付けてコンテナにバインドする。
サービスを利用したいときはService Containerのmakeメソッドを使いラベルを指定してサービスのインスタンスを得る。
となる。これをさらに疎結合にする方法が後述のFacadeに当たる。

Laravel 5.6 サービスコンテナ

サービスの作成

Service Providerはサービスを供給する機能なのでサービスそのものではない。
従って供給するサービスを指定してやる必要がある。今回は自分で作成してみる。

app/Servicesディレクトリを作成し、その中にMyService.phpを作成する

// app/Services/MyService.php
namespace App\Services;

class MyService {
    public function say($msg){
        echo $msg;
    }
}

クラス/ファイル名は他に合わせて〜Serviceという名前の方が良い。
namespaceも他のものに倣った。

Service Providerの作成

先ほど作成したサービスを供給するService Providerを作成する。
雛形はArtisanから作成できる。

$ php artisan make:provider MyServiceProvider

と書けば、app/providers/MyServiceProvider.phpファイルが生成される。
またクラス/ファイル名は「〜ServiceProvider」となっているのでこれも合わせておいた方が良い。

Service Containerの結合処理

作成したService Providerのregisterメソッドからサービスの結合処理を行う。
Service Providerを継承したクラスでは「$this->app」でService Containerにアクセスできる。

// app/Providers/MyServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;

class MyServiceProvider extends ServiceProvider {
    public function boot(){},
    public function register(){
        $this->app->bind('MyService', 'App\services\MyService');
    }
}

結合処理を提供するメソッドは複数あるので併せて確認
Laravel 5.6 サービスコンテナ 結合

registerメソッド

Service Containerにサービスをバインド(結合)する時にこのメソッドの中に定義する。
registerメソッドが呼ばれるタイミングでは他の全てのサービスの読み込みが終了している保証はないのでService Containerへのバインド以外のことをしてはいけない。

bootメソッド

全Service Providerが結合処理を終えたあとに呼ばれる。
このメソッドの中なかでイベントの登録やラウティング処理などを記述する。

遅延読み込み

初期起動処理時にサービスが結合されるのでサービスの量や処理が多いと動作が遅くなる。
そのため、必要なタイミングでロードされる遅延読み込み機能がある。

Service Providerの登録

Service Providerを定義しただけではLaravelは認知しないので、config/app.phpにServiceProviderを登録してやる。

// config/app.php
...
    'providers' => [
      ...
      App\Providers\MyServiceProvider::class,
      ...
    ]
...

インタンス化されたサービスの取得

サービスのインスタンスの取得はService Containerのmakeメソッドを利用する。
今回はシンプルにするために先ほど作成したService ProviderのMyServiceProviderのbootメソッド内部に記述する。
bootメソッドは全てのサービスの結合処理を終えたあとに実行されるので、このメソッド内部でサービスのインスタンスを得ることができる。

// app/Providers/MyServiceProvider.php
...
    public function boot(){
        $myService = $this->app->make('MyService');
        $myService->say('hello');
    }
...

これで画面にhelloと表示される。

Facade

おそらくGoFのFacadeパターンから来てる名前。
もともとFacadeは建築関係で使われている言葉で「正面◆建物を特徴付ける、装飾などが施された正面の構造」という意味らしい。
faceの語源でもあるとか。

GoFのFacadeパターンは・・・
受け取った仕事を別のシステム(サブシステム)に投げるだけの窓口のようなクラス(Facade)を作成する。
そして窓口となるFacadeに対して仕事を投げれば、仕事を投げた側はサブシステムを意識しなくて良いし、サブシステムが別のシステムに置き換わっても影響がなく、故にサブシステムの独立性が高まるというデザインパターン

[*] -> facade -> sub system1
これが
[*] -> facade -> sub system2
になっても利用方法は変わらない。故にsub systemの独立性が高まる

LaravelでのFacade

LarvelではFacadeはクラスメソッドとして定義されている。

Laravel 5.6 ファサード ファサードクラス一覧

もしくはconfig/app.phpにFacadeのエイリアスが登録されているのでそこでも一覧が確認できる。

Middleware

MiddlewareはHTTPリクエストに対してフィルタリングを行う機能を提供する。
例えばユーザー認証でログインしていないユーザーを別ページへリダイレクトさせるなど。

Laravel 5.6 ミドルウェア

$ php artisan make:middleware Test

でapp/Http/Middleware/Test.phpファイルが作成される。

namespace App\Http\Middleware;

use Closure;

class Test
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
}

Middlewareはリクエストに対するフィルター処理なのでRouteのFacadeを使い適用する。

前処理と後処理

前処理と後処理があり
前処理として登録されたMiddlewareはリクエストが処理される前に実行される。
後処理として登録されたMiddlewareはリクエストが処理された後に実行される。

ライフサイクルに関しては
Laravel5 lifecycleとMVCの図

Middlewareの登録

Middlewareの登録は

  • 全てのHTTPリクエストで処理する (Global Middleware)
  • 特定のラウトで処理する (Route Middleware)
  • Middlewareをグループ化しRouteで処理する (Group Middleware)

の種類がある。

migration

DBのテーブル作成や削除、変更などのバージョン管理を行う機能。

  • migrationファイルの作成
  • migrationの実行

を行うことで機能を実現する。migrationファイルの作成とmigrationの実行はartisanから行う。

migrateコマンド一覧
migrate
migrate:freshDrop all tables and re-run all migrations
migrate:installCreate the migration repository
migrate:refreshReset and re-run all migrations
migrate:resetRollback all database migrations
migrate:rollbackRollback the last database migration
migrate:statusShow the status of each migration

migrationファイルの作成

$ php artisan make:migration posts_table

これで「database/migrations」ディレクトリ以下にmigrationファイルが作成される。
make:migrationコマンドではなくmake:modelコマンドでモデルを作成する際に–migration(-m)オプションでmigrationファイルを作成することもできる。

$ php artisan make:model Post -m

この場合、「database/migrations」ディレクトリ以下に
[年]_[月]_[日]_[時分秒]_create_posts_table.php
が作成される。

モデルは単数形で作成されるmigrationは複数形になるのでこの制約には従った方が良い。

--createオプション

--createオプションを付けるとSchemaファサードのtableメソッドを使いテーブルを作成するコードが書かれているmigrationファイルが生成される。

$ php artisan make:migration create_posts_table --create=posts

この場合、postsテーブルを作成する

--tableオプション

--tableオプションを付けるとSchemaファサードのtableメソッドを使いオプションで指定したテーブルを変更するコードが書かれているmigrationファイルが生成される。

migrationファイルの編集

migrationファイルを編集しテーブルの構成を変更するわけだが、Schemaファサードのtableメソッドで設定できるカラムや装飾子はLaravel 5.6 データベース:マイグレーション カラムで確認できる。

migrationの実行

$ php artisan migrate

でmigrationファイルを元にテーブルの作成やカラム変更などが行われる。

やり直したい

1つ前に戻りたい時はmigrate:Rollback
全て戻したいときはmigrate:reset

[補足]MAMP環境で作業している場合

artisanコマンドを実行しているPHPはMacの標準とかHomebrewでインストールしたものとかではないか?
その場合、PHPからMAMPのmySQLへの接続ができない(ソケットが見つからない)のでNot foundみたいなエラーが出てるはず。
その場合は単純に.envファイルに

DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock

とソケットのパスを記載してやれば良い。

open close