官术网_书友最值得收藏!

Adding a prefix

Prefixes are additional values prepended to the URL, which allow you to clearly separate collections of actions in your controllers. This is typically used to rapidly create an admin area for an application.

In this recipe, we'll create an inventory management area to a books controller, where the standard actions will simply display details of books and the inventory area will be used to manage our books.

Getting ready

For this recipe, we'll need a table for our books, so create a table named books by using the following SQL statement:

CREATE TABLE books (
  id VARCHAR(36) NOT NULL,
  name VARCHAR(100),
  stock INT(4),
  created DATETIME,
  modified DATETIME,
  PRIMARY KEY(id)
);

We'll then need some sample data, so run the following SQL statement to insert some books:

INSERT INTO books (id, name, stock, created, modified)
VALUES
('635c460a-f230-4565-8378-7cae01314e03', 'CakePHP Application', 2, NOW(), NOW()),
('635c4638-c708-4171-985a-743901314e03', 'PHP for Beginners', 3, NOW(), NOW()),
('635c49d9-917c-4eab-854f-743801314e03', 'Server Administration', 0, NOW(), NOW());

We'll also need to create a BooksController. So, create a file named BooksController.php in app/Controller/ with the following content:

<?php
App::uses('AppController', 'Controller');

class BooksController extends AppController {

  public $helpers = array('Html', 'Form');

}

Then create a directory named Books/ in app/View/, and create the following files in that directory: index.ctp, view.ctp, inventory_stock.ctp, and inventory_edit.ctp.

How to do it...

Perform the following steps:

  1. First, open your core.php file in app/Config/ and make sure the following line is uncommented and has the following value:
    Configure::write('Routing.prefixes', array('inventory'));
  2. Create the following index() and view() methods in your BooksController:
    public function index() {
      $this->set('books', $this->Book->find('all', array(
        'conditions' => array(
          'Book.stock >' => 0
        )
      )));
    }
    
    public function view($id) {
      if (!($book = $this->Book->findById($id))) {
        throw new NotFoundException(__('Book not found'));
      }
      if ($book['Book']['stock'] < 1) {
        throw new CakeException(__('Book not in stock'));
      }
      $this->set(compact('book'));
    }
  3. In the BooksController class, add the following inventory_stock() and inventory_edit() methods:
    public function inventory_stock() {
      $this->set('books', $this->Book->find('all'));
    }
    
    public function inventory_edit($id) {
      $book = $this->Book->findById($id);
      if (!$book) {
        throw new NotFoundException(__('Book not found'));
      }
      if ($this->request->is('post')) {
        $this->Book->id = $id;
        if ($this->Book->save($this->request->data)) {
          $this->Session->setFlash(__('Book stock updated'));
          return $this->redirect(array(
            'prefix' => 'inventory',
            'action' => 'stock'
          ));
        }
        $this->Session->setFlash(__('Could not update book stock'));
      } else {
        $this->request->data = $book;
      }
    }
  4. Introduce the following content into your app/View/Books/index.ctp file:
    <h2><?php echo __('Books'); ?></h2>
    <table>
      <tr>
        <th><?php echo __('Name'); ?></th>
        <th><?php echo __('Created'); ?></th>
        <th><?php echo __('Modified'); ?></th>
      </tr>
      <?php foreach ($books as $book): ?>
        <tr>
          <td>
            <?php
            echo $this->Html->link($book['Book']['name'], array('controller' => 'books', 'action' => 'view', $book['Book']['id']));
            ?>
          </td>
          <td>
            <?php
            echo $this->Time->nice($book['Book']['created']);
            ?>
          </td>
          <td>
            <?php
            echo $this->Time->nice($book['Book']['modified']);
            ?>
          </td>
        </tr>
      <?php endforeach; ?>
    </table>
  5. Add the following content to your app/View/Books/view.ctp file:
    <h2><?php echo h($book['Book']['name']); ?></h2>
    <dl>
      <dt><?php echo __('Stock'); ?></dt>
      <dd><?php echo $book['Book']['stock']; ?></dd>
      <dt><?php echo __('Created'); ?></dt>
      <dd><?php echo $this->Time->nice($book['Book']['created']); ?></dd>
      <dt><?php echo __('Modified'); ?></dt>
      <dd><?php echo $this->Time->nice($book['Book']['modified']); ?></dd>
    </dl>
  6. Introduce the following content into your app/View/Books/inventory_stock.ctp file:
    <h2><?php echo __('Books Stock'); ?></h2>
    <table>
      <tr>
        <th><?php echo __('Name'); ?></th>
        <th><?php echo __('Stock'); ?></th>
        <th><?php echo __('Created'); ?></th>
      </tr>
      <?php foreach ($books as $book): ?>
        <tr>
          <td>
            <?php
            echo $this->Html->link($book['Book']['name'], array('prefix' => 'inventory', 'controller' => 'books', 'action' => 'edit', $book['Book']['id']));
            ?>
          </td>
          <td>
            <?php echo $book['Book']['stock']); ?>
          </td>
          <td>
            <?php
            echo $this->Time->nice($book['Book']['created']);
            ?>
          </td>
        </tr>
      <?php endforeach; ?>
    </table>
  7. Once more, with the following content into your app/View/Books/inventory_edit.ctp file.
    <h2><?php echo __('Edit Stock'); ?></h2>
    <p>
      <?php echo __('Book') . ':' . h($this->request->data('Book.name')); ?>
    </p>
    <?php
    echo $this->Form->create('Book');
    echo $this->Form->input('id');
    echo $this->Form->input('stock');
    echo $this->Form->end(__('Submit'));
    ?>
  8. Now when we enabled the inventory routing prefix, we have to adjust the settings for AuthComponent so that it correctly redirects to the non-prefixed methods of UsersController even from any prefixed method. Open the file named app/Controller/AppController.php and adjust settings for AuthComponent like this:
    public $components = array(
      ...
      'Auth' => array(
        'loginRedirect' => array(
          'inventory' => false,
          'controller' => 'products'
        ),
        'logoutRedirect' => array(
          'inventory' => false,
          'controller' => 'users',
          'action' => 'login'
        ),
        'loginAction' => array(
          'inventory' => false,
          'controller' => 'users',
          'action' => 'login'
        )
      ),
      ...
    );

    Note

    Note that we added inventory to all settings related to URLs and added the loginAction setting, as we're no longer going to use a default nonprefixed URL.

  9. Finally, navigate to /books/index, /books/view/635c460a-f230-4565-8378-7cae01314e03, /inventory/books/stock, or /inventory/books/edit/635c460a-f230-4565-8378-7cae01314e03 in your browser. The respective screenshots are shown as follows:
    How to do it...
    How to do it...
    How to do it...
    How to do it...

How it works...

In this recipe, we first set up the prefix settings for our routing. Specifically, we created a prefix named inventory. In this case, you could also define more prefixes by simply adding more values to the array of the Routing.prefixes configuration value.

We then created some index() and view() actions in our BooksController. These simply read the books available and show the details of a book, although the find('all') call of our index() method filters the results via the conditions option to not include any books with stock at 0 (out of stock). We also defined some inventory_stock() and inventory_edit() methods. You'll notice that these are prefixed with inventory_. This was intentional, as this is how the framework maps the router prefix with the action by convention. So, when calling any action of a controller prefixed with /inventory/ in the URL, the router will search for the requested action where the prefix is prepended with inventory_.

You probably also saw that while generating the URL for our links in our inventory management area, we included the prefix option in our call to the link() method on the Html helper. This tells the router to create a link using that prefix. Without it, the router would simply create a URL to a normal action on the controller.

Here, we simply prefixed some actions. However, you could easily extend this controller now so that it requires some special attribute of the currently logged-in user account in order to use the inventory actions.

主站蜘蛛池模板: 陆河县| 肥乡县| 临漳县| 黑龙江省| 城市| 安塞县| 绥棱县| 中西区| 安溪县| 襄汾县| 榆中县| 普兰店市| 满洲里市| 桐城市| 高密市| 万盛区| 绥江县| 锡林郭勒盟| 牙克石市| 红原县| 宁海县| 缙云县| 建瓯市| 成武县| 海林市| 虹口区| 博湖县| 烟台市| 嘉善县| 宁远县| 五寨县| 弥勒县| 玛纳斯县| 临沂市| 包头市| 镶黄旗| 宁城县| 襄汾县| 随州市| 凌海市| 庄河市|