The router

This component of the framework has been rewritten from scratch and it's really powerful and flexible, allowing you to create a lot of combination of routes. The main functionality of the router is matching a request to a given controller/action. It also assembles URLs based on the defined routes. This process is accomplished by inspecting the URI and attempting to match it with a given route that has some constraints, or by generating the URL based on the parameters defined on the routes.

The general flow of this component is as follows:

  • A request arrives and the framework creates a request object
  • Then the route parses the URI to identify the segments
  • After that the router iterates through the list of routes previously ordered
  • On each iteration, the segments of the URI are checked to see if it matches the current route
  • When a route matches the URI, the request is dispatched to the specific controller and action is configured on the route

We have two parts on the routing system: the router itself that holds the logic to test URIs against routes and generate URLs, and the route that will hold the data of how to match a specific request. The route can also hold default data, extra parameters, and so on.

'wall' => array(
    'type' => 'ZendMvcRouterHttpSegment',
    'options' => array(
        'route'    => '/api/wall[/:id]',
        'constraints' => array(
            'id' => 'w+'
        ),
        'defaults' => array(
            'controller' => 'WallControllerIndex'
        ),
    ),
)

This is an example of a route. As you can see we are specifying a parameter called id and we are adding constraints on this id.

The router in ZF2 can be used not only for HTTP requests but also for CLI applications. In our case, we will focus our attention on the website-related router but the essence of the router will be the same for the CLI apps.

Zend Framework 2 provides two different routers: SimpleRouteStack and TreeRouteStack, and eight possible route types to choose from: Hostname, Literal, Method, Part, Regex, Scheme, Segment, and Query. Here is a detailed view of all of them.

SimpleRouteStack

This is a basic router that gets all the configured routes and loops through them in a LIFO order until a match is found. The routes have priority and as the router is looping them in a LIFO order, the routes that are more likely to be matched (the ones that match more often) should be registered last, and the one that matches less should be registered first. Also, an easy way to set up the priority of the routes is using the third parameter of the AddRoute() method.

$router->addRoute('foo', $route, 10);

That's an example of how you can specify priorities on routes; just pass a number and the routes will be ordered by those values.

TreeRouteStack

This router is a little bit more complex than SimpleRouteStack because this allows you to create a tree of routes and will use a binary-tree algorithm to match the routes. The basic configuration of a TreeRouteStack route will consist of the following:

  • A base route that will be the root of the tree and all the following routes will extend this one.
  • An optional configured instance of RoutePluginManager to be able to lazy-load routes.
  • Another optional parameter will be may_terminate that tells the router that no other route will follow this one.
  • Finally, a child_routes array that can also be optional. If we specify routes here, they will extend the main one; also, a child route can be another TreeRouteStack.

You can add routes one by one on both routers by using the AddRoute() method or in batches using AddRoutes().

$route = Part::factory(array(
    'route' => array(
        'type' => 'literal',
        'options' => array(
            'route' => '/',
            'defaults' => array(
                'controller' => 'ApplicationControllerIndexController',
                'action' => 'index'
            )
        ),
    ),
    'child_routes' => array(
        'forum' => array(
            'type' => 'literal',
            'options' => array(
                'route' => 'forum',
                'defaults' => array(
                    'controller' => 'ApplicationControllerForumController',
                    'action' => 'index'
                )
            )
        )
    )
));

As you can see, the first route we defined is the home page – the root of the domain. Then we defined the route for the forum extending from the base one.

Hostname

$route = Hostname::factory(array(
    'route' => ':subdomain.domain.tld[/:type]',
    'constraints' => array(
        'subdomain' => 'fwd{2}'
    ),
    'defaults' => array(
        'type' => 'json',
    ),
));

This is a usage example of how to configure a Hostname route. In the route parameter, we specify the hostname to match in the URI. Also, you can set up parameters, such as subdomain in this case.

You can set up constraints and default values on the route; in this particular example, we are specifying a regular expression that will limit the matching of the route to all the subdomains starting with the letters fw and followed by two digits. Sometimes you will need to pass values to the controllers based on the URL or define some default values for parameters on the URL. In this example we are setting the default value of type to the json string.

Literal

This route will match a URI path literally as specified by the route parameter. As usual, the default data will be the parameters you want returned on a match.

$route = Literal::factory(array(
    'route' => '/foo',
    'defaults' => array(
        'controller' => 'ApplicationControllerIndexController',
        'action' => 'foo'
    ),
));

Method

This type of route will match if the HTTP method used on the request matches the one configured in the route using the verb parameter. We can specify multiple methods on the same route if we separate them with comma. A valid list of request methods can be found in the RFC 2616 Sec. 5.1.1 section.

$route = Method::factory(array(
    'verb' => 'post,put',
    'defaults' => array(
        'controller' => 'ApplicationControllerIndexController',
        'action' => 'form-submit'
    ),
));

Part

The Part route type not only extends TreeRouteStack but also implements RouteInterface. It means that this route can hold a tree of possible routes based on the URI segments. Let's explore the idea of a forum application. We want to show the home of the website when you go to the root of the domain, and then we want to display the forum if you go to domain.com/forum. We can accomplish that using the Part route type and we will need to configure it as shown in the following code snippet:

$route = Part::factory(array(
    'route' => array(
        'type' => 'literal',
        'options' => array(
            'route' => '/',
            'defaults' => array(
                'controller' => 'ApplicationControllerIndexController',
                'action' => 'index'
            )
        ),
    ),
    'route_plugins' => $routePlugins,
    'may_terminate' => true,
    'child_routes' => array(
        'forum' => array(
            'type' => 'literal',
            'options' => array(
                'route' => 'forum',
                'defaults' => array(
                    'controller' => 'ApplicationControllerForumController',
                    'action' => 'index'
                )
            )
        )
    )
));

As you can see in the previous code example, we are defining a child_routes parameter with more routes inside, thus creating a tree of routes. Of course, the routes added as child will extend the parent route and therefore the matching URI path. Now with this in place if we get a request on domain.com/forum, ZF2 will inspect the request object and will match the URI against the routes we defined. Finally, as the forum route will match, the request will be dispatched to ForumController.

Regex

A Regex route will be based on a regular expression test match of the URI. You need to specify regex in the regex parameter and it can be any valid regular expression.

When working with this route we have to keep two things in mind. The first one is to use named captures on regex for any value we want to return as parameter on a match, the second is that we need to specify a value for the spec parameter to map each regex capture to the specific parameter. This will be used by the URL helper when building URLs based on the routes. For instance:

$route = Regex::factory(array(
    'regex' => '/blog/(?<id>[a-zA-Z0-9_-]+)(.(?<format>(json|html|xml|rss)))?',
    'defaults' => array(
        'controller' => 'ApplicationControllerBlogController',
        'action'     => 'view',
        'format'     => 'html',
    ),
    'spec' => '/blog/%id%.%format%',
));

In the previous example, you will notice that regex is using named captures enclosed in <> and we are specifying the format of the URL in the spec parameter, identifying each parameter with a text between percentage symbols. This will help the router to put the value of the parameters in the correct place in the URL while assembling it.

Scheme

The Scheme route type will match a URI based only on the URI scheme. This route type is similar to the Literal route because the match has to be exact and will return the default parameters on a successful match.

$route = Scheme::factory(array(
    'scheme' => 'https',
    'defaults' => array(
        'https' => true,
    ),
));

As you can see in the previous code example, if the route matches, we will return a parameter called https with a true value.

Segment

$route = Segment::factory(array(
    'route' => '/:controller[/:action]',
    'constraints' => array(
        'controller' => '[a-zA-Z][a-zA-Z0-9_-]+',
        'action'     => '[a-zA-Z][a-zA-Z0-9_-]+',
    ),
    'defaults' => array(
        'controller' => 'ApplicationControllerIndexController',
        'action'     => 'index',
    ),
));

This is an example of how to use the Segment route that will allow us to match against any segment of the URI path. In the route parameter, the segments are defined using a specific notation; this is a colon followed by alphanumeric characters. The segments on a URI can be optional and that will be denoted by enclosing the segment in brackets.

Each segment must have constraints associated with it; the constraint will be a regular expression defining the requirements for a positive match.

Wildcard

This type of route allows you to get all the segments of a URI specifying the separator between keys and values. Consider the following code example to get a better understanding:

'route_name' => array(
    'type' => 'ZendMvcRouterHttpWildcard',
    'options' => array(
        'key_value_delimiter' => '/',
        'param_delimiter' => '/',
    )
)

That's how the route looks when configured, and it will work like this. If you have a URI such as /id/1/name/john, this route will return the two variables id and name. The first one will contain the number 1 and the second will contain the string john.

Query

This is the last type of route offered by the route system of Zend Framework 2. This will allow us to capture and define parameters on a query string. An important point is that it's designed to be used as a child route.

$route = Part::factory(array(
    'route' => array(
        'type'    => 'literal',
        'options' => array(
            'route'    => 'page',
            'defaults' => array(
            ),
        ),
    ),
    'may_terminate' => true,
    'route_plugins'  => $routePlugins,
    'child_routes'  => array(
        'query' => array(
            'type' => 'Query',
            'options' => array(
                'defaults' => array(
                    'foo' => 'bar'
                )
            )
        ),
    ),
));

In this example we can see how the route has been defined as a child of a Literal one. Then we can use this to generate a URL with a query string. For example:

$this->url(
    'page/query',
    array(
        'name'=>'my-test-page',
        'format' => 'rss',
        'limit' => 10,
    )
);

In the previous code example, we should specify /query in order to activate the child route while assembling the URL and be able to append the parameters to the query string of the URL generated.

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

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