ユーザーを認証するだけならAuthコンポーネントで十分なのですが、アクセスしてきたユーザーを個別に管理するにはAclコンポーネントが不可欠です。今日はそのAcl(アクセス制御リスト)コンポーネントで、アクセス管理を行いたいと思います。
1. CakePHPのACLは、ACO(Access Controll Object)とARO(Access Request Object)という2つの概念で、管理されています。
2. 簡単に言えば、ACOが利用される側、AROが利用する側、つまり、ACOは、アクションやモデル、特定のフォルダやページを指し、AROは、ユーザーやユーザーグループを指します。arosテーブルにユーザー情報、acosテーブルにコントローラ情報、そしてaros_acosテーブルでその両方のアクセス情報を管理しているのです。
設定情報ファイルの修正
3. Aclコンポーネントを利用するには、Aclの設定情報をセットする必要があります。configファイルを下記の2行が有効になっているかどうかを確認して下さい(228行目あたり)。
app/Config/core.php
Configure::write('Acl.classname', 'DbAcl'); Configure::write('Acl.database', 'default');
セッションの設定
4. Atuhコンポーネントのところでもやりましたが、ログイン関係には、セッションが必要ですので、セッション関係の設定を下記に記述しておきます。core.phpの175行目あたりです。
Configure::write('Session', array( 'defaults' => 'database', 'cookie' => 'SID', //セッションの保持時間(秒数) 'timeout' => 86400, ));
5. データベーステーブルを下記のように作成します。
CREATE TABLE IF NOT EXISTS `cake_sessions` ( `id` varchar(255) NOT NULL DEFAULT '', `data` text NOT NULL, `expires` int(11) DEFAULT NULL, PRIMARY KEY (`id`) )
テーブルの作成
6. ACLを構築するためには、usersテーブルとgroupsテーブルが必要になります。usersテーブルは以前(usernameと passwordが含まれているテーブル)のテーブルでも構わないのですが、groupsテーブルとアソシエーションで繋ぐためにgroup_idも必要 です。両方とも新規作成したいと思います。
7. CakePHPのCookbookのチュートリアルに沿って作成していきたいと思います。チュートリアル記載されている下記のSQL文で4つのテーブルを作成します。
CREATE TABLE users ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) NOT NULL UNIQUE, password CHAR(40) NOT NULL, group_id INT(11) NOT NULL, created DATETIME, modified DATETIME ); CREATE TABLE groups ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, created DATETIME, modified DATETIME ); CREATE TABLE posts ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id INT(11) NOT NULL, title VARCHAR(255) NOT NULL, body TEXT, created DATETIME, modified DATETIME ); CREATE TABLE widgets ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, part_no VARCHAR(12), quantity INT(11) );
BakeでMVCの一括作成
8. 次にMVCの各ファイルの作成ですが、bakeだと簡単に作成できますので、bakeで4つのテーブルのモデル、コントローラ、ビューを作成します。コマンドプロンプトを起動したら、bakeのフォルダに移動して、『cake bake all』と入力します。
cd c:\xammp\htdocs\cakephp\app cake bake all
10. ずらずらと文字が表示されて、『Bake All complete』が表示され、元のコマンドプロンプトの画面に戻りました。再度『cake bake all』と入力してEnterします。
11. 同様な操作を続けて残り3つのMVCを作成します。
Authを追加する準備
12. 次にログインとログアウト用のアクションをUsesrControllerに追加します。
app/Controller/UsersController.php
//ログインログアウトアクションの追加 public function login() { //POST送信なら if ($this->request->is('post')) { //ログインOKなら if ($this->Auth->login()) { //Auth指定のリダイレクト先へ移動 $this->redirect($this->Auth->redirect()); } else { //ログインNGなら $this->Session->setFlash('ユーザー名かパスワードが間違っています'); } } } public function logout() { //ここは、今は空にしておいてください }
13. そしてログイン用のビューファイルを作成します。
app/View/Users/login.ctp
<?php echo $this->Form->create('User', array('action' => 'login')); echo $this->Form->inputs(array( 'legend' => __('ログイン'), 'username', 'password' )); echo $this->Form->end('ログイン');
14. 次にパスワードをハッシュ化するためにUserモデルに下記の記述を追加するのですが、下記のコードのままでは、エラーが発生します(私の使用しているバージョンが2.2だからかもしれません)。
app/Model/User.php
public function beforeSave() { $this->data['User']['password'] = AuthComponent::password($this->data['User']['password']); return true; }
15. そこで、beforeSaveの引数に配列を指定することで、エラーが解消できます。
app/Model/User.php
public function beforeSave($options=array()) { $this->data['User']['password'] = AuthComponent::password($this->data['User']['password']); return true; }
AppControllerの修正
16. コントローラ全体に認証とACLを行うためにAppControllerを修正します。
app/Controller/AppController.php
class AppController extends Controller { //使用するコンポーネントの指定 public $components = array( 'Acl', 'Auth' => array( 'authorize' => array( 'Actions' => array('actionPath' => 'controllers') ) ), 'Session' ); //使用ヘルパーの指定 public $helpers = array('Html', 'Form', 'Session'); public function beforeFilter() { //ログインページの指定 $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); //ログアウトページの指定 $this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login'); //ログイン後の移動先の指定 $this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'index'); } }
一時的にAuthコンポーネントの無効化
17. このままの状態では、Authコンポーネントが全てのアクセスを拒否してユーザーの登録さえ出来ません。そこで、Atuhコンポーネントを一時的に無効化するために下記のコードをUsersControllerとGroupsControllerの両方に記述しておきます。
function beforeFilter() { parent::beforeFilter(); $this->Auth->allow('*'); }
ACL用データベーステーブルの作成
18. さてここでやっとACL用テーブル(aros、acos、aros_acos)を作成します。これもシェルコマンドで作成するとほんの数秒で作成することが出来ます。コマンドプロンプトから下記のコードを入力します。 ※DbAclのDとAは大文字で入力して下さい。
cake schema create DbAcl
19. テーブルを削除しますかと尋ねてきます(まだテーブルはありませんが)ので、yと入力してEnterします。そして、テーブルを作成しますかと尋ねてきますので、yと入力してEnterします。
20. 元のコマンドプロンプトに戻ったらテーブルが出来上がっているはずです。phpMyAdiminで見てみると、3つのテーブルが作成されているのが分かります。
21. シェルが使えない状況の時のために下記にSQL文を記述しておきます。
CREATE TABLE acos ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INTEGER(10) DEFAULT NULL, model VARCHAR(255) DEFAULT '', foreign_key INTEGER(10) UNSIGNED DEFAULT NULL, alias VARCHAR(255) DEFAULT '', lft INTEGER(10) DEFAULT NULL, rght INTEGER(10) DEFAULT NULL, PRIMARY KEY (id) ); CREATE TABLE aros_acos ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, aro_id INTEGER(10) UNSIGNED NOT NULL, aco_id INTEGER(10) UNSIGNED NOT NULL, _create CHAR(2) NOT NULL DEFAULT 0, _read CHAR(2) NOT NULL DEFAULT 0, _update CHAR(2) NOT NULL DEFAULT 0, _delete CHAR(2) NOT NULL DEFAULT 0, PRIMARY KEY(id) ); CREATE TABLE aros ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INTEGER(10) DEFAULT NULL, model VARCHAR(255) DEFAULT '', foreign_key INTEGER(10) UNSIGNED DEFAULT NULL, alias VARCHAR(255) DEFAULT '', lft INTEGER(10) DEFAULT NULL, rght INTEGER(10) DEFAULT NULL, PRIMARY KEY (id) );
AuthとACLを関連づける
22. AuthとACLを関連づけるためにAclbehaviorを使用します。このAclbehaviorを使用するのに、モデル内でparentNode()を実行する必要があります。Userモデルと、Groupモデルに下記のコードを追加します。
app/Model/User.php
class User extends Model { public $name = 'User'; public $belongsTo = array('Group'); public $actsAs = array('Acl' => array('type' => 'requester')); public function parentNode() { if (!$this->id && empty($this->data)) { return null; } if (isset($this->data['User']['group_id'])) { $groupId = $this->data['User']['group_id']; } else { $groupId = $this->field('group_id'); } if (!$groupId) { return null; } else { return array('Group' => array('id' => $groupId)); } } }
app/Model/Group.php
class Group extends Model { public $actsAs = array('Acl' => array('type' => 'requester')); public function parentNode() { return null; } }
23. ただ、BakeでUserモデルを作成した場合、既にpublic $belongsTo=array('Group');が作成されている場合があります。下記は重複時のエラーです。
24. そのときは、どちらかのアソシエーションを削除して下さい。
AROデータの作成
25. それでは、いよいよデータを入力したいと思います。まず、グループを追加します。ブラウザから直接GroupsControllerにアクセスします。adminsと入力してSubmitボタンをクリックします。
http://localhost/cakephp/groups/add
26. データが保存されました。New Groupsをクリックし、続けて『managers』と『users』を作成します。
27. とりあえず、グループを3つほど作成したので、次はNew Userをクリックして、ユーザーも各グループごとに作成します。
28. phpMyAdminでarosテーブルを確認してみましょう。下記のように登録されています。lftとrghtの数値はAclが自動的に作成しています。
ACOデータの作成
29. ACOのデータを作成するにあたり、まず、トップレベルACOを作成します。このトップレベルのACOを作成することにより、アプリケーション全体に対してアクセス権を設定することが出来ます。これもコマンドプロンプトで作成します。
cake acl create aco root controllers
30. phpMyAdminで確認するとcontrollersが作成されているのが分かります。
ACOを作成するツール
31. 全てのコントローラとアクションを一つ一つ登録するのはとても面倒です。AclExtrasというプラグインを利用すると全てのACOを簡単に生成することが出来ます。githubの下記のアドレスからダウンロードします。
https://github.com/markstory/acl_extras/zipball/2.0
32. 解凍したフォルダ名をAclExtrasに変更して、app/Pluginフォルダにコピーします。
33. bootstrapファイルで今保存したAclExtrasプラグインを有効にします。
app/Config/bootstrap.php
CakePlugin::load('AclExtras');
34. そしてコマンドプロンプトで下記のコマンドを入力します。
cake AclExtras.AclExtras aco_sync
35. 『Aco Update Complete』と表示されたら、ACOは完成です。phpMyAdminで確認してみましょう。全てのコントローラ及びアクションが登録されています。
簡易Aclアプリケーションの作成
36. Acl管理用のPluginACLというかなり便利そうなプラグインをネットで紹介していたので、インストールしてみたのですが、エラーが発生して先に進めませんでした(私の設定ミスかCakePHPのバージョン違いのどちらかだと思います)。
37. 仕方が無いので、簡単なAcl管理用のアプリケーションを作成することにしました。UsersController.phpに下記のコードを追加します。
app/Controller/UsersController.php
//ACL作成用のアクション public function acl_add($id=null){ if($this->request->is('post')){ $aro=$this->User->Group; $aro->id=$this->request->data['Acl']['group_id']; $aco=$this->request->data['Acl']['aco']; $create=$this->request->data['Acl']['create']; $read=$this->request->data['Acl']['read']; $update=$this->request->data['Acl']['update']; $delete=$this->request->data['Acl']['delete']; //パーミッションの設定 $this->Acl->$create($aro,$aco,'create'); $this->Acl->$read($aro,$aco,'read'); $this->Acl->$update($aro,$aco,'update'); $this->Acl->$delete($aro,$aco,'delete'); //リストAclに移動 $this->redirect('../arosacos/index'); } $groups = $this->User->Group->find('list'); $this->set(compact('groups')); } //ACL編集用のアクション public function acl_edit($id=null){ if($this->request->is('post')){ $aro=$this->User->Group; $aro->id=$this->request->data['ArosAco']['aro_id']; $aco=$this->request->data['ArosAco']['aco_id']; $create=$this->request->data['ArosAco']['create']; $read=$this->request->data['ArosAco']['read']; $update=$this->request->data['ArosAco']['update']; $delete=$this->request->data['ArosAco']['delete']; //パーミッションの設定 $this->Acl->$create($aro,$aco,'create'); $this->Acl->$read($aro,$aco,'read'); $this->Acl->$update($aro,$aco,'update'); $this->Acl->$delete($aro,$aco,'delete'); //リストAclに移動 $this->redirect('../arosacos/index'); } $groups = $this->User->Group->find('list'); $this->set(compact('groups')); }
38. aros_acosテーブルを操作するためのコントローラを作成します。
app/Controller/ArosAcosController.php
<?php App::uses('AppController', 'Controller'); class ArosAcosController extends AppController { //Aclを作成したら、下記の4行は削除します。 function beforeFilter() { parent::beforeFilter(); $this->Auth->allow('*'); } public function index() { $this->ArosAco->recursive = 0; $this->set('arosAcos', $this->paginate()); } public function add() { $aros = $this->ArosAco->Aro->find('list'); $acos = $this->ArosAco->Aco->find('list',array('fields'=>array('alias','alias'))); $this->set(compact('aros', 'acos')); } public function edit($id = null) { $this->ArosAco->id = $id; $this->request->data = $this->ArosAco->read(null, $id); $aros = $this->ArosAco->Aro->find('list'); $acos = $this->ArosAco->Aco->find('list',array('fields'=>array('alias','alias'))); $this->set(compact('aros', 'acos')); } public function view($id = null) { $this->ArosAco->id = $id; if (!$this->ArosAco->exists()) { throw new NotFoundException(__('Invalid user')); } $this->set('arosAco', $this->ArosAco->read(null, $id)); } }
39. モデルも作成します。bakeで作成すれば、Validationとかも作成してくれますが、今回は特に必要ないので、必要最低限(アソシエーション)しか作成していません。
app/Model/ArosAco.php
<?php App::uses('AppModel', 'Model'); class ArosAco extends AppModel { public $belongsTo = array('Aro','Aco'); }
40. 4つのビュー(index,add,edit,view)を作成します。ここでデータを削除するとAclがおかしくなりますので、deleteアクションは作成しません。
app/View/ArosAco/index.ctp
<div class="arosAcos index"> <h2><?php echo __('リストAcl'); ?></h2> <table cellpadding="0" cellspacing="0"> <tr> <th><?php echo $this->Paginator->sort('id'); ?></th> <th><?php echo $this->Paginator->sort('aro_id'); ?></th> <th><?php echo $this->Paginator->sort('aco_id'); ?></th> <th><?php echo $this->Paginator->sort('AcoAlias'); ?></th> <th><?php echo $this->Paginator->sort('作成'); ?></th> <th><?php echo $this->Paginator->sort('読込'); ?></th> <th><?php echo $this->Paginator->sort('更新'); ?></th> <th><?php echo $this->Paginator->sort('削除'); ?></th> <th class="actions"><?php echo __('Actions'); ?></th> </tr> <?php foreach ($arosAcos as $arosAco): ?> <tr> <td><?php echo h($arosAco['ArosAco']['id']); ?></td> <td><?php echo h($arosAco['Aro']['id']); ?></td> <td><?php echo h($arosAco['Aco']['id']); ?></td> <td><?php echo h($arosAco['Aco']['alias']); ?></td> <td><?php echo h($arosAco['ArosAco']['_create']); ?></td> <td><?php echo h($arosAco['ArosAco']['_read']); ?></td> <td><?php echo h($arosAco['ArosAco']['_update']); ?></td> <td><?php echo h($arosAco['ArosAco']['_delete']); ?></td> <td class="actions"> <?php echo $this->Html->link(__('Edit'), array('action' => 'edit', $arosAco['ArosAco']['id'])); ?> <?php echo $this->Html->link(__('View'), array('action' => 'view', $arosAco['ArosAco']['id'])); ?> </td> </tr> <?php endforeach; ?> </table> <p> <?php echo $this->Paginator->counter(array( 'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}') )); ?> </p> <div class="paging"> <?php echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled')); echo $this->Paginator->numbers(array('separator' => '')); echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled')); ?> </div> </div> <div class="actions"> <h3><?php echo __('Actions'); ?></h3> <ul> <li><?php echo $this->Html->link(__('新規Acl'), array('controller'=>'Users','action' => 'acl_add')); ?></li> <li><?php echo $this->Html->link(__('Userリスト'), array('controller' => 'Users', 'action' => 'index')); ?> </li> <li><?php echo $this->Html->link(__('Groupリスト'), array('controller' => 'Groups', 'action' => 'index')); ?> </li> </ul> </div>
app/View/ArosAco/add.ctp
<div class="arosAcos form"> <?php echo $this->Form->create('ArosAco',array('action'=>'../users/index','method'=>'post')); ?> <fieldset> <legend><?php echo __('新規Acl'); ?></legend> <?php echo $this->Form->input('aro_id'); echo $this->Form->input('aco_id'); echo $this->Form->radio('create',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'作成','value'=>'deny')); echo $this->Form->radio('read',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'読み込み','value'=>'deny')); echo $this->Form->radio('update',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'更新','value'=>'deny')); echo $this->Form->radio('delete',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'削除','value'=>'deny')); ?> </fieldset> <?php echo $this->Form->end(__('Submit')); ?> </div> <div class="actions"> <h3><?php echo __('Actions'); ?></h3> <ul> <li><?php echo $this->Html->link(__('リストAcl'), array('action' => 'index')); ?></li> <li><?php echo $this->Html->link(__('リストGroup'), array('controller' => 'groups', 'action' => 'index')); ?> </li> <li><?php echo $this->Html->link(__('リストUser'), array('controller' => 'users', 'action' => 'index')); ?> </li> </ul> </div>
app/View/ArosAco/edit.ctp
<div class="arosAcos form"> <?php echo $this->Form->create('ArosAco',array('action'=>'../users/acl_edit')); ?> <fieldset> <legend><?php echo __("Acl編集(ID:".$this->request->data['ArosAco']['id'].")"); ?></legend> <?php echo $this->Form->hidden('id'); echo $this->Form->hidden('aro_id',array('value'=>$this->request->data['ArosAco']['aro_id'])); echo $this->Form->hidden('aco_id',array('value'=>$this->request->data['Aco']['alias'])); echo $this->Form->radio('create',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'作成','value'=>$this->request->data['ArosAco']['_create']==1 ? 'allow' : 'deny')); echo $this->Form->radio('read',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'読み込み','value'=>$this->request->data['ArosAco']['_read']==1 ? 'allow' : 'deny')); echo $this->Form->radio('update',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'更新','value'=>$this->request->data['ArosAco']['_update']==1 ? 'allow' : 'deny')); echo $this->Form->radio('delete',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'削除','value'=>$this->request->data['ArosAco']['_delete']==1 ? 'allow' : 'deny')); ?> </fieldset> <?php echo $this->Form->end(__('Submit')); ?> </div> <div class="actions"> <h3><?php echo __('Actions'); ?></h3> <ul> <li><?php echo $this->Html->link(__('リストAcl'), array('action' => 'index')); ?></li> <li><?php echo $this->Html->link(__('リストGroups'), array('controller' => 'groups', 'action' => 'index')); ?> </li> <li><?php echo $this->Html->link(__('リストUsers'), array('controller' => 'users', 'action' => 'index')); ?> </li> </ul> </div>
app/View/ArosAco/view.ctp
<div class="arosAcos view"> <?php //echo var_dump($arosAco);?> <h2><?php echo __('Aros Aco'); ?></h2> <dl> <dt><?php echo __('Id'); ?></dt> <dd> <?php echo h($arosAco['ArosAco']['id']); ?> </dd> <dt><?php echo __('Aro'); ?></dt> <dd> <?php echo h($arosAco['Aro']['id']); ?> </dd> <dt><?php echo __('Aco'); ?></dt> <dd> <?php echo h($arosAco['Aco']['id']); ?> </dd> <dt><?php echo __('Aco_parent'); ?></dt> <dd> <?php echo h($arosAco['Aco']['parent_id']); ?> </dd> <dt><?php echo __('Aco_alias'); ?></dt> <dd> <?php echo h($arosAco['Aco']['alias']); ?> </dd> <dt><?php echo __('作成'); ?></dt> <dd> <?php echo h($arosAco['ArosAco']['_create']); ?> </dd> <dt><?php echo __('読込'); ?></dt> <dd> <?php echo h($arosAco['ArosAco']['_read']); ?> </dd> <dt><?php echo __('更新'); ?></dt> <dd> <?php echo h($arosAco['ArosAco']['_update']); ?> </dd> <dt><?php echo __('削除'); ?></dt> <dd> <?php echo h($arosAco['ArosAco']['_delete']); ?> </dd> </dl> </div> <div class="actions"> <h3><?php echo __('Actions'); ?></h3> <ul> <li><?php echo $this->Html->link(__('編集Acl'), array('action' => 'edit', $arosAco['ArosAco']['id'])); ?> </li> <li><?php echo $this->Html->link(__('リストAcl'), array('action' => 'index')); ?> </li> <li><?php echo $this->Html->link(__('リストGroups'), array('controller' => 'groups', 'action' => 'index')); ?> </li> <li><?php echo $this->Html->link(__('リストUsers'), array('controller' => 'users', 'action' => 'index')); ?> </li> </ul> </div>
Acl(パーミッション)の設定
41. それでは、パーミッションを設定してみましょう。ブラウザで新規入力ページへ移動します。まず最初にトップレベルACOの『controllers』をadmins、managers、usersの各グループのパーミッションを設定します。
http://localhost/cakephp/users/acl_add
42. トップレベルのパーミッションを設定しましたので、ブラウザで確認してみます。『1』が許可、『-1』が禁止となっています。
43. トップレベル以下のパーミッションを作成するには、ACOに『/』で区切って入力します。例えば、トップレベルACOで作成更新を許可しているグループでも、特定のコントローラに関しては、『読込』以外は禁止することなどが設定できます。また、逆に許可することも出来ます。さらに細かく『/』で区切って、アクションごとに設定することも出来ます。
44. 下記のように登録されました。一応Editボタンでパーミッションの修正も出来るように作成しておきました。尚、このAclのデータに関しては、データベーステーブルを直接修正することは絶対にしないようにして下さい(Aclがおかしくなります)。
45. 最後に、UsersController.phpとGroupsController.php及び、ArosAcosController.phpに記述しておいた下記のコードは必ず削除するようにして下さい。
function beforeFilter() { parent::beforeFilter(); $this->Auth->allow('*'); }
これで、コントローラやアクションごとにアクセス管理をすることが出来るようになりました。本日は以上です。
ビューファイルの追加
ビューファイルをひとつ記述忘れしていました。acl_add.ctpファイルを下記に記述しておきます。
app/View/Users/acl_add.ctp
<div class="Acl form"> <?php echo $this->Form->create('Acl'); ?> <fieldset> <legend><?php echo __('パーミッションの追加'); ?></legend> <?php echo $this->Form->input('group_id'); echo $this->Form->input('aco'); echo $this->Form->radio('create',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'作成','value'=>'deny')); echo $this->Form->radio('read',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'読み込み','value'=>'deny')); echo $this->Form->radio('update',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'更新','value'=>'deny')); echo $this->Form->radio('delete',array( 'allow'=>'許可','deny'=>'禁止'), array('legend'=>'削除','value'=>'deny')); ?> </fieldset> <?php echo $this->Form->end(__('追加')); ?> </div> <div class="actions"> <h3><?php echo __('Actions'); ?></h3> <ul> <li><?php echo $this->Html->link(__('新規User'), array('controller'=>'users','action' => 'add')); ?></li> <li><?php echo $this->Html->link(__('リストGroups'), array('controller' => 'groups', 'action' => 'index')); ?> </li> <li><?php echo $this->Html->link(__('新規Group'), array('controller' => 'groups', 'action' => 'add')); ?> </li> <li><?php echo $this->Html->link(__('リストAcl'), array('controller' => 'arosacos', 'action' => 'index')); ?> </li> </ul> </div>
以上、追記でした(2012/08/03)。