A free and open-source book on Zend Framework for beginners


5.7. Regex Route Type

The regular expression route type (Regex) is useful if you have URLs which can be matched against a regular expression.

For example, assume you want to create a simple documentation system for your website. The documentation would consist of "static" pages mapped to URLs like /doc/<page_name>.html.

By the term "static page" we refer to a page which mostly contains static HTML code plus several PHP inline fragments. For such simple pages you do not need to create separate controller actions. All "static" pages can be served by the single controller action.

Let's implement the route which will serve the "static" pages of the site. Because "static" pages are simple, you typically won't need to add per-page action methods to the controller. All pages will be handled by the single action IndexController::docAction().

First, we add the Regex route named "doc" to the module.config.php file:

'doc' => [
    'type' => Regex::class,
    'options' => [
        'regex'    => '/doc(?<page>\/[a-zA-Z0-9_\-]+)\.html',
        'defaults' => [
            'controller' => Controller\IndexController::class,
            'action'     => 'doc',
        ],
        'spec'=>'/doc/%page%.html'
    ],
],

Line 2 defines the Regex type for the route. In line 4, we have the regular expression /doc(?<page>\/[a-zA-Z0-9_\-]+)\.html. It will match to URLs like "/doc/contents.html", "/docs/introduction.html" and so on. The expression contains the named capture 6 "page", which will be returned by the router on match together with the default parameters.

Line 9 contains spec option, which is used for generating URLs by route (we will discuss generating URLs by route later in this chapter).

6) In PHP PCRE regular expressions, it is possible to name a sub-pattern using the syntax (?P<name>pattern). This sub-pattern will then be indexed in the matches array by its name.

Do not forget to add the following line to the beginning of module.config.php file:

use Zend\Router\Http\Regex;

Next, add the following action to IndexController class:

public function docAction() 
{
    $pageTemplate = 'application/index/doc'.
        $this->params()->fromRoute('page', 'documentation.phtml');        
  
    $filePath = __DIR__.'/../../view/'.$pageTemplate.'.phtml';
    if(!file_exists($filePath) || !is_readable($filePath)) {
        $this->getResponse()->setStatusCode(404);
        return;
    }
	
    $viewModel = new ViewModel([
            'page'=>$pageTemplate
        ]);
    $viewModel->setTemplate($pageTemplate);
	
    return $viewModel;
}

In lines 3-4 above, we retrieve the page parameter from route (remember the "page" named capture from our regular expression?) and save it as the $pageTemplate variable. We will use the $pageTemplate variable for determining the view template name to pass to the view resolver. Then, in lines 6-10, we check if such a file is present, and if not, return the 404 "Not Found" status code, which will force ZF3 to display the error page. In line 12, we create the ViewModel variable container, and in line 15 we explicitly set the view template name for rendering.

To see the documentation system in action, create a couple of "static" view template files: the Table of Contents page (contents.phtml) and the Introduction page (introduction.phtml). Create the doc subdirectory under the view/application/index directory of the Application module and put the contents.phtml view template there:

<h1>Table of Contents</h1>

<ul>
    <li>
        <a href="<?= $this->url('doc', ['page'=>'introduction']); ?>">
            Introduction
        </a>
    </li>  
</ul>

In the lines above, we provide the HTML code for the "Table of Contents" page header, and the list which contains the single item named "Introduction" pointing to the Introduction "static" page. The link URL is generated with the Url view helper (for more details on the Url[Zend\View\Helper\Url] helper, see further sections in this chapter).

Then add the introduction.phtml page into the same doc directory:

<h1>Introduction</h1>

<p>Some introductory materials.</p>

In the lines above, we define the HTML markup for the simple Introduction page.

Now, if you open the "http://localhost/doc/contents.html" URL in your browser, you should see a nice simple documentation system which you can extend and use in your site (figure 5.8):

Figure 5.8. "Static" Page Figure 5.8. "Static" Page

Clicking the Introduction link will direct you to the "Introduction" static page. You can also add other pages to the doc directory to make them automatically available for site users through our Regex route.

One disadvantage of such a documentation system is that it does not work well if you place nested pages in subdirectories under the doc directory. The reason of this limitation lies in the way the Regex route assembles URLs. You can't generate URLs containing slash characters, as these "unsafe" characters will be automatically URL-encoded. We will work-around this problem with our custom route type that we will create at the end of this chapter.


Top