『PHPフレームワーク Laravel入門』の雑メモ
章ごとに区切っているわけじゃないけど、とりあえずページを進めていく中で覚えておきたいことをメモした(全部が全部そうなわけではないけど)。
★マークはLaravelに慣れた上で改めて調べ直すこと。
▫️http://アプリケーションのアドレス/コントローラ/アクション
というように対応させるのが一般的
▫️シングルアクションコントローラ(一つのコントローラに一つのアクションしか存在しない)というものが存在する
→普通のアクションメソッドの代わりに __invokeメソッドで処理を実装する
→一応アクションメソッドは追加できるが、アクションとしての利用は不可
→ルート情報の設定では Route::xxx(“address”, “controller_name”) とする
→__constructは使っても良い
→__invokeはクラスのインスタンスを関数的に実行するためのもの(PHPのクラスに用意されているマジックメソッド)
▫️★ DI(依存性注入)について詳しく調べる
▫️viewメソッドの階層表現は . ドット
→viewメソッドの戻り値はテンプレートファイルではなく、「Response」インスタンス(このインスタンスにテンプレートのレンダリング結果がコンテンツとして格納されている)
▫️ルーティング設定にパラメータを設定する場合、 { id? } というように$はいらない
▫️クエリー文字列(?id=1&password=xxxxx)はRequestから受け取る
▫️同名の.phpファイルと.blade.phpファイルでは、bladeファイルが優先される
▫️エスケープ処理させたくない場合は、{!! 値・式・変数・関数など !!}
▫️条件不成立の場合に処理されるディレクティブ(@unless)
▫️@whileディレクティブなどを使用する場合に用いられる@php
▫️@breakや@continueもある
▫️繰り返しディレクティブには$loopという繰り返しに関する状態を持った変数が用意されている
▫️blade: レイアウトのような土台となるルートファイルで@sectionを用意する場合は。@endsectionではなく@showで締める
▫️componentディレクティブで他ファイルの中身をまるっと持ってこれる
→他ファイルの方で (( $val )) のような変数を用意しておくと、読み込む側(componentディレクティブを使う側)で@slot(“val”)という形で値を流し込める
→slotに何も流し込まなければ、何も表示されない
→@component内でslot以外の値を記述しても、何も表示されない
▫️componentと似たようなサブビュー(@include)も存在する(詳しい違いは画像)
▫️繰り返し固まった要素を表示したいとき、それにコントローラから受け取った値に応じて内容を変化させたいときに@eachを使うと良い(@each(“読み込むテンプレート”, “データ”, “テンプレート側での名前”))
▫️コントローラ→ビューコンポーザ(必要な情報などの処理)→ビュー(テンプレート側で行うべき処理をどっかに任せたい・・・)
→ビューをレンダリングする際に自動的に実行される処理を用意するための部品
→ビューコンポーザの引数にViewオブジェクトが渡され、必要な処理を行った後にそのViewオブジェクトと結合することでテンプレート側に引き渡せる
▫️ビューコンポーザを利用するためには、「サービス」と「サービスプロバイダ」の仕組みについての理解が必要
→サービス: 機能強化のための仕組みの一つ
→サービスプロバイダ: DI(依存性注入)の機能を持ったシステムで、必要に応じてサービス(プログラム)を自動的に自身の中に取り込み、使用できるようにしてくれるシステム
→サービスとサービスコンテナにより、必要に応じて各種機能をアプリ内に取り込み、機能拡張をすることができる
▫️サービスを「登録」するために用意されているのがサービスプロバイダ
→自身でサービスを定義し組み込むことも可能だが、サービスに限らずアプリの様々な機能を「実行」するのにもサービスプロバイダは利用されている
→この「実行」という利用方法で実現されるのが「ビューコンポーザ」
→サービスプロバイダは「ServiceProvider」というクラスを継承して作成される
→registerとbootメソッドが用意されている
→register: サービスプロバイダの登録処理
→boot: アプリケーションサービスへの「ブートストラップ処理(アプリケーションが起動する際に割り込んで実行される処理)」
=> 「何を登録するのか」と「実際どんな処理をするのか」を定義する
→そのほかにもメソッドは用意されているが、とりあえずはboot(実行させたいから)
→★ サービスとサービスコンテナ、DIについてよく調べる
▫️ビューコンポーザの作成には2通りある
→サービスプロバイダとは別にビューコンポーザのクラスを定義し、bootで設定
→boot内に無名クラスでビューコンポーザの処理を組み込む
▫️クロージャ(or 無名クラス)を使用する方法
→View::composer(“ビュー(テンプレート)の指定”, 関数またはクラス)
→使用できるように「サービスプロバイダ」に登録
▫️ビューコンポーザクラスを使用する方法
→特に配置する場所は用意されていない
→アプリケーションで利用できるスクリプトは、「Http」フォルダ内であればどこでも構わない
→普通のphpファイルでおけ
→必要となるのはcomposeメソッドで、Illuminate\View\Viewのインスタンスを引数として持っていて、サービスプロバイダのbootからView::composerが実行された際に呼び出される
▫️ビューコンポーザの処理はコントローラからは見えないため、コントローラで処理すべきものはビューコンポーザに用意すべきでない
→「このビュー(テンプレート)では「常に」この処理をしてこの結果をビューに渡す」ということが決まっている場合に有効
→「その処理は指定のビューで常に行うのか、それとも必要に応じてなのか」を考えるべき
▫️ミドルウェアとは、コントローラ処理の前後に割り込み独自の処理を追加する仕組み
→リクエスト -> ミドルウェア -> アクション -> ミドルウェア -> レスポンス
→作成するとhandleメソッドが追加される
→$requestとClosure(無名クラスを表すためのクラス)インスタンスの$nextが渡される
→nextにrequestを渡すことで次のステップに進む
→このミドルウェアを使用できる状態にするため、Kernel.phpに追加する
→利用可能になったミドルウェアを指定することが必要(一般的にはルーティングに設定する[web.php])
→この場合、web.phpでuseして ->middlewareに::classを指定する(登録名でもおけ)
→ミドルウェア内で$requestにデータを追加した場合、コントローラの引数に$requestを用意する
→アクションの後の処理(アフター)も作成することができる
→$next()で返される値がreturnされるが、戻り値は・・・レスポンスインスタンス
→流れは
①クライアントリクエスト
②$next($request)までの処理(ビフォーミドルウェア)
③ $next($request)でコントローラにリクエスト
④コントローラの処理
⑤コントローラからレスポンス
⑥ミドルウェア内での処理(アフターミドルウェア)
⑦コントローラからのレスポンスをミドルウェア内でreturn(テンプレートへ)
→responceにはsetContentというメソッドが装備されている(まるっと中身を入れ替え)
▫️グローバルミドルウェアは全てのアクセスに対して自動的に処理を追加する
▫️複数のミドルウェアをセットにして適用できるミドルウェアグループもある
▫️バリデーションする簡単な方法はコントローラのvalidateメソッドを利用するやり方
→これはControllerクラスに組み込まれているValidateRequestというトレイト
→$this->validate($request, バリデーションルール)
→エラーが発生すると、Laravelが内部的にフォームページを表示するレスポンスを生成してクライアントに返送する
→エラーが発生すると、フォームページにreturnし、ついでに$errors変数にエラー内容が付加されたものが利用できるようになる
→前回送信した値をバックさせるにはoldメソッドを用いる
→特定のフィールドにおけるエラー文を特定するhasメソッドやfirstメソッド、getメソッドを持つ
→@ifを用いなくても、@errorを使えば条件分岐を勝手にしてくれる
▫️バリデーションのカスタマイズには「フォームリクエスト」と「カスタムバリデーション」の二つがある
▫️フォームリクエストはRequestクラスを継承して作成されるもので、リクエストに関するロジックを切り分けることができて便利
→authorizeメソッドとrulesメソッドを持つ
→authorize: フォームリクエストの利用制限(true=許可 | false=不許可(HttpExceptionエラー))
→rules検証ルールの配列を返す
→メッセージのカスタマイズをするmessageメソッドもある(既存のメソッドをオーバーライドしている)
▫️バリデータの作成をすることで、エラー発生時の挙動を制御できる
→バリデータはバリデーションを行う機能のことで、Validatorクラスがそれを担う(useする)
→withErrorsメソッドにはValidatorインスタンスを渡し、発生したエラーメッセージをリダイレクト先まで引き継がせる
→withInputメソッドは送信されたフォーム値をそのまま引き継がせる
→$request->query()でクエリー文字列にバリデータを適用できる
→エラーメッセージのカスタマイズをするには、Validator::makeの第三引数に配列として定義する
→状況に応じてルールを「追加」するには$validatorのsometimesメソッドを用いる(falseを返すと、追加ルールを適用)
→独自バリデータもIlluminate\Validation\Validatorクラスを継承したクラスで作成できる
→validateXxxというメソッドを用意し、Xxxというバリデーションルールを作成できる
→第一引数には属性(設定したコントロール名)、第二引数にチェック対象、第三引数にルールに渡されるパラメータを定義できる
→falseを返すとエラーが発生したことを示す
→独自バリデータを使えるようにするには、サービスプロバイダを使用する
→この独自バリデータはValidator::extendでも簡単に定義できる
→extend(“バリデーション名”, クロージャ)として追加し、クロージャの引数には上記の3つに加えて、$validatorのインスタンスが用意される(falseでエラー)
→ルールを作って利用する方法もあり、Ruleクラスを継承したクラスで定義できる
→passesメソッドとmessageメソッドを持つ
→passes: ルールの追加条件
→引数にはrequiredなどの属性とチェックする値が渡される
→message: 問題発生時のメッセージを返すメソッド
▫️CSRF対策はVerifyCsrfTokenクラスで行われている
▫️クッキーの利用はRequestとResponseクラスに用意されているメソッドを用いる
→Responseインスタンスのcookieメソッドでクッキーの値を保存するが、cookieメソッドで保存処理をした「responseを返さないとクッキーは保存されない」点に注意
▫️redirectヘルパを引数なしで呼び出すと、Illuminate\routingのRedirectorクラスのインスタンスが返される
→このインスタンスのメソッドを呼び出すことで、リダイレクト先の設定などを行える
→redirect()->json(“テキスト”)というような返送の仕方もある
▫️responseメソッドで得られるのはResponseクラスのインスタンスではない
→引数でResponse $responseとしても response()->cookie(…)などは利用できない
→response()で得られるのは、Responseを生成するファクトリクラスのResponse Factoryのインスタンスで、そのインスタンスがcookieメソッドなどを持っている
→このファクトリクラスでviewを呼び出すことでResponseインスタンスを生成している
▫️データベース処理のための機能には、主に| DBクラス(クエリビルダ) | Eloquent(ORM)がある。
→DBクラス: データベースアクセスのための基本的な機能をまとめたクラス
→DBにアクセスするためのクエリを発行し、送信することができる
→「クエリビルダ」という機能が用意されており、これを利用するとメソッドを使って(SQLクエリを書かずに)データベースにアクセス可能
→Eloquent: ORM(データベースのデータをシームレスに言語のオブジェクトに変換し操作できる)の機能を持ったもの
▫️DB利用のためにはconfig/database.phpに情報を追加
▫️DBクラスを利用してデータベースにアクセス
→DBクラスのSQLクエリ実行メソッドは簡単
→DB::select()…etc.
→パラメータ結合でSQL文を簡単に作成できる
→パラメータ部分を :xxx としておき、selectの第二引数に連想配列として:xxxを埋める値を定義する
▫️クエリビルダを利用することで、PHPらしい書き方でデータベースを操作できる
→メソッドチェーンでアクセスが行える
→PHPのコードにSQL文が紛れることがないので、ストレスがない
→取得: DB::tableとget(DB::table(“test_users”)->get())
→table: BuilderクラスでSQLクエリ文を「生成するための機能を提供」する
→tableでSQLクエリ発行の準備ができたら、getメソッドで実際に発行
→get( [ “id”, “name” ] )で特定フィールドの取得もできる
→where: フィールド名と値を指定し、合致しているものを保管する
→( フィールド名, 演算子, 値 )とすることで合致以外の検索もかけられる
→first: 保管されたデータの最初の一つを取得する
→orWhere: 複数条件の設定ができる
→where()->where()… とすると、andでつながれた状態(全ての条件に合致したものを保管)
→where()->orWhere()->orWhere()…とすると、orでつながれた状態(複数条件のうち、一つでも当てはまったものを保管)
→whereRaw: where, orWhereが連なって長くなるときに有効
→whereRow(“xxx >= ? and yyy === ? …”, [ “ ?に対応するパラメータの値たち ” ] )->get() のようにして使う(名前指定プレースホルダーは無理)
→そのほか(orderBy, offset=指定した位置から取得, limit=指定した数だけ取得) →offsetとlimitを使えば、指定データずつ取得できる
→DB::table(”xxx”)->insertのようにCRUD処理も簡単にできる
▫️マイグレーションとは、データベースの構造を定義するもので、この定義に従って再現すると楽チンっていう機能
→マイグレーションファイルの作成・定義→マイグレートという手順でテーブルなどが作成される
→マイグレーションクラスのクロージャの引数に渡されるtable(Blueprintクラスのインスタンス)でカラムの定義をしていく
▫️シーディングでダミーレコードを作成できる
→シーディングファイルを作成・定義→「DatabaseSeeder登録」→シーディング実行
→runメソッドにレコード作成などの処理を追加していく
→シーディングコマンドで起動するのはDatabaseSeeder.phpであるため、ここに個別のシーディングクラスを登録しておく必要がある
▫️データベースにアクセスするための機能自体は、Illuminate\Database名前空間に存在するDatabaseManagerとConnectionというクラスが提供している
→DatabaseManagerでデータベース設定を利用した「接続を管理」し、そこから取得されたConnectionインスタンスを利用してデータベースを利用している
→これらの機能を簡単に呼び出せるよう「ファサード」という形にしたものがDBクラス
→ファサードは、Illuminate\Support\Facades名前空間にまとめられているため、この名前空間が登場したら「実際の機能は別に定義してある」と理解
▫️ORMとは、データベースのレコードをクラスオブジェクトとして扱えるようにするための仕組み
→Laravelでは「Eloquent」というORMが用意されており、「モデル」と呼ばれるクラスを定義し、データベースを扱う
→モデルは、テーブルの内容を定義したクラス(テーブルのフィールド情報など)
→$tableというメンバ変数で明示的にテーブル名(モデルの複数形じゃない場合など)を指定できる
→★ テーブルとモデルに関連を持たせるためには、テーブルは「複数形」、モデルは「単数形」という命名規則に則らなければならない
→モデル::all(): 全レコード取得(Illuminate\Database\Eloquent名前空間のCollectionクラスのインスタンスとして得られる)
→モデル::find(“整数”): idによるレコード検索
→idというフィールド以外でプライマリキーを設定した場合、モデルクラスに$primaryKeyというプロパティを用意して、そこに名前を設定する
→モデル::where(“F名”, 値)->get(): whereは「ビルダクラス」のインスタンスを返すため、DBクラスのビルダとは異なる
→モデルのwhereのビルダクラス: Illuminate\Database\Eloquent名前空間のBuilderクラスのインスタンス
→DBクラスのwhereのビルダクラス: Illuminate\Database≠Query名前空間のBuilderクラスのインスタンス
▫️モデルクラスの拡張
→独自のメソッドなどを追加できる
→モデルスコープで、モデルの範囲を特定(絞り込み)できる
▫️スコープにはグローバルスコープとローカルスコープがある
→ローカルスコープ: モデル内にメソッドを用意しておき、必要に応じてそれらのメソッドを呼び出して絞り込む = 呼び出さなければ機能しない
→ scopeXxxYxxというメソッド名にする必要がある
→引数には$queryが渡され、これの正体はモデルクラスのwhereで返ってくるBuilderインスタンス($query以降に引数を用意できる)
→return で返すものは、絞り込む処理をして得られた「ビルダ」
→ビルダを返すことでメソッドチェーンが実現できる
→スコープメソッドを呼び出す際には、メソッド名のscopeはいらない
→グローバルスコープ: 処理を用意するだけで、「そのモデル(全てのモデルではない)」での全てのレコード取得に適用される
→bootメソッド: モデルが作成される際の初期化処理
→static::addGlobalScope: グローバルスコープの処理(これをオーバーライドする)
→第一引数にスコープ名、第二引数にBuilderインスタンスを持つクロージャを用意している
→ Illuminate\Database\Eloquent\Builderをuse
→protected static function boot内にparent::boot(親から引き継ぎ)
→boot内にstatic::addGlobalScopeを定義
→boot内にグローバルスコープを定義する
→汎用性の高い(複数のモデルで使用される)グローバルスコープは、「Scopeクラス」として作成しておくと便利
→Illuminate\Database\Eloquent名前空間にあるScopeを実装(インターフェース)して定義されるクラスを作成
→第一引数にBuilderインスタンス、第二引数にModelを持つapplyメソッドを用意し、絞り込みの処理を行う
→特定のモデルではないため、Modelが渡されている
→Scopeクラスを適用させるには、それをuseして各モデルのboot内のaddGlobalScopeの引数にインスタンスを渡す
▫️モデルを使用したCUD
→Create: モデルインスタンス作成->値を設定->インスタンスを保存(saveメソッド)
→モデル内でスタティックな変数としてルールを定義しておくと楽
→$request->all()で取り出した値の中から_tokeを削除
→モデルのプロパティに追加するためfillメソッドを実行(フォームの値を引数に)
→saveメソッドで作成
→インスタンス->プロパティ = $request->プロパティとしても良いが、まとめてやったほうが楽
→Update: モデル::findでレコードを特定->フォームの値を取り出す->save
→Delete: モデルインスタンスの特定->モデルインスタンス+->delete()で完了
▫️より本格的な(複雑な)開発にはEloquent、比較的簡単でシンプルな操作にはDBクラスのクエリビルダ、というように状況に合わせて使えるようにする
▫️複数のテーブルにまたがってデータを取得したい場合、モデルの「リレーション」を使用するのが良い
→モデル内のtimestamps()ではcreated_atとupdated_atフィールドが自動的に追加される
→リレーション関係のあるテーブルでは、一方に「外部キー」と呼ばれる項目が用意される
→外部キーとは、関連するもう一つのテーブルのレコードIDを保管しておくフィールドのこと(関連するテーブル名の単数形_idなどが一般的)
→外部キーを持たないテーブルが主テーブルで、外部キーを持っている主テーブルの関連情報を保管しているテーブルを從テーブルと呼ぶ
→リレーションにはいくつか種類がある
→hasOne: 2つのテーブルが 1 : 1 の関係で紐づけられている
主テーブルから、それに関連する從テーブルのレコードを取得するための機能
主テーブルに從テーブルの名前を指定したメソッドを用意するのが一般的
関連づけられた從テーブルは、プロパティとして取得でき、(中身は從テーブルのインスタンス)、続けて主テーブルの独自メソッドなどを呼び出せる
→hasMany: 1 : 多 の関係で紐づけられている
hasManyはhasOneと同様に、主テーブルに用意するリレーション
自分(主テーブルのID)と関係のある(外部キーを持つ)從テーブルたちからレコードを引っ張ってくる
→belongsTo: 從テーブル側から関連づけている主テーブルのレコードを取り出す
他人(外部キー)を辿っていったら一人の人(主テーブルのID)にたどり着くイメージ
複数の投稿をしているユーザー(一人)を、投稿側から特定する感じ
從テーブル側から特定するので、メソッドの追加は從テーブルのモデルに
→関連レコードの有無は、外部キーを持っているか否かで異なる
→投稿データを持つテーブルにはユーザーを特定する外部キーが存在する
→外部キーが存在するということは必ず一人のユーザーにたどり着く
→なぜならユーザーが投稿していないのに、投稿データが存在するはずがないから
→ただ、ユーザー側から関連レコード(投稿データ)を取得しようとした場合は、必ずしもレコードが存在するとは限らない
→なぜなら、一人のユーザーが必ず投稿しているという保証がないから
→このような関連の有無によってレコードを取得することは、hasやdoesntHaveメソッドで実現できる(投稿データを持っているユーザーのみ、持たないユーザーのみ取得)
→モデルクラス::has(“リレーション名(定義したメソッド名)”)->get()
→モデルクラス]::doesntHave(“リレーション名(定義したメソッド名)”)->get()
→上記のようなリレーション上での操作はデータベースによっては辛いものがある
→全ユーザーを取得し、そのユーザーに関連する投稿データを全て取得するとする
→全ユーザーの取り出し(1回の問い合わせ)
→一人のユーザが10個の投稿をしていた場合の取得(10回の問い合わせ)
—
→一人のユーザーに紐づく全投稿データ(10個)の取り出し(1回の問い合わせ)
→一つ一つの投稿データからユーザーを特定(10回の問い合わせ)
→N個のデータを取得するときに N + 1 回問い合わせをしなくてはならないことから、「N+1問題」と呼ばれている(これが問題)
→このような問題を回避するために「with」メソッドを用いる
→モデル::with(“リレーション名(定義したメソッド名)”)->get()
→このwithを使用することで、レコードの取得の仕方を変更し負担を減らせる
→投稿データのみを取得(一回の問い合わせ)->得られた投稿データの外部キーをまとめて、それらのIDのユーザーを取得(2回の問い合わせ)
→このように2回で済む
→withのようなやり方を「Eagerローディング」と呼ぶ
▫️RESTとRESTful
→RESTの考えに基づいたRESTful「的な」アプリケーションを作成する場合、リソースコントローラを用いると手軽に実装できる
→make:controller —resource
→Laravelでは、アクションメソッド内で配列をreturnすると、自動的にその配列データをJSON形式(データ構造)に変換して出力してくれる
→JSON形式であれば、外部サーバーからアクセスして、取得したデータを簡単に処理できる(Vue.jsとかでも利用できる?)
→上記のような機能を利用したものは、Resourcefullであって、RESTfulではない
→RESTfulでは、「CURDは全て同一のアドレス」で、「アクセスに使うHTTPメソッドの違い(GET/POST/PATCH(PUT)/DELETE)によって分ける」のが一般的
→RESTfulなサービスでは、入力のためのフォームは不要
→ /xxx - (GET) - index - 一覧表示
→ /xxx - (POST) - store - 作成
→ /xxx/id - (GET) - show - 詳細表示
→ /xxx/id - (PUT/PATCH) - update - 更新
→ /xxx/id - (DELETE) - delete - 削除
▫️セッションは、サーバー<=>クライアント間の接続を「維持」し、ここのクライアントごとに各種のサービスや情報などを保持する技術(ステートレスでない)
→セッション = クッキー + データベース(Webサーバ-ファイル)
→それぞれのクライアントごとにID(ユーザーを特定できる一意の値)をクッキーとして保管する(これを「セッションID」と呼ぶ) => ブラウザが保管
→そしてクライアントごとの情報は、そのセッションIDに関連づけてデータベース(サーバー側)に保存することで、やりとりが可能となる => Webサーバーにファイルとして保管
→Cookieは「クライアント側に保存する」ことで完結
→SessionはCookie + データベースなので、「クライアント側に保存」しつつ、「データベース(Webサーバにあるファイル)にも保存」する
→Cookieとして保管されたデータはクライアント側にあるため操作でき、Sessionとして保管されたデータはサーバ側で保管されているため操作が困難
→値の保存: $request->session()->put(“キー”, “値”)
→値の取得: $request->session()->get(“キー”)
→セッションファイルは、storage内のframeworkファイル内にあるsessionsに保管される
→本格的に稼働させるようになると、セッションごとにファイルが増えていくため、非効率
→データベースを利用した形にするのが良い?
→sessionに関する設定情報は、config/session.phpに用意されている
→セッションの保存先を変更するにはdriverをdatabaseに変えてあげれば良い
→そして.envのSESSION_DRIVERもdatabaseに変更してあげる
→後はセッション用のテーブルをデータベースに準備する
→セッション用のテーブルは仕様が決まっているため、手作業はキツイ(コマンドを利用すべき)
▫️ページネーションは、データベースに保管されているレコードを一定数ごとに取り出す記述
→「1ページごとに決まったレコードを取り出す昨日」「指定ページに該当するレコードを表示するための移動機能」の2つによって実現されるもの
→DBクラスとsimplePaginateメソッド: DB::table(“テーブル名”)->simplePaginate(“いくつずつ取り出す?”)
→このsimplePaginateの戻り値に、リンクの情報も入っているため手軽
→$items = DB::table(xx)->simplePaginate => $items->links()
とテンプレート側でするだけで、リンクが表示される
→モデルとsimplePaginateメソッド: モデルクラス::simplePaginateで同様のことができる
→※メソッドの呼び出し順序は、simplePaginateがラストにくるようにしなければいけない(getと同じような感じ、simplePaginateが返すものでないとlinkメソッドが利用できない)
→ソートしてページネーションを実現したい場合は、orderByしてからsimplePaginate
→テンプレート側では、受け取ったデータ群のappnedsメソッドにオプションを追加した上でlinksメソッドを発動させる
→ $items->appends( [ ’sort’ => $sort(“どのフィールドでソートする?”) ] )->links()
→simplePaginateでは前後(prev-next)のみであったが、paginateメソッドを利用すれば、ページ番号のリンクが表示されるようになる
→ページ移動のリンクをカスタマイズしたい場合は、linksメソッドが使用するテンプレートを変更してあげれば良い
→linksの引数にテンプレート名を指定することで、そのテンプレートを利用して移動のリンクを生成させることができる
→Laravelが用意しているデフォルトのリンクテンプレートを利用可能にするには、 php artisan vendor:publish —tag=laravel-pagination というコマンドを実行する
→views/vendor/pagination下にテンプレートファイルが保存される
→simpleXXXはsimplePaginate用、それ以外がpaginate用
→これらのファイルをベースとして、カスタマイズし、linksメソッドの引数に名前を指定してあげれば良い
→$paginator = paginateやsimplePaginateで返されたインスタンス($items)
(以下、先頭に$paginatorが付く)
→hasPagesメソッド = 複数ページあるか否か
→onFirstPageメソッド = 最初のページを表示しているか否か
→@lang(‘pagination.previous’) = 国際化対応リソースからpagination.previousという名前の値を取り出す
→hasMorePagesメソッド = 現在ページより先にページがあるか否か
→previousPageUrlメソッド = 前ページのURLを取得
→@lang(“pagination.next”) = 国際化対応リソースからpagination.nextという名前の値を取り出す
→currentPageメソッド = 現在開いているページ番号
→countメソッド = ページに表示されているレコード数
→nextPageUrlメソッド = 次のページのURLを取得
→url(“番号”) = 引数に指定したページ番号のURLを取得
→simpleXXXテンプレートでないファイルでは、$elementsが用意され、これを使用してページ番号の表示を行う処理をする(default.blade.phpでされている)
→Bootstrapなどを利用してリンクのデザインをよくするのも良い
▫️認証機能を担うのがAuthクラス
→Laravel6以降では laraval/ui というパッケージが必要
→Auth利用のためには
・laravel/ui をcomposerでインストール
→composer require laravel/ui
・npm 利用のためにNode.jsをインストール
→公式からダウンロード
する必要がある
→ 上記の環境が整ったら
・php artisan ui vue —auth
・この段階ではまだ利用できない
・npm install && npm run dev
・これにより、フロントエンド側のファイルがビルドされる
→認証機能では、Authenticatableを継承したモデルクラスである必要がある
→認証機能をコントローラに付加するには、middleware(“auth”)を付加する
→ログイン未ログインで処理を分けたい場合は、Auth::attemptを用いる
→★Auth認証について、詳しく調べる
▫️ユニットテストとは、単体テストとも呼ばれるテストであり、機能ごとに動作を確認していくもの
→LaravelではPHPUnitが組み込まれており、これを利用してテストができる
→テストをするにはtestsフォルダの下にファイルを作る必要がある
→testsフォルダ下には、FeatureとUnitというフォルダがあり、これらの中にExampleTestというサンプルコードがある
Unitフォルダのファイル: TestCaseクラスを継承
testをプレフィックスとするメソッドを定義していく
本番ではテスト用のデータベースを準備する必要がある
phpunit.xmlにPHPUnitの設定にしようするデータベースの情報を追記する
→<phpunit>タグの中のなかのphpタグ内にあるenvタグにデータベース名を指定(sqliteの場合はvalueにファイル名も)
ダミーレコードの情報を用意するために、database/factories内のUserFactory.phpを編集(テーブルによって異なる?)
→defineメソッドの第一引数にモデルクラス、第二引数に、Facker\Generatorクラスのインスタンスを受け取るクロージャが用意されている
→fakerを利用してフェイクデータを用意し、モデルに設定する各フィールドの値を連想配列にまとめてreturnする
ダミーデータが揃ったらユニットテストのスクリプトを作成
→ php artisan make:test XXX
→tests/Feature内にスクリプトが作成される
ダミーデータが飛んできたときにどういう検証をするのかをスクリプトに記述
vendor/bin/phpunit を実行
指定アドレスにアクセスすることも可能
→Featureフォルダ内のExampleTest.phpを参考に(アドレス確認用)
値検証(Unit/ExampleTest.php) | アドレス検証(Feature/ExampleTest.php)のサンプル
→テストスクリプトはFeature下に作成していく
この内、例えばアドレス検証の際にログインユーザーのみアクセスできる状態かを検証したい場合にfakerで作成したダミーレコードの定義が使用される
→actingAs(“作成したインスタンス”)->get…
データベース(モデル)のテストも可能
→ php artisan make:test で作成したFeature下のファイルに記述する
→その際に後処理(テストに使用したデータの削除など)を行なってくれるDatabaseMigrationsをuseしておく必要がある
▫️ユニットテストでコントローラやモデルの動作確認はできるが、Laravelのテストには「ブラウザテスト」と呼ばれる、実際にブラウザからアクセスして動作確認をする機能もある
▫️★ そのほか、今後はサービス関連(サービス、サービスコンテナ、ファサード)、キューとジョブおよびタスクなどの非同期関連などの理解を深めていく必要がある
【スクショ】
以下のサイトを使用させていただきました。