Creating the rule class

URL rules declared in terms of pattern-route pairs can cover the majority of projects. However, it is not flexible enough with dynamic data, where the URL could be any format and value stored in the database.

Now, we need to display item details using a URL that contains only the item title, such as http://hostname/basic/web/news/Test news of 2015-04-19

There is no way to solve this with URL rules, as we have done until now.

A more general solution to parse and create URL requests is using Rule classes.

The Rule class extends Object and implements UrlRuleInterface.

The next example will explain how to display item details, finding it from the title (defined in data() array of objects), and parsing and creating routes with a Rule class.

The route displayed in the browser will have the news/title format.

For this purpose, create a new folder components under the basic folder if it does not exist, and create components/NewsUrlRule.php with the following content:

<?php

namespace appcomponents;

use yiiwebUrlRuleInterface;
use yiiaseObject;

class NewsUrlRule extends Object implements UrlRuleInterface
{

  public function createUrl($manager, $route, $params)
  {
    if ($route === 'news/item-detail') {
      if (isset($params['title'])) {
        return 'news/'.$params['title'];
      }
    }
    return false;  // this rule does not apply
  }

  public function parseRequest($manager, $request)
  {
    $pathInfo = $request->getPathInfo();

    if (preg_match('%^([^/]*)/([^/]*)$%', $pathInfo, $matches)) {
      if($matches[1] == 'news')
      {
        $params = [ 'title' => $matches[2]];
        return ['news/item-detail', $params];
      }
      else
      {
        return false;
      }
    }
    return false;  // this rule does not apply
  }
}

The first method, createUrl() receives $manager, $route, and $params. With route and params, the framework builds the URL. In this case, we check whether the route passed is equivalent to news/item-detail and if it is so, return the corresponding URL.

The second method, parseRequest() receives $manager and $request. A match with a custom regular expression will be done to extract the required parts, using the $request data. The process will return the route, to be executed.

Now, link these components to urlManager of the web.php file located at config/, appending the following lines in the rule property of the urlManager component:

[
'class' => 'appcomponentsNewsUrlRule',
// ...configure other properties...
],

The next thing to do is to create actionItemDetail in NewsController, as follows:

public function actionItemDetail()
{
    $title = Yii::$app->request->get('title');
    
    $data = $this->data();
    
    $itemFound = null;
    
    foreach($data as $d)
    {
        if($d['title'] == $title) $itemFound = $d;
    }        
    
    return $this->render('itemDetail', ['title' => $title, 'itemFound' => $itemFound]);
}

In this action, we simply find the item starting from the title received from the route. We pass the title and itemFound to view.

The last file to create is view under views/news/itemDetail.php:

Detail item with title <b><?php echo $title ?></b>
<br /><br />
<?php if($itemFound != null) { ?>
    <table border="1">
        <?php foreach($itemFound as $key=>$value) { ?>
        <tr>
            <th><?php echo $key ?></th>
            <td><?php echo $value ?></td>
        </tr>
        <?php } ?>
    </table>
    
    <br />
    
    Url for this items is: <?php echo yiihelpersUrl::to(['news/item-detail', 'title' => $title]); ?>
    
<?php } else { ?>
    <i>No item found</i>
<?php } ?>
Creating the rule class

Item detail output

In this view, the item details (if the item is found) along with how to build the URL of the item detail will be displayed.

..................Content has been hidden....................

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