English spoken conference

Defunct Route Handlers

1.3 version
Maintained Unmaintained
1.2

Defunct Route Handlers

When an already-persisted document is updated and the URI generated by the RoutingAuto system is changed, a new route is always created. Defunct route handlers decide what to do with the old routes.

remove

The remove handler will simply delete any old routes. This is the default action.

  • YAML
    1
    2
    3
    stdClass:
        uri_schema: /cmf/blog
        defunct_route_handler: remove
    
  • XML
    1
    2
    3
    4
    5
    <auto-mapping xmlns="http://cmf.symfony.com/schema/routing_auto">
        <mapping class="stdClass" uri-schema="/cmf/blog">
            <defunct-route-handler name="remove" />
        </mapping>
    </auto-mapping>
    

Note

The above example is illustrative only. Removing old routes is the default action, so it is not necessary to explicitly configure this handler.

leave_redirect

The LeaveRedirectDefunctRouteHandler will automatically update old routes to redirect the browser to the route which has replaced it. This effectively means you can rename your objects without worrying about users receiving HTTP 404 responses.

The handler will replace the old route with a RedirectRoute at the same path.

  • YAML
    1
    2
    3
    stdClass:
        uri_schema: /cmf/blog
        defunct_route_handler: leave_redirect
    
  • XML
    1
    2
    3
    4
    5
    <auto-mapping xmlns="http://cmf.symfony.com/schema/routing_auto">
        <mapping class="stdClass" uri-schema="/cmf/blog">
            <defunct-route-handler name="leave_redirect" />
        </mapping>
    </auto-mapping>
    

For the redirect to take place you will need to tell the DynamicRouter to route routes with the type cmf_routing_auto.redirect to a controller which can perform the redirect.

The RoutingAutoBundle has included such a controller for your convenience. It can be configured as follows:

  • YAML
    1
    2
    3
    4
    5
    6
    7
    # app/config/config.yml
    cmf_routing:
        dynamic:
            controllers_by_class:
                # ...
            controllers_by_type:
                cmf_routing_auto.redirect: cmf_routing_auto.redirect_controller:redirectAction
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services">
    
        <config xmlns="http://cmf.symfony.com/schema/dic/routing">
            <dynamic>
                <controller-by-type
                    type="cmf_routing_auto.redirect">
                    cmf_routing_auto.redirect_controller:redirectAction
                </controller-by-class>
            </dynamic>
        </config>
    
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    // app/config/config.php
    $container->loadFromExtension('cmf_routing', array(
        'dynamic' => array(
            'controllers_by_type' => array(
                'cmf_routing_auto.redirect' => 'cmf_routing_auto.redirect_controller:redirectAction'
            ),
        ),
    ));
    

Creating a Custom Defunct Route Handler

To create a custom default route handler, you have to implement DefunctRouteHandlerInterface. This requires a method handleDefunctRoutes().

They are not all-together trivial - the following handler removes old routes and is the default handler:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
namespace Symfony\Cmf\Component\RoutingAuto\DefunctRouteHandler;

use Symfony\Cmf\Component\RoutingAuto\DefunctRouteHandlerInterface;
use Symfony\Cmf\Component\RoutingAuto\UriContextCollection;
use Symfony\Cmf\Component\RoutingAuto\Adapter\AdapterInterface;

class RemoveDefunctRouteHandler implements DefunctRouteHandlerInterface
{
    protected $adapter;

    public function __construct(AdapterInterface $adapter)
    {
        $this->adapter = $adapter;
    }

    public function handleDefunctRoutes(UriContextCollection $uriContextCollection)
    {
        // get all routes that refer to the subject object
        $referringAutoRouteCollection = $this->adapter->getReferringAutoRoutes(
            $uriContextCollection->getSubjectObject()
        );

        foreach ($referringAutoRouteCollection as $referringAutoRoute) {
            // if the route no longer exists
            if (false === $uriContextCollection->containsAutoRoute($referringAutoRoute)) {
                // get the new route
                $newRoute = $uriContextCollection->getAutoRouteByTag($referringAutoRoute->getAutoRouteTag());

                // migrate the children to the new route
                $this->adapter->migrateAutoRouteChildren($referringAutoRoute, $newRoute);
                // remove the old route
                $this->adapter->removeAutoRoute($referringAutoRoute);
            }
        }
    }
}

All defunct route handlers should be tagged with cmf_routing_auto.defunct_route_handler. The above class is registered as following:

  • YAML
    1
    2
    3
    4
    5
    services:
        acme_cms.defunct_route_handler.foobar:
            class: Acme\CmsBundle\RoutingAuto\DefunctRouteHandler\RemoveConflictResolver
            tags:
                - { name: cmf_routing_auto.defunct_route_handler, alias: "remove"}
    
  • XML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services">
        <service
            id="acme_cms.defunct_route_handler.foobar"
            class="Acme\CmsBundle\RoutingAuto\DefunctRouteHandler\RemoveConflictResolver"
        >
            <tag name="cmf_routing_auto.defunct_route_handler" alias="remove"/>
        </service>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    use Symfony\Component\DependencyInjection\Definition;
    
    $definition = new Definition('Acme\CmsBundle\RoutingAuto\DefunctRouteHandler\RemoveConflictResolver');
    $definition->addTag('cmf_routing_auto.defunct_route_handler', array('alias' => 'foobar'));
    
    $container->setDefinition('acme_cms.defunct_route_handler.remove', $definition);
    

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.