CakePHP3で一覧画面表示の実装を共通化する方法
index.ctpでよく見る一覧画面の実装
例)ユーザーの一覧画面
<table>
<thead>
<tr>
<th><?= $this->Paginator->sort('id') ?></th>
<th><?= $this->Paginator->sort('mame') ?></th>
<th><?= $this->Paginator->sort('sex') ?></th>
<th><?= $this->Paginator->sort('age') ?></th>
<th><?= $this->Paginator->sort('mail') ?></th>
<th><?= $this->Paginator->sort('tel') ?></th>
<th><?= __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?= $user->id ?></td>
<td><?= $user->name ?></td>
<td><?= $user->sex ?></td>
<td><?= $user->age ?></td>
<td><?= $user->mail ?></td>
<td><?= $user->tel ?></td>
<td><?= $this->Html->link(__('Edit'), ['action' => 'edit', $user->id]) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
という感じで他のindex画面も同じように作っていくわけですが、書いていくのが面倒です・・・
Bakeで楽はできるけども、コード量が増えるということはバグが増えるということで極力書きたくないもの。
というわけで良い方法がないか考えてみました。
検討したポイントとしては3点
-
共通化
したい -
<table>
特に、<tr><td>
タグを書きたくない - 表示項目(テーブルのカラム名)を
index.ctp
に書きたくない
検討した結果の実装コード
表示項目をコントローラーに記述
src/Controller/UsersController.ctp
namespace App\Controller;
use App\Controller\AppController;
use Cake\Collection\Collection;
class UsersController extends AppController
{
/*
* ヘッダー(この項目が一覧として表示される)
*/
public $tableHeader = [
'id',
'name',
'sex',
'age',
'mail',
'tel',
];
public function index()
{
$users = $this->paginate($this->Users);
$this->set(compact('users'));
$this->set('_serialize', ['users']);
$seedHeader = new Collection($this->tableHeader);
$this->set('seedHeader', $seedHeader);
}
表示項目を毎回を書きたくないのでControllerに表示項目を記述してtemplate側に渡すことにする
table部分をElement化
src/Template/Elememt/default_table.ctp
<table>
<thead>
<?php
$contentsHeader = [];
$contentsHeader[] = __('Actions');
$contentsHeader = array_merge($contentsHeader, $seedHeader->map(function ($header) {
return $this->Paginator->sort($header);
})->toArray());
?>
<?= $this->Html->tableHeaders($contentsHeader) ?>
</thead>
<tbody>
<?php
$contentsBody = $seedBody->map(function ($body) use ($seedHeader) {
$row = [];
$row[] = $this->Html->link(__('Edit'), ['controller' => $body->source(), 'action' => 'edit', $body->id]);
$row = array_merge($row, $seedHeader->map(function ($header) use ($body) {
return $body->{$header};
})->toArray());
return $row;
})->toArray();
?>
<?= $this->Html->tableCells($contentsBody); ?>
</tbody>
</table>
どの画面でも使えるようにしたいのでtable部分をelement化して外出し
CakePHP3から新しく入った $this->Html->tableHeaders()
、$this->Html->tableCells()
を利用して