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 } ?>
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.
3.137.220.120