Laravelで開発をするときにSEO対策をしっかりしたいということで、フロントをSPAではなくbladeを使って開発することになったのですが、bladeの知見がなかったので色々試しながら開発したことについてまとめてみました。
viewロジックを書く場所に困った
まず初めにviewロジックをeloquentモデルにアクセサに記述していたのですが、viewロジックを分離させた方がいいということでrobclancy/presenterを採用することにしました。robclancy/presenterは簡単に言うと、eloquentモデルをDecoratorパターンで拡張してviewロジックを切り離して書けるようにするライブラリです。
eloquentモデル自体にはアクセサなどを増やすことなく、eloquentモデルを拡張するような形でviewロジックを書けることにありがたみを感じていましたが、開発が進むにつれてfatになっていきメンテナンスが難しくなってく印象がありました。
また、viewロジックはrobclancy/presenterで書いていけばいいやという感じで進めていましたが、複数のモデルと関連した画面固有のロジックはどこに書けばいいのだろうと悩んだりしたが、画面固有のviewロジックを記述するオブジェクトをviewに渡してもよかったかもしれないです。eloquentモデルに紐づいているviewロジックだったとしても、一つの画面でしか使わないし他で使い回すべきではないロジックなどは画面固有のオブジェクトに移せばfatになっていくこともある程度は防止できると思います。
フロントからのリクエストデータの構造に影響を受けてしまい困った
コントローラに直接ビジネスロジックを書くべきではないということで、サービス層を設けてそこにビジネスロジックを書くようにしていたのですが
$data = $request->all();
$service->execute($data);
上記のように配列をそのままサービス層へ渡してしまい、フロントから送出されるデータ構造に影響を受けてしまい、フロントの変更に伴ってサービス層も修正しないといけないという問題が発生していました。
コントローラからサービス層を呼び出すときは、以下のようにリクエストデータをDTOなどに詰め直してそのオブジェクトを渡した方がいいと思います。
$data = new Data($request->all());
$service->execute($data);
こうすることでフロントから送出されるデータ構造に変更があっても、データをDTOに詰め直す部分に修正を加えるだけで済み、サービス層への影響は考えなくて良くなります。
フロントとの適切な作業分担うまくいかず困った
フロントエンドとバックエンドで担当するエンジニアが異なっていたのですが、テンプレートのコーディングをほぼほぼフロントエンジニアが担当していて、動的な値の埋め込みや条件分岐による表示といったこともフロントエンジニアが作業するといった状態でした。
何が問題かというとテンプレートで使える変数がテンプレートからだと分からなかったり、バックエンドの処理を追う必要が出てしまいフロントエンジニアの作業量が膨らんでしまうので、バックエンドの実装の知識が必要になってくるような箇所についてはバックエンド側で対応した方がいいと思います。
フロントエンジニアにはcssなどが適用されたHTMLファイルを作成してもらい、そのHTMLファイルを元にバックエンドエンジニアがbladeファイルを作成し動的表示を実装するという流れだとフロントエンジニアがbladeやlaravelについて学習する必要が少なくなると思います。
<header>
<div class="navi">
ナビメニュー
</div>
</header>
<div class="content">
ユーザー名:田中 太郎
</div>
このようなHTMLファイルがあったとすると、ユーザー名などの動的な部分を置き換えてあげて、ナビメニューのような重複する内容の場合は@include
を使って再利用すると楽になると思います。
<header>
@include('navi')
</header>
<div class="content">
ユーザー名:{{ $user->name }}
</div>
<div class="navi">
ナビメニュー
</div>
view composerの使い所に困った
view composerを使うとviewに何が渡されているかわかりづらくなるので積極的に使うべきではないという印象ですが、リクエストの内容によらずviewに必ず渡すデータなどはview composerを使った方がいいと思います。
良くあるのがナビメニューやヘッダーにユーザー情報などを表示する場合で、基本的にどの画面でも必要なデータでかつリクエストの内容に影響を受けない場合がほとんどだと思うので使い所になります。
<?php
namespace App\Http\ViewComposers;
use Auth;
use Illuminate\View\View;
class NaviComposer
{
/**
* @param View $view
*/
public function compose(View $view)
{
$view->with([
'user' => Auth::user(),
]);
}
}
viewを出力する際にControllerとは隔離されて上記処理が行われviewにデータが受け渡されるようになるため、Controllerではルーティング固有の処理に専念することができます。
@include('navi')
<div>コンテンツ</div>
{{ $user->name }}
ナビメニューのbladeファイルは予め分割しておくといいと思います。
bladeのコーディングに困った
IDEはphpstormを使っていたのですが、bladeでコード補完をする方法が分からず開発初期からしばらくはコード補完なしで進めていました。しかし、タイポや変数名が分からず調べるといったことが度々発生してしまい、効率が悪いと感じたので調べたところコード補完を効かせる方法を見つけました。
phpstromを使っている場合は、以下のようにbladeファイル上で変数を定義しておくとコード補完が効くようになります。タイポも減るしコーディングのスピードも向上するので特に理由がなければ記述しておくことをおすすめします。
@php
/** @var App\Models\User $user */
@endphp