Chapter No.12 " Route Management" In this package, you will find: The authors biography A preview chapter from the book, Chapter no.12 "Route Management" A synopsis of the books content Information on where to buy this book
About the Authors Mark Safronov is a professional web application developer from the Russian Federation, with experience and interest in a wide range of programming languages and technologies. He has built and participated in building different types of web applications, from pure computational ones to full-blown e-commerce sites. He is also a proponent of following the current best practices of test-first development and clean and maintainable code. He is currently employed at Clevertech and is working on Yii-based PHP web applications. He was also a maintainer of the popular YiiBooster open source extension for some time. Back in 2008, he translated the book Visual Prolog 7.1 for Tyros, Eduardo Costa, in Russian with a totally new color layout. In 2013, along with Jacob Mumm, he co-authored the book Instant Yii Application Development Starter, Packt Publishing.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Jeffrey Winesett is a partner at SeeSaw Labs in Austin, Texas, and has over 10 years of experience building large-scale, web-based applications. He is a strong proponent of using open source development frameworks when developing applications, and a champion of the Yii framework in particular since its initial alpha release. He frequently presents on, writes about, and develops with Yii as often as possible. I would like to thank Qiang Xue for creating this amazing framework, and the entire Yii framework development team who continually improve and maintain it. I thank all of the technical reviewers, editors, and staff at Packt Publishing for their fantastic contributions, suggestions, and improvements. I would also like to thank my family, who have provided encouragement and unconditional support, and to my many colleagues over the years for providing invaluable opportunities for me to explore new technologies, expand my knowledge, and shape my career.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Web Application Development with Yii 2 and PHP This book is a guide that describes the process of incremental, test-first development of a web application using Yii framework Version 2. The Yii framework, hosted at http://www.yiiframework.com/, is a PHP-based application framework built around the Model-View-Controller composite pattern. It is suitable for building both web and console applications, but its feature set makes it most useful for web applications. It has several code generation facilities, including the full create-read-update-delete (CRUD) interface maker. It relies heavily on the conventions expressed in its default configuration settings. Overall, if all you need is a fancy interface for the underlying database, there is probably nothing better for you than the Yii framework. Given the extensive configuration options, any kind of application can be made from Yii. Version 2 of the Yii framework is built utilizing the latest improvements in the PHP infrastructure collected over the years. It uses the Composer utility (see https:// getcomposer.org/) as a primary distribution method, PSR levels 1, 2, and 4 from the PHP Framework Interop Group guidelines (see http://www.php-fig.org/), and PHP 5.4+features, such as short array syntax and closures. At the time of writing, Yii 2 is at the stage of late beta. Some changes are expected, but there should not be backward-compatibility-breaking changes anymore. Thus, the content of this book can be reasonably trusted even if the framework can attain some additional features after this book is published. What This Book Covers Chapter 1, Getting Started, covers the simplest possible methods to raise a working web application completely from scratch using the Yii framework. Chapter 2, Making a Custom Application with Yii 2, shows how the process of implementation of a web application with a single, working, tested feature can be done from scratch using the Yii framework. Chapter 3, Automatically Generating the CRUD Code, shows how we can implement a working, tested feature in an existing web application using only the code generation facilities and not a line of custom code written. Chapter 4, The Renderer, describes the details of how the framework renders its output and presents some tricks to introduce customizations to the rendering process.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Chapter 5, User Authentication, discusses the tools to provide authentication to application visitors. Chapter 6, User Authorization and Access Control, explains the ways to control access for application visitors, and, especially, about the role-based access control system. Chapter 7, Modules, returns from the exact features of the framework to its fundamentals. Here we will clearly understand the internal structure and logic of the Yii-based application and how it influences the overall design. Chapter 8, Overall Behavior, is about the infrastructure of the Yii-based application. We will learn about several features that affect the application as a whole. Chapter 9, Making an Extension, tells us how to make the extension to the Yii 2 framework and prepare it so that it is installable in the same way as the extensions built- in to the basic distribution of the framework itself. Chapter 10, Events and Behaviors, investigates the intricacies of the system inside the Yii 2 framework allowing us to attach custom behavior to many of the usual activities of the application, such as fetching a record from the database or rendering a view file. Chapter 11, The Grid, has two purposes. First, it explains the powerful and complex GridView widget, which allows you to make complicated, table-based interfaces relatively easily. Second, it presents a different approach in developing applications using the Yii 2 framework, the one that is customary in its community, so you can see both the advantages and the disadvantages of both approaches. Chapter 12, Route Management, explains the top level of the framework, that is, how it responds to HTTP requests from actual visitors. Chapter 13, Collaborative Work, concludes the book by presenting the methods that help to manage the code base of a Yii-based application when there are several developers working on it. Appendix A, Deployment Setup with Vagrant, shows a simple way to construct a virtual machine for your local development, which you can use for building the examples from this book. Appendix B, The Active Form Primer, contains an extension to Chapter 11, The Grid, in which we use another powerful user interface widget of Yii 2, the ActiveForm. It was excluded from the chapter text because it's not directly related to the GridView widget, but we could not gloss over it completely. Without the ActiveForm, the feature we were building in Chapter 11, The Grid, is not complete. Through the course of the book, starting from Chapter 2, Making a Custom Application with Yii 2, we'll be working with a single code base. Later chapters will build over the work previously done, so the book is expected to be read sequentially, without skipping or changing order.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Route Management In this chapter, we will explore how the Yii 2 routing system works, that is, how the framework responds to different URL routes requested from it. We'll start with the description of the process that the Yii application performs to determine the controller action to execute in response to client requests. Then, we will implement a small feature, which will demonstrate how we can control our routes using just the application conguration. And lastly, we'll implement one particularly interesting feature that will require our own custom rule class and show the considerations while doing so. Yii 2 routing 102 We have seen Yii 2 routing 101 in Chapter 2, Making a Custom Application with Yii 2, and this section is an extension of it. As we already know, everything in Yii 2 starts with the entry-point script, which in our example application is web/index.php. This script should be the only PHP script in the directory published by the web server. As everything comes to this script, all routes we used in the 10 chapters (excluding Chapter 1, Getting Started, discussing the installation of the framework) look as follows: protocol://domainname/path/to/ index.php?r=module/controller/action¶m=value&etc
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Route Management [ 324 ] So, any request is being processed by accessing the index.php le, and passing it the further route inside the application as the GET parameter named r. This name is congurable in the \yii\web\UrlManager::$routeParam property, so the following conguration snippet will set the name of the route parameter to icecream: [ 'components' => [ 'urlManager' => [ 'routeParam' => 'icecream' ] ] ] Such ddling is irrelevant in most cases, though, because we have two other properties, UrlManager: enablePrettyUrl and showScriptName, the usage of which we discussed in the Routing 101 section in Chapter 2, Making a Custom Application with Yii 2: The enablePrettyUrl property effectively removes the ?r= part from the URLs acceptable by the application. What was accessible by index. php?r=module/controller/action will be accessible by just index.php/ module/controller/action. But in addition to that, it enables the support to dene custom rules of parsing and generating routes. Basically, it completely changes the way the Yii application handles requests. The showScriptName property, when set to false, will prohibit the URL manager from adding the script name to the URLs it generates. The actual name of the entry-point script is irrelevant; it's inferred from the current $_SERVER settings automatically. Practically speaking, you will almost always use the following combinations of the parameters: 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, ] The only downside of this approach is that you have to congure your web server to send all requests to your entry point, like the following Apache rewrite directive: RewriteRule . index.php
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Chapter 12 [ 325 ] Note that the enablePrettyUrl modes are incompatible. If you are using pretty URLs, you cannot request your application using the ?r=:route notation and vice versa. Getting the actual route from the request string is just the rst step in the Yii 2 routing system. As discussed in the The informal concept of reachability section in Chapter 7, Modules, the route concept boils down to the following string: /moduleid/moduleid/.../moduleid/controllerid/actionid This string allows the framework to guess which controller action it should execute. If there is no moduleid, then the application itself is considered as a target module. When we have enablePrettyUrl set to true, though, we are able to dene special URL rules to parse client requests to the application. In fact, we are able to use arbitrary strings as routes in our system. There are three ways to control routes, which are as follows: Names of modules, controllers, and actions Custom rule definitions inside the components. urlManager.rules setting of the Yii application configuration Custom rule classes referenced inside the same setting FEATURE routing using names of modules, controllers, and actions Unless you make really convoluted URL rules using the other two options (custom URL rules and custom URL rule classes, see the end of the preceding section), you can rely on the basic path format Module ID Controller ID Action ID with arguments to the action being inside the request parameters. This already gives you a lot of power and is suitable in most cases. By carefully and thoughtfully choosing the names of modules, controllers, and actions, you probably will never need to dene any other routing rules. Inside the module, you have the controllerMap property, which allows you to assign controller IDs to specic controller classes manually.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Route Management [ 326 ] Otherwise, controllerNamespace works as a fallback mechanism. The controller ID will be used to infer the expected controller class name, and the namespace in controllerNamespace will be used to nd the physical location of the le holding its denition. The controller ID is converted to the controller class name using exactly the following conversion: $className = str_replace(' ', '', ucwords(str_replace ('-', ' ', $className))) . 'Controller'; That is, the dash-separated format of the ID becomes replaced by the uppercase format of the class name, and additionally Yii 2 expects that the controller class name will end with the string Controller. Inside the controller, you have similar mechanics. Using the actions property (never before discussed in this book), you can assign action IDs to specic controller action classes, which are descendants of \yii\base\Action. If there are no actions declared this way, the controller will use its public methods, the names of which start with the string action, as actions. This is called inline action. In fact, when you request the user/view route and UserController does not have anything assigned to the view ID in its actions property, it actually creates the instance \yii\base\InlineAction, instructs it to refer to the actionView method, and then uses this inline action as any other \yii\base\Action action (see the documentation and denition of \yii\base\Controller::runAction, which is available at http://www.yiiframework.com/doc-2.0/yii-base-controller. html#runAction%28%29-detail, for the exact reference). Maybe it's quite ironic, but these two fallback mechanisms of the module and controller are what you usually use when developing web applications with Yii 2. Fundamental rules of URL management in Yii 2 It is quite important to understand some fundamental concepts behind the Yii 2 routing system; it will make everything easier to understand: 1. Any request you pass to the Yii application eventually will be resolved as the name of the module, name of the controller, name of the action, and parameters to this action.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Chapter 12 [ 327 ] 2. The universal format, which allows Yii 2 routing mechanics to understand which controller action to call, is as follows: [ "/moduleid/.../moduleid/controllerid/actionid", [ "param1" => "value1", , "paramN" => "valueN" ] ] 3. The URL manager component parses the incoming request to the format described earlier using the URL rule entities. 4. The URL manager component converts the route from this format to the string to be placed as the URL into the HTML page being rendered, using the same URL rule entities. 5. The URL rules dene the parsing of URLs and the creating of URLs as completely separate activities. In fact, by using custom URL rules, you'll be able to create URLs from one route denition, which will be parsed as a completely different route denition. FEATURE creating URLs in Yii Before we delve into the details of how the URLs are parsed by Yii 2 and converted into calls to controller actions, let's mention the enormously important function that actually creates the URLs to be displayed to the client. This function is the \yii\ web\UrlManager.createUrl($params) function. You can access this method by the following incantation from anywhere in your application: Yii::$app->urlManager->createUrl($params); This method receives one argument, which has the parameters to create a text representation of the URL in the universal format presented in the previous section. This method is so widely and often used that there is a helper method to simplify its usage, the \yii\helpers\BaseUrl::toRoute() method, which you have to call as follows: URL::toRoute($params);
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Route Management [ 328 ] Custom routes using a conguration Look at the following path we go to when opening the View Customer Record page: /customer-records/view?id=1 This is quite verbose. Why not just use the following: /customer/1 We can implement it quite easily using the following declaration inside the components.urlManager.rules setting of the Yii application conguration: 'components' => [ 'urlManager' => [ 'rules' => [ 'customer/<id:\d+>' => 'customer-records/view', ] ] ] This declaration is being read and understood as follows: 1. If the request begins with customer/. 2. After this there are only digits. 3. Store these digits as an argument named id. 4. Process the request as the customer-records/view route. 5. Pass the stored id argument to the resulting controller action. FEATURE URL rules The components.urlManager.rules setting of the application, which corresponds to the \yii\web\UrlManager::$rules property, can be lled with objects in two notations. The full notation is the array notation to be consumed by the Yii::createObject() method. You dene the instances of the \yii\web\UrlRule class here. The following table has the most crucial properties of the URL rules: Property Meaning pattern This means what the incoming request should look like for this rule to take effect. verb This means which HTTP method should be used in the request for this rule to take effect. route This is the route to the controller action in the moduleid/ controllerid/actionid format, to which the pattern should resolve to.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Chapter 12 [ 329 ] Property Meaning suffix This means what string to append when creating URLs and what string must be present at the end of the pattern when parsing the request for this rule to take effect. mode If set to 0, the rule will be used both to create URLs and parse them. Otherwise, you can set it to \yii\web\UrlRule::PARSING_ONLY or \ yii\web\UrlRule::CREATION_ONLY. There are some other properties, which have more specic usages, such as host and defaults. You are encouraged to read the documentation (http://www.yiiframework.com/doc-2.0/yii-web-urlrule.html) and/or source code of the \yii\web\UrlRule class to get the exact details. The most important and useful property here is the pattern property. It denes what should be presented to Yii as a request string (without the request parameters), with the addition of the named parameters. The named parameter is the construct of the form given as follows: <Name:RegularExpression> Angle brackets and colons are the mandatory syntax. Named parameters can be referenced in the route property later, increasing the genericity of the rule. If they are not referenced in the route, they become stored as a $_GET parameter with the specied name (overriding existing values, if any). The shorthand notation for dening the URL rules is as follows: "[verb ]pattern" => "route" This will initialize the URL rule object with just the pattern, verb, and route properties specied, leaving everything else blank, with verb being optional. The Yii 2 documentation for \yii\web\UrlManager::$rules presents a great self-describing example of a URL manager congured for REST-compliant requests: 'rules' => [ 'dashboard' => 'site/index', 'POST <controller:\w+>s' => '<controller>/create', '<controller:\w+>s' => '<controller>/index', 'PUT <controller:\w+>/<id:\d+>' => '<controller>/update', 'DELETE <controller:\w+>/<id:\d+>' => '<controller>/delete', '<controller:\w+>/<id:\d+>' => '<controller>/view', ];
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Route Management [ 330 ] It actually reads quite easily given that you always remember that the line noise between the colon and the closing angular bracket is just a regular expression. As you can see, the named id parameters from the pattern are not mentioned in the route part of the rule, which means that they will be passed to the corresponding controller action as arguments with the same names. The parameter named controller makes this ruleset generic, applicable to all controllers in the system. The rules declared in the rules setting are checked in the order of appearance. The rst rule, which corresponds to the current request, is applied, and everything else is ignored after that. If no rule was red, then the URL manager falls back on the parsing of the base /moduleid/controllerid/actionid format. Apart from manipulating the properties of the base \yii\web\UrlRule class, we can reference any other class as the URL rule inside the rules setting, given that this class implements \yii\web\UrlRuleInterface. This interface declares two fundamental activities of the URL rule: Method Meaning parseRequest( $manager, $request ) The $manager argument is an instance of the UrlManager class. The $request argument is an instance of a request class, which you can use to get the request string and parameters to parse. This method must return either a route in the canonical format shown in the Fundamental rules of URL management in Yii 2 section or exactly false, which means that this rule cannot be applied to the current request. createUrl( $manager, $route, $params ) The $manager argument is an instance of the UrlManager class. The $route argument is a string denoting the route in the base /moduleid/ controllerid/actionid format. This can have variations, such as omitted parts. Be careful about it. The $params argument is an array of key-value pairs specifying the query parameters for this route. This method is expected to return a string, which should be a relative URL, ideally parsable back to route/parameters by the parseRequest call of the same UrlRule class. If the route/parameters do not correspond to this rule, this method should return exactly the false value.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Chapter 12 [ 331 ] Custom routes using custom URL rule classes As a harder task, let's implement a more convoluted feature. Given our migration script creating default users in the database, the following URL brings us to the View page for the user who has the username AnnieManager: /users/view?id=2 A real-world feature request from the higher-ups can be the following: make the same page accessible by the following URL: /AnnieManager This rule cannot be represented as the pattern-route pair, because we should match the given username stored inside the database, with the ID expected by the actionView() controller action. To understand custom URL rules, you should understand this concept very well: in the end, a particular action of the controller will be called, and we should pass to it the arguments it expects. What we are talking about in this chapter is the abstraction, which is one level above that, when we hide this base routing under a different vocabulary, with the goals to be more SEO-friendly, more regular like REST, or just overall more pleasant to see. But this level is ultimately resolved to the base route/parameters pair. We will solve this task by introducing the custom URL rule class. Declare it in the ruleset as follows: 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ 'customer/<id:\d+>' => 'customer-records/view', // our rule from previous task [ 'class' => 'app\utilities\UsernameUrlRule' ] ] ],
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Route Management [ 332 ] This time, we started with the declaration instead of wiring up the already existing class. Let's create the class, then, inside the @app/utilities/UsernameUrlRule.php le as declared: namespace app\utilities; use yii\web\UrlRuleInterface; class UsernameUrlRule implements UrlRuleInterface { public function parseRequest($manager, $request) { // parse request here ... } public function createUrl($manager, $route, $params) { // make the URL from route/params pair here... } } First, parse by the parseRequest() method. We will check whether the rule applies to us as follows: $maybeUsername = $request->pathInfo; $user = UserRecord::findOne(['username' => $maybeUsername]); if (!$user) return false; There is a very simple logic here. If the string between hostname and the ? symbol denoting the start of request parameters is not a username of UserRecord in our database, we tell UrlManager that we can't do anything here.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Chapter 12 [ 333 ] It is a serious security breach here, which you must solve in some way if you really end up implementing such a feature on your web application. If users can register themselves and choose their username, then nothing stops them from choosing names, such as site, or users, or customer-records, which correspond to the controller IDs. As URL rules are checked rst, the existence of such a user will damage access to the referenced controller. For example, the /customer-records URL, which normally is identical to /customer-records/index, will be resolved to the View page of the user with the username customer- records. One way, which is quite cumbersome to maintain, is to check whether $maybeUsername is among some set of prohibited keywords, and this set can be automatically generated from the controller IDs used in your application. On the other hand, if $user is really found, we construct the required route/ parameters pair and return it: $route = 'users/view'; $params = ['id' => $user->id]; return [$route, $params]; Second, we should be able to create URLs in the same format through our application by the createUrl() method. One place where we can nd URLs to the View User pages is /users/index, with GridView listing the UserRecord models. We should rst check whether the route and parameters given to us are really relevant to us: if ($route !== 'users/view' || !array_key_exists ('id', $params)) return false; We don't care about routes other than users/view, and we require that id to be given to us. Also, we must be sure that the UserRecord really exists in the database, or else we will not be able to fetch the username: $user = UserRecord::findOne($params['id']); if (!$user) return false;
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Route Management [ 334 ] If everything's all right, all we have to do is return the username: return "{$user->username}"; Note the absence of a leading slash, made explicit by the string interpolation notation. Yii 2 automatically inserts this slash for us, so createUrl() should return only the remaining string. Now open the /users page, and hover on any button with the icon of an eye. It should have the URL equal to the corresponding username. After clicking on this button, you should end on the View page for the corresponding UserRecord object. Summary This chapter summarizes the routing mechanics that we dealt with through the whole book. We discussed the layer of custom routes that can be resolved back to basic controller actions. We looked at two practical examples from real life that showed how we can utilize these mechanics. Everything else can be read in the documentation for UrlManager and UrlRule and additionally, in the \yii\helpers\Url helper class. The next chapter will be the nal one in our adventure. We'll deal with the infrastructure problems of developing a Yii 2 application, especially the problem of sharing the code base between developers and between development and production environments.
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php
Where to buy this book You can buy Web Application Development with Yii 2 and PHP from the Packt Publishing website: https://www.packtpub.com/all-books/web- application-development-yii-2-and-php. Free shipping to the US, UK, Europe and selected Asian countries. For more information, please read our shipping policy. Alternatively, you can buy the book from Amazon, BN.com, Computer Manuals and most internet book retailers.
www.PacktPub.com
For More Information: www.packtpub.com/all-books/web-application-development-yii-2-and-php