FMCakeMixのUser Guide.pdfを参考に、CakePHP x FileMakerでWebアプリの作成方法を紹介する。FX.phpに添付されているFileMakerファイルをベースに、Paginationを使った一覧画面の実装方法を。5回目よりCakePHP, FMCakeMixの規約を紹介。前回までに規約にしたがったFileMakerデータベース、database.php、モデル、Booksの登録処理・一覧・詳細表示におけるコントローラ・ビューの作成を紹介した。今回は編集・削除処理といったほかの画面について触れていこう。
Hello, FMCakeMix! チュートリアル / 編集・削除におけるコントローラ、ビューの記述例
Booksテーブルの登録処理をFMCakeMixで実装した。今回は登録したレコードの編集、および削除処理を実装してみよう。今回作成するアクションは次の3つ。
- edit: レコードの編集画面を表示、および編集処理
- delete: レコードの削除処理。一覧(index)から実行。削除後、一覧に戻る
- delete_all: 全レコードの削除処理。一覧(index)から実行。削除後、一覧に戻る
まずは編集画面から実装してみよう。
booksコントローラ記述例(edit) - /app/controllers/books_controller.php
function edit($id = null)
{
if (!$id && empty($this->data))
{
$this->Session->setFlash(__('不正なidです', true));
}
if (!empty($this->data))
{
if ($this->Book->save($this->data))
{
$this->Session->setFlash(__('書籍情報を保存しました', true));
$this->redirect(array('action'=>'index'));
}
else
{
$this->Session->setFlash(__('書籍情報の保存に失敗しました', true));
}
}
if (empty($this->data))
{
$this->data = $this->Book->read(null, $id);
}
}
booksビュー記述例 - /app/view/books/edit.ctp
<h1>書籍編集</h1>
<?php
echo $form->create('Book', array('action' => 'edit'));
echo $form->input('title',array('label'=>'書籍名'));
echo $form->end('書籍情報を編集');
?>
<ul>
<li><?php echo $html->link('書籍情報詳細に戻る', array ( 'controller' => 'books', 'action' => 'view', 'id' => $this->data['Book']['id'] ) ); ?></li>
</ul>
詳細画面と同様、いったんread()を使用してレコード情報を取得。フォームから入力内容が送信され、$this->dataが空欄でなければその内容をsave()し、保存をおこなう。保存に成功した場合は、setFlash()でメッセージを埋め込み、redirect()で一覧画面(index)にリダイレクトさせるように。
続けて削除処理の実装だ。
booksコントローラ記述例(delete) - /app/controllers/books_controller.php
function delete($id=null)
{
$this->Book->find
(
'first',
array
(
'conditions' => array
(
'id' => $id
),
'recursive' => 0
)
);
if ($this->Book->del())
{
$this->Session->setFlash(__('書籍情報を削除しました', true));
$this->redirect(array('action'=>'index'));
}
else
{
$this->Session->setFlash(__('書籍情報の削除に失敗しました', true));
$this->redirect(array('action'=>'view', 'id'=>$id));
}
}
このアクションは画面を表示する必要がないので、ビューは作成しない。
コントローラの修正が終わったら、詳細画面から編集と削除をおこなえるように、view.ctpに修正をおこなう。
booksビュー記述例 - /app/view/books/view.ctp
<h1>書籍詳細</h1>
<table cellpadding="0" cellspacing="0">
<tr>
<th>
Id
</th> <td>
<?php echo h($book['Book']['id']); ?>
</td>
</tr>
<tr>
<th>
Title
</th>
<td>
<?php echo h($book['Book']['title']); ?>
</td>
</tr>
<tr>
<th>
Author
</th>
<td>
</td>
</tr>
<tr>
<th>
Created
</th>
<td>
<?php echo h(date('Y/m/d H:i:s', $book['Book']['created'])); ?>
</td>
</tr>
<tr>
<th>
Modified
</th>
<td>
<?php echo h(date('Y/m/d H:i:s', $book['Book']['modified'])); ?>
</td>
</tr>
</table>
<ul>
<li><?php echo $html->link('書籍情報を編集', array ( 'controller' => 'books', 'action' => 'edit', 'id' => $book['Book']['id'] ) ); ?></li>
<li><?php echo $html->link('書籍情報を削除', array ( 'controller' => 'books', 'action' => 'delete', 'id' => $book['Book']['id'] ), null, '「' . $book['Book']['title'] . '」を削除してもよろしいですか?'); ?></li>
<li><?php echo $html->link('書籍情報一覧', array ( 'controller' => 'books', 'action' => 'index' ) ); ?></li>
</ul>
削除処理では最初に-recidを渡して削除するのではなく、いったんidフィールドの値で検索(find)ををおこなっている。その後、該当したレコードをdelete()してレコードの物理削除をおこなう。また、前回紹介した$confirmMessageで削除前に確認のメッセージを表示するようにしている。
ここまで追加・修正をおこなった画面をWebブラウザで表示してみよう。
CakePHP x FileMakerでのdeleteAll代替手段
このコラムでも何回か述べてきたとおり、FileMakerのWeb公開機能には次の制約がある。
- 編集処理(-edit)と削除処理(-delete)には、レコードID(-recid)の指定が必須
- 上記2処理で操作できるレコードは基本的に1つ
ポータル内に操作したいレコードを参照させることで複数のレコードを編集・削除することも可能だが、操作したいポータル内のレコードIDも要求され、どちらもかなりトリッキー実装となる。PHP側で複数のレコードIDを配列に持たせてループで処理することも可能だが、FileMaker Serverに大きな負荷がかかってしまう。
CakePHP(FMCakeMix)のdeleteAllを実現したい場合は、FileMakerスクリプトで「全レコードを表示→対象レコードを削除」を作成しておき、それをWeb経由で実行するのがベストだろう。開発時間、処理時間、サーバにかかる負荷3点をカバーできる実装方法だ。
まずはFileMaker側にスクリプトを作成しておく。名前は「deleteAll」とした。
FileMakerスクリプト - deleteAll
全レコードを表示
対象レコード削除 [ ダイアログなし ]
スクリプト内に作業するレイアウトを明示しないことで、Web上からレコードを削除できるテーブルを指定できるようにしている。続いてコントローラ側で、このFileMakerスクリプトを実行するアクションを定義する。
booksコントローラ記述例(delete_all) - /app/controllers/books_controller.php
function delete_all()
{
$this->Book->find
(
'first',
array
(
'conditions' => array
(
'-script' => 'deleteAll'
),
'recursive' => 0
)
);
$this->Session->setFlash(__('書籍情報を削除しました', true));
$this->redirect(array('action'=>'index'));
}
検索条件とおなじ要領でconditionsの-scriptに対してスクリプト名を定義し、モデルやコントローラで指定しているレイアウト上でスクリプトが動作するように。このアクションを一覧画面から実行できるように、/app/views/books/index.ctpにリンクを追加する。
booksビュー記述例 - /app/view/books/index.ctp
<h1>書籍一覧</h1>
<p style="text-align: center">
<?php
echo $paginator->counter
(
array
(
'format' => __('%page% / %pages% ページ, <span class="foundCount">%count%</span>件中、%start% - %end% 件目を表示', true)
)
);
echo '<br>';
echo $paginator->prev('<< '.__('前のページ', true), array(), null, array('class'=>'disabled', 'tag' => 'span'));
echo ' | ' . $paginator->numbers() . ' | ';
echo $paginator->next(__('次のページ', true).' >>', array(), null, array('tag' => 'span', 'class' => 'disabled'));
?>
</p>
<table cellpadding="0" cellspacing="0">
<tr>
<th>
<?php echo $paginator->sort('Id' , 'id');?>
</th>
<th>
<?php echo $paginator->sort('Title' , 'title');?>
</th>
<th>
<?php echo $paginator->sort('Author', 'author');?>
</th>
<th>
<?php echo $paginator->sort('Created', 'created');?>
</th>
<th>
<?php echo $paginator->sort('Modified', 'modified');?>
</th>
</tr>
<?php
$i = 0;
foreach ($books as $book)
{
?>
<tr>
<td>
<?php
echo $html->link
(
h($book['Book']['id']),
array
(
'controller' => 'books',
'action' => 'view',
'id' => $book['Book']['id']
)
); ?>
</td>
<td>
<?php echo h($book['Book']['title']); ?>
</td>
<td>
</td>
<td>
<?php echo h(date('Y/m/d H:i:s', $book['Book']['created'])); ?>
</td>
<td>
<?php echo h(date('Y/m/d H:i:s', $book['Book']['modified'])); ?>
</td>
</tr>
<?php
}
?>
</table>
<p style="text-align: center">
<?php
echo $paginator->counter
(
array
(
'format' => __('%page% / %pages% ページ, <span class="foundCount">%count%</span>件中、%start% - %end% 件目を表示', true)
)
);
echo '<br>';
echo $paginator->prev('<< '.__('前のページ', true), array(), null, array('class'=>'disabled', 'tag' => 'span'));
echo ' | ' . $paginator->numbers() . ' | ';
echo $paginator->next(__('次のページ', true).' >>', array(), null, array('tag' => 'span', 'class' => 'disabled'));
?>
</p>
<ul>
<li><?php echo $html->link('書籍情報を登録する', array ( 'controller' => 'books', 'action' => 'add') ); ?></li>
<li><?php echo $html->link('書籍情報を全削除', array ( 'controller' => 'books', 'action' => 'delete_all' ), null, '書籍情報をすべて削除します。よろしいですか?'); ?></li>
</ul>
一覧画面(books/index)でdeleteAllの動作を確認する。
次回、著者情報(Author)の画面や関連付けについて紹介する。