Using routes with prefixes

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.

Getting ready

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(); ?>&nbsp;
<?php echo $this->Paginator->numbers(); ?>&nbsp;
<?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'), ?>

How to do it...

  1. We start by adding two prefixes to CakePHP: 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'));
    
  2. Let us modify the 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'));
    }
    
  3. We now need to change the 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
    ));
    }
    }
    
  4. The next step is changing the views. Edit your 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'));
    }
    ?>
    
  5. Finally, edit your 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'), ?>
    

How it works...

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.

See also

  • Using prefixes for role based access controller in Chapter 1, Authentication
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.92.105