【PHP】Laravelのbladeテンプレートを理解する。

個人用メモです。
以下のコードの各行が何をしているのかを理解する。

```php:table.blade.php
<div class="p-article__table-wrap">
<table class="p-article__table {{ $classes }}">
  @if ($table->getColgroup())
  <colgroup>
    @if ($table->getColgroup())
      @foreach ($table->getColgroup()->getCols() as $col)
        <col width="{{ $col->getWidth() ?: 'auto'}}">
      @endforeach
    @endif
  </colgroup>
  @endif

  @include('mrgrpcv::items.items', ['items' => $items])
</table>
</div>
```

##目次

1. [bladeとは？](#bladeとは)
2. [bladeのメリット](#bladeのメリット)
3. [`@`アットマークの意味](#アットマークの意味)
4. [`$`の意味](#の意味)
5. [二重波カッコ`{{ }}`の意味](#二重波カッコ-の意味)
6. [コメントアウト](#コメントアウト)
7. [`@foreach`と`@endforeach`](#foreachとendforeach)
8. [アロー「->」の意味](#アロー-の意味)
9. [ダブルアロー「=>」の意味](#ダブルアローの意味)
10. [`?:`の意味（三項演算子の省略形）](#の意味三項演算子の省略形)
11. [`@include`の意味](#includeの意味)
12. [名前空間](#名前空間)
13. [`$classes`の中身](#classesの中身)
14. [`$class`の元となる`$itemService`がどこからきているか？](#classの元となるitemserviceがどこからきているか)
15. [`@inject`の意味](#injectの意味)



<br>

##bladeとは？
ファイルの拡張子は`.blade.php`。
bladeと呼びLaravel特有のファイル。**ビューの作成に使われるテンプレート**。

bladeファイルの記述内容がブラウザに表示される。（Vue.jsの`.vue`ファイルや`template`に該当する）

ビュー（表示）のためのファイルのため、**bladeビュー**と呼ばれる。



###bladeのメリット
基本的な書き方はHTMLと同じ。
HTMLタグと併せてPHPも使うことができる。

`{{ $classes }}`や`@if ($table->getColgroup())`など。

HTMLの中で変数を使用したり、if文やfor文などを埋め込むことができる。


<br>
##`@`アットマークの意味
`@if`や`@foreach`などのアットマークはこれがphpの処理ということを示している。

blade.phpファイル特有の書き方で、HTMLの間にif文などのPHPを使いたい場合に、冒頭に`@`をつける。

`@if`や`@foreach`などアットマークがついた指示を**ディレクティブと呼ぶ**

>ディレクティブとは？
directiveは指令の意味。.blade.phpファイル内に@から始まるコードがあれば、PHPに変換せよという指令になる。




<br>
##`$`の意味
**変数**を表す。`$classes`や`$table`など。これらの変数は親ファイルから渡される。

親ファイルの中でこのtable.blade.phpを`include`した際に引数でデータを渡している。

```php:親ファイル(item.blade.php)
@switch($itemService->getItemType($item->getType()))
  @case('table')
    @include('mrgrpcv::items.table', ['table' => $item->getTable(), 'items' => $item->getItems(), 'id' => $item->getId(), 'classes' => $classes])
    @break
@endswitch
```

```php:@include抜粋
@include('mrgrpcv::items.table', [
  'table' => $item->getTable(), 
  'items' => $item->getItems(), 
  'id' => $item->getId(), 
  'classes' => $classes
  ]
)
```

・`mrgrpcv::items.table`
名前空間mrgrpcvのitemsフォルダのtable.blade.phpファイルを呼び出し。

・`'table' => $item->getTable()`
別のビューを呼び出したときに渡したデータ。
指定したファイルの中で、`$table`という変数名でデータ`$item->getTable()`が利用できるようになる。



<br>
##二重波カッコ`{{ }}`の意味
値を表示する。

**▼echoとの違い**
`{{ }}`ならタグが文字列として出力できる。JS勝手に実行されることなく安心。（クロスサイトスクリプティングの防止）

`echo`はタグをHTMLタグとして処理する。`<script>`で囲まれた変数が渡されればその内容を実行してしまう。。。

[tektektechさん](https://tektektech.com/laravel-double-braces/)の実例がわかりやすい。



###コメントアウト
`{{ }}`の記述はコメントアウトにも使われる。コメントアウトの場合は`--`でコメントを囲む。

`{{-- コメント --}}`


<br>
##`@if`と`@endif`
文の頭に`@`をつけると、HTML内でその文を使える。

処理内容は改行して記述。
終了するときは、`@end文の名前`とする。

```php:
@if(条件)
  処理
@else if(条件)
  処理
@else 
  処理
@endif
```

条件がtrueの場合に処理を実行。


<br>
##`@foreach`と`@endforeach`
考え方は`@if`と同じ。

`foreach( 配列 as 変数):　処理`
配列の要素を一つづつ取り出し、変数に格納する。処理の中でその変数を使える。


<br>
##アロー「->」の意味
インスタンスのもつプロパティやメソッドにアクセスしている。
・`インスタンス->プロパティ/メソッド`

・**▼例**
`$table->getColgroup()`

インスタンスが格納された変数`$table`のメソッド`getColgroup`を実行した戻り値が返る。


<br>
##ダブルアロー「=>」の意味
連想配列のキーと値を結びつける。`array()`または`[ ]`の中で使用することで連想配列を作成できる。

`$arr = ['item' => 'a']`

```php:
$items = "a";

#連想配列の作成
$arr = ['items' => $items];

#確認
var_export($arr);
array (
  'items' => 'a',
)
```


<br>
##`?:`の意味（三項演算子の省略形）
三項演算子の省略形。trueの場合に条件式の値をそのまま用いる。

**▼通常の三項演算子**
・`条件式 ? trueの場合の処理 : falseの場合の処理`

**▼省略形**
・`条件式 ?: falseの場合の処理`
　┗ trueの場合は条件式の値をそのまま用いる。

<br>

```php:
<col width="{{ $col->getWidth() ?: 'auto'}}">
```


```php:元の処理
@if ($col->getWidth())
  {{ $col->getWidth() }}
@else 
  auto
@endif
```



<br>
##`@include`の意味
`include('ファイルパス')`で指定した外部ファイルを読み込む。

第２引数は指定したファイルにデータを渡している。

・`@include('ファイル名', '変数名' =>  渡すデータ)`
　┗ 変数名に`$`は不要。
　┗ 指定ファイルで渡されたデータを使う場合は`$変数名`とする。


```php:
@include('mrgrpcv::items.items', ['items' => $items])
```

つまり、指定したファイル`items.blade.php`内で、`$items`を使うと、このファイルで定義した`$items`を使うことができる。




###名前空間
ファイル名で`mrgrpcv::items.items`を指定している。
**ダブルコロンは名前空間**

これを外部のビューとして扱うためには、サービスプロバイダーのファイル（xxxServiceProvider.php）に、`loadViewsForm`メソッドと`publishes`メソッドを使ってファイルの場所を登録する。


```php:ServiceProvider.php
public function boot()
    {   
        $this->loadViewsFrom(__DIR__.'/../../views', 'mrgrpcv');
        $this->publishes([
            __DIR__.'/../../views' => resource_path('views/vendor/mrgrpcv'),
        ], 'mrgrpcv');
    }
```

例えば上記のように設定すると`/views`フォルダに入っているファイルを`mrgrpcv::`という名前空間で指定することができる。

後ろのファイル名は`.blade.php`が省略された形。
ドットで繋がる場合はフォルダの中に入ったファイルを指す。

よって、`mrgrpcv::items.items`は、`../../views/items/items.blade.php`を指す。

>（参考）https://readouble.com/laravel/5.dev/ja/packages.html


<br>
##`$classes`の中身
`{{ $classes }}`で呼び出されている`$class`も親ファイルから渡されている。

item.blade.phpファイルが親にあたり、その中で`@include`により`table.blade.php`にデータが渡されている。

`$classes`はこの元ファイルの情報に定義されている。

```php:item.blade.php
@inject('itemService', 'LaravelMicresArticle\Services\ItemService')

@php
  $classes = $itemService->getClasses($item);
@endphp


@include('mrgrpcv::items.table', [
  'table' => $item->getTable(), 
  'items' => $item->getItems(), 
  'id' => $item->getId(), 
  'classes' => $classes
  ]
)
```

<br>
###`$class`の元となる`$itemService`がどこからきているか？

`$class`は以下のように定義されている。

・`$classes = $itemService->getClasses($item);`

`$itemService`インスタンスのメソッド`getClasses($item)`で呼び出した値が入っている。


この`$itemService`は`@inject`で渡されたインスタンスが格納された変数となっている。

```php:
@inject('itemService', 'LaravelMicresArticle\Services\ItemService')
```

<br>
###`@inject`の意味
`@inject`ディレクティブを使うと、指定したクラスから生成したインスタンスを格納した変数を使えるようになる。

`@inject('変数名', 'クラス名')`

ここでクラス名は`'LaravelMicresArticle\Services\ItemService'`

冒頭の`LaravelMicresArticle\Services\`はnamespace。`ItemService`がクラス名になる。

以下ファイルのclassを呼び出している。

```php:ItemService.php
<?php

namespace LaravelMicresArticle\Services;
use Illuminate\Support\Facades\Blade;

class ItemService
{
    public function getClasses(object $item):string
    {
        $classes = 'article-item';
        if(!empty($item->getTypeDetails())){
            $classes .= ' ' . $item->getTypeDetails();
        }elseif($item->getType() == 1){
            $classes .= ' custom';
        }elseif($item->getType() == 99){
            $classes .= ' items';
        }
        if(method_exists($item, 'getBoxType')) $classes .= ' ' . $item->getBoxType();
        foreach($item->getClasses() as $class){
            if(method_exists($item, 'getClasses')) $classes .= ' ' . $class;
        }
        
        return $classes;
    }
}
```