リファクタリングの個人メモです。
ビューの中に繰り返し処理を記述している場合は、処理を別ファイルに切り出し、
@include
で呼び出すPHPの処理はビューの中に書かず、コントローラで渡す(他でも使う処理の場合は自作のヘルパー関数を作って渡す)
リファクタリング事例
リファクタリング前のコード
以下のように同じコードが繰り返されている処理をリファクタリングする。
<div class="p-service__list">
<section>
<h2 class="c-page-headline">iphone</h2>
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'iphone' )
<section class="p-service-section">
<div>
<span class="p-service-section__img-border">
<img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}">
</span>
</div>
<div>
<h3 class="p-service-section__name">{{ $service['name'] }}</h3>
<p class="p-service-section__lead">{{ $service['lead'] }}</p>
</div>
</section>
@endif
@endforeach
</section>
<section>
<h2 class="c-page-headline">iphone</h2>
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'android' )
<section class="p-service-section">
<div>
<span class="p-service-section__img-border">
<img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}">
</span>
</div>
<div>
<h3 class="p-service-section__name">{{ $service['name'] }}</h3>
<p class="p-service-section__lead">{{ $service['lead'] }}</p>
</div>
</section>
@endif
@endforeach
</section>
<section>
<h2 class="c-page-headline">xperia</h2>
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'xperia' )
<section class="p-service-section">
<div>
<span class="p-service-section__img-border">
<img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}">
</span>
</div>
<div>
<h3 class="p-service-section__name">{{ $service['name'] }}</h3>
<p class="p-service-section__lead">{{ $service['lead'] }}</p>
</div>
</section>
@endif
@endforeach
</section>
</div>
</div>
コードを見るとsection
が繰り返されているのがわかる。
<section>
<h2 class="c-page-headline">iphone</h2>
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'iphone' )
<section class="p-service-section">
<div>
<span class="p-service-section__img-border">
<img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}">
</span>
</div>
<div>
<h3 class="p-service-section__name">{{ $service['name'] }}</h3>
<p class="p-service-section__lead">{{ $service['lead'] }}</p>
</div>
</section>
@endif
@endforeach
</section>
@foreach(__('service') as $service)
言語ファイル( resources > lang > ja )のservice.phpに記述された配列を、$service
として一つづつ抜き出している。
@if( $service['category'] === 'iphone' )
抜き出した配列のキー名category
の値がiphone
なら以下の処理を実行する。
このように、category
の値によって表示するタイトルとデータを変えている処理。
リファクタリング
1. 繰り返しのコードを別ファイルに移動する。
繰り返されているコードを別ファイルに記述する。ここでは、section.blade.phpを作成。
呼び出しは@include
を使う。
<section>
<h2 class="c-page-headline">{{ $categoryTitle }}</h2>
@foreach($services as $service)
<section class="p-service-section">
<div>
<span class="p-service-section__img-border">
<img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}">
</span>
</div>
<div>
<h3 class="p-service-section__name">{{ $service['name'] }}</h3>
<p class="p-service-section__lead">{{ $service['lead'] }}</p>
</div>
</section>
@endforeach
</section>
[1] <h2 class="c-page-headline">{{ $categoryTitle }}</h2>
h2タグのデータは変数$categoryTitle
とし、@include
した時に渡すようにする。
[2] @foreach($services as $service)
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'iphone' )
foreachでデータを一つづつ取得し、指定のカテゴリ名に一致する場合のみ実行(フィルタリング)していた処理を変更し、フィルタリング後のデータを$services
として渡すようにする。
2. PHPの処理をコントローラに移動する
public function index(Request $request)
{
return view('contents.service.index');
}
元の状態はビューファイルを返しているだけ。
public function index(Request $request)
{
foreach(__('service') as $service){
if( isset($service['category'])){
$services[$service['category']][] = $service;
}
}
return view('contents.service.index', $services);
}
リファクタリング後はビューの中のforeach
処理をコントローラ内で実行し、ビューに渡している。
▼foreachの処理
foreach(__('service') as $service){
if( isset($service['category'])){
$services[$service['category']][] = $service;
・if( isset($service['category']))
変数$serviceのキーcategoryに値があるか確認。
・$services[$service['category']][] = $service;
変数$services
を新たに用意。
キー名がカテゴリー名となる連想配列にforeachで抜き出した値($service
)を追加していく。
▼注意点
配列に要素を追加する場合はarray[] = '追加する値'
とする。
array[キー名]
のようにキー名を指定して代入すると上書きになってしまう。
3. ビューの修正(@include
で読み込む)
切り出したビューを読み込む。
・@include('ビュー', ['変数名'=>'渡すデータ'])
┗ ビューはresources > views 配下のディレクトリパスで指定。
┗ ディレクトリはドットでつなぐ。
┗ 第2変数でビューにデータを渡す。
<div class="p-service__list">
@include('contents.service.section', ['categoryTitle'=>"iphone", 'services'=>$iphone])
@include('contents.service.section', ['categoryTitle'=>"android", 'services'=>$android])
@include('contents.service.section', ['categoryTitle'=>"xperia", 'services'=>$xperia])
</div>
あんなに長かったビューが驚くほどシンプルになった。。
繰り返し処理があったら@include
が便利。
(補足)PHP処理のリファクタリングの考え方
リファクタリングLevel 0
リファクタリングなし
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'iphone' )
//処理
@endif
@endforeach
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'android' )
//処理
@endif
@endforeach
@foreach(__('service') as $service)
@if( isset($service['category']) && $service['category'] === 'xperia' )
//処理
@endif
@endforeach
↓ 処理を外部ファイルに移動し@import
で読み込む
PHP処理をビューファイルの情報に
リファクタリングLevel 1
@php
foreach(__('service') as $service){
if( isset($service['category']) && $service['category'] === 'iphone' ){
$iphone[] = $service;
}
elseif( isset($service['category']) && $service['category'] === 'android' ){
$android[] = $service;
}
elseif( isset($service['category']) && $service['category'] === 'xperia' )
$xperia[] = $service;
}
}
@endphp
<div class="p-service__list">
@include('contents.service.section', ['categoryTitle'=>"iphone", 'services'=>$iphone])
@include('contents.service.section', ['categoryTitle'=>"android", 'services'=>$android])
@include('contents.service.section', ['categoryTitle'=>"xperia", 'services'=>$xperia])
</div>
↓ PHP処理をコントローラに移動
リファクタリングLevel 2
public function index(Request $request)
{
foreach(__('service') as $service){
if( isset($service['category']) && $service['category'] === 'iphone' ){
$iphone[] = $service;
}
elseif( isset($service['category']) && $service['category'] === 'android' ){
$android[] = $service;
}
elseif( isset($service['category']) && $service['category'] === 'xperia' )
$xperia[] = $service;
}
}
return view('contents.service.index', compact('iphone', 'android', 'xperia'));
}
ビューのPHP処理をそのままコントローラに移動。(★基本的に、PHP処理はビューではなくコントローラで行う)
・compact('変数名', '変数名', '変数名',,,,,)
compactメソッドは指定した変数を連想配列にしてくれる。
キー名は変数名、値は変数に入っている値が自動的に適用される。
※compactの注意点
変数は$変数名
ではなく、'変数名'
で渡す。
↓ ビューに連想配列を渡す(compactメソッドを使わない)
リファクタリングLevel 3
public function index(Request $request)
{
foreach(__('service') as $service){
if( isset($service['category']) && $service['category'] === 'iphone' ){
$services["iphone"][] = $service;
}
else if( isset($service['category']) && $service['category'] === 'android' ){
$services["android"][] = $service;
}
else if( isset($service['category']) && $service['category'] === 'xperia' ){
$services["xperia"][] = $service;
}
}
return view('contents.service.index', $services);
}
・$services["キー名"][] = 値
変数$services
を新たに定義し、指定したキーに値を追加していく。
↓ カテゴリ名の分岐にifを使わない
リファクタリングLevel 4
public function index(Request $request)
{
foreach(__('service') as $service){
if( isset($service['category'])){
$services[$service['category']][] = $service;
}
}
return view('contents.service.index', $services);
}
・if( isset($service['category']))
ifを使うのは対象の値の存在確認のみ。
・$services[$service['category']][]
キー名はテキストでベタ打ちせず、$service['category'
で動的に指定する。