Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【Laravel】繰り返し処理は@includeを使う。PHPはビューではなくコントローラに記述する(リファクタリング)

リファクタリングの個人メモです。

  • ビューの中に繰り返し処理を記述している場合は、処理を別ファイルに切り出し、@includeで呼び出す

  • PHPの処理はビューの中に書かず、コントローラで渡す(他でも使う処理の場合は自作のヘルパー関数を作って渡す)

リファクタリング事例

リファクタリング前のコード

以下のように同じコードが繰り返されている処理をリファクタリングする。

phones.balde.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.blade.php
<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

リファクタリングなし

.blade.php
          @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

.blade.php
        @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'で動的に指定する。

yuta-38
メモとして活用してます
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away