Often enough we find ourselves needing to separate different areas of our application, not only in terms of code and user interface, but also in terms of functionality. With CakePHP's flexible routing system, we can achieve this and more by using prefixes, which provide us with a way to reimplement certain controller actions in different ways, and reach a particular implementation depending on the prefix being used, if any.
To go through this recipe we need a sample table to work with. Create a table named profiles
, using the following SQL statement:
CREATE TABLE `profiles`( `id` INT UNSIGNED AUTO_INCREMENT NOT NULL, `name` VARCHAR(255) NOT NULL, `email` VARCHAR(255) NOT NULL, `active` TINYINT(1) NOT NULL default 1, PRIMARY KEY(`id`) );
Add some sample data, using the following SQL statements:
INSERT INTO `profiles`(`id`, `name`, `email`, `active`) VALUES (1, 'John Doe', '[email protected]', 1), (2, 'Jane Doe', '[email protected]', 1), (3, 'Mark Doe', '[email protected]', 0);
Next, create the required ProfilesController
class in a file named profiles_controller.php
and place it in your app/controllers
folder, with the following contents:
<?php class ProfilesController extends AppController { public function index() { $profiles = $this->paginate(); $this->set(compact('profiles')); } public function edit($id) { if (!empty($this->data)) { if ($this->Profile->save($this->data)) { $this->Session->setFlash('Profile saved'), $this->redirect(array('action'=>'index')); } else { $this->Session->setFlash('Please correct the errors'), } } else { $this->data = $this->Profile->find('first', array( 'conditions' => array('Profile.id' => $id), 'recursive' => -1 )); } } } ?>
Create a folder named profiles
in your app/views
folder, then create the view in a file named index.ctp
and place it in your app/views/profiles
folder, with the following contents:
<p> <?php echo $this->Paginator->prev(); ?> <?php echo $this->Paginator->numbers(); ?> <?php echo $this->Paginator->next(); ?> </p> <table> <thead><tr><th>Name</th><th>Email</th><th>Actions</th></tr></thead> <tbody> <?php foreach($profiles as $profile) { ?> <tr> <td><?php echo $profile['Profile']['name']; ?></td> <td><?php echo $profile['Profile']['email']; ?></td> <td> <?php echo $this->Html->link('Edit', array('action'=>'edit', $profile['Profile']['id'])); ?> </td> </tr> <?php } ?> </tbody></table>
Create the view for the edit
action in a file named edit.ctp
and place it in your app/views/profiles
folder, with the following contents:
<?php echo $this->Form->create('Profile'), ?> <?php echo $this->Form->input('name'), ?> <?php echo $this->Form->input('email'), ?> <?php echo $this->Form->end('Save'), ?>
admin
, and manager
. Edit your app/config/core.php
file and look for the line that defines the Routing.prefixes
setting. If it is commented out, uncomment it. Then change it to:Configure::write('Routing.prefixes', array('admin', 'manager'));
ProfilesController
class to add the overridden index
and edit
actions for both prefixes. We will also add a new action so that when accessed with the admin
prefix, we can add new profile records. Edit your app/controllers/profiles_controller.php
file and add the following methods at the beginning of the ProfilesController
class:public function beforeFilter() { parent::beforeFilter(); $prefixes = Configure::read('Routing.prefixes'), if (!empty($prefixes)) { foreach($prefixes as $prefix) { $hasPrefix = false; if (!empty($this->params['prefix'])) { $hasPrefix = ($this->params['prefix'] == $prefix); } $prefixName = 'is' . Inflector::classify($prefix); $this->$prefixName = $hasPrefix; $this->set($prefixName, $hasPrefix); } } } public function manager_index() { $this->setAction('index'), } public function manager_edit($id) { $this->setAction('edit', $id); } public function admin_index() { $this->setAction('index'), } public function admin_edit($id) { $this->setAction('edit', $id); } public function admin_add() { $this->setAction('edit'), } public function index() { $profiles = $this->paginate(); $this->set(compact('profiles')); }
edit
action so that it can handle the creation of new records. While still editing your app/controllers/profiles_controller.php
file, make the following changes to the edit()
method of the ProfilesController
class:public function edit($id = null) { if (!empty($id) && !$this->isAdmin && !$this->isManager) { $this->redirect(array('action' => 'index')); } if (!empty($this->data)) { if (empty($id)) { $this->Profile->create(); } if ($this->Profile->save($this->data)) { $this->Session->setFlash('Profile saved'), $this->redirect(array('action'=>'index')); } else { $this->Session->setFlash('Please correct the errors'), } } elseif (!empty($id)) { $this->data = $this->Profile->find('first', array( 'conditions' => array('Profile.id' => $id), 'recursive' => -1 )); } }
app/views/profiles/index.ctp
view file and add the following at the end:<?php if ($isAdmin) { echo $this->Html->link('Create Profile', array('admin' => true, 'action'=>'add')); } ?>
app/views/profiles/edit.ctp
view file and make the following changes:<?php echo $this->Form->create('Profile'), ?>
<?php echo $this->Form->input('name'), ?>
<?php echo $this->Form->input('email'), ?>
<?php
if ($isManager || $isAdmin) {
echo $this->Form->input('active', array(
'options' => array(1 => 'Yes', 0 => 'No')
));
}
?>
<?php echo $this->Form->end('Save'), ?>
Any set of values specified in the configuration setting, Routing.prefixes
, act as routing prefixes. In this example, we have added two prefixes: admin
and manager
. Whenever we use a prefix in an URL (where the prefix precedes a normal CakePHP URL), CakePHP will set the current prefix in $this->params['prefix']
and execute an action whose name is the same as if the prefix were not used, but preceded with the prefix and an underscore sign, in the same controller as if the prefix were not used.
When we access http://localhost/manager/profiles/index
in our example, CakePHP will process this request by executing the action manager_index
located in the ProfilesController
, and setting $this->params['prefix']
to manager
. Knowing this, we can add controller and view variables to tell actions and views if we are accessing the application as a manager (when the manager
prefix is set) or as an administrator (when the admin
prefix is set.) We implement this through a more general approach by creating an appropriate controller and view variable for each prefix (isManager for the manager
prefix, and isAdmin
for the admin
prefix) in the beforeFilter
callback.
3.144.92.105