• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Can you do nested/sub routes?

Jaxel

Well-known member
#1
I can easily make a route to "/xenforo/media/" with:
Code:
<?php

class EWRmedio_Route_Media implements XenForo_Route_Interface
{
	public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
	{
		$action = $router->resolveActionWithIntegerParam($routePath, $request, 'media_id');
		$action = $router->resolveActionAsPageNumber($action, $request);
		return $router->getRouteMatch('EWRmedio_ControllerPublic_Media', $action, 'media');
	}

	public function buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, array &$extraParams)
	{
		$action = XenForo_Link::getPageNumberAsAction($action, $extraParams);
		return XenForo_Link::buildBasicLinkWithIntegerParam($outputPrefix, $action, $extension, $data, 'media_id', 'media_title');
	}
}
But what if I wanted to make a nested/sub route to "/xenforo/media/category/"? How would I do this? The problem is that every time you go to such an url, it would hit the original "media" router and ignore the "media/category" router. Because of this, I've been forcing my router to "index" instead of "$action" and simply doing the routing manually in my mods... this is the wrong way.
 

Mike

XenForo developer
Staff member
#3
You can really build the URLs and then parse them however you want. We have standard approaches that we use, but if you don't want to follow them, you don't have to -- however, you will have to write code to do that.

You can see an example of this in XenForo_Route_PrefixAdmin_Permissions.
 

Jaxel

Well-known member
#4
Mike, that was pretty much exactly what I was looking for..

Code:
	public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
	{
		$components = explode('/', $routePath);
		$subPrefix = strtolower(array_shift($components));

		switch ($subPrefix)
		{
			case 'category':
				$controllerName = 'EWRmedio_ControllerPublic_Media_Category';
				$majorSection = 'media/category';
				$paramName = 'category_id';
				break;
		}

		if (empty($controllerName))
		{
			return $router->getRouteMatch('EWRmedio_ControllerPublic_Media', 'index', 'media', $routePath);
		}
		else
		{
			$routePath = implode('/', $components);
			$action = $router->resolveActionWithIntegerParam($routePath, $request, $paramName);
			$action = $router->resolveActionAsPageNumber($action, $request);
			return $router->getRouteMatch($controllerName, $action, $majorSection, $routePath);
		}
	}
As you can see, by default, it routes to "EWRmedio_ControllerPublic_Media"; however, if it finds a subprefix it routes differently.
 

Jaxel

Well-known member
#5
Okay... I've figured this out... and I know other people have asked this same question before...

So, here is how to do route matching and link building in a single route prefix file...
Code:
<?php

class EWRmedio_Route_Media implements XenForo_Route_Interface
{
    public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
    {
        $components = explode('/', $routePath);
        $subPrefix = strtolower(array_shift($components));
        $intParams = '';
        $strParams = '';

        switch ($subPrefix)
        {
            case 'comment':        $controllerName = 'Comment';    $intParams = 'comment_id';        break;
            case 'playlist':    $controllerName = 'Playlist';    $intParams = 'playlist_id';        break;
            case 'category':    $controllerName = 'Category';    $intParams = 'category_id';        break;
            case 'user':        $controllerName = 'User';        $intParams = 'user_id';            break;
            case 'keyword':        $controllerName = 'Keyword';    $strParams = 'keyword_slug';    break;
            case 'service':        $controllerName = 'Service';    $strParams = 'service_slug';    break;
        }

        if (!empty($controllerName))
        {
            $routePathAction = implode('/', array_slice($components, 0, 2));
            $action = $router->resolveActionWithIntegerOrStringParam($routePathAction, $request, $intParams, $strParams);
            $action = $router->resolveActionAsPageNumber($action, $request);

            return $router->getRouteMatch('EWRmedio_ControllerPublic_Media_'.$controllerName, $action, 'media', $routePath);
        }
        else
        {
            return $router->getRouteMatch('EWRmedio_ControllerPublic_Media', $action, 'media', $routePath);
        }
    }

    public function buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, array &$extraParams)
    {
        $components = explode('/', $action);
        $subPrefix = strtolower(array_shift($components));

        switch ($subPrefix)
        {
            case 'comment':        $field = 'comment_id';        $title = '';                $type = 'int';    break;
            case 'playlist':    $field = 'playlist_id';        $title = 'playlist_name';    $type = 'int';    break;
            case 'category':    $field = 'category_id';        $title = 'category_name';    $type = 'int';    break;
            case 'user':        $field = 'user_id';            $title = 'username';        $type = 'int';    break;
            case 'keyword':        $field = 'keyword_slug';    $title = '';                $type = 'str';    break;
            case 'service':        $field = 'service_slug';    $title = '';                $type = 'str';    break;
            default:            $field = 'media_id';        $title = 'media_title';
        }

        if (!empty($type))
        {
            $outputPrefix .= '/'.$subPrefix;
            $action = implode('/', $components);
        }

        $action = XenForo_Link::getPageNumberAsAction($action, $extraParams);

        if ($type == 'str')
        {
            return XenForo_Link::buildBasicLinkWithStringParam($outputPrefix, $action, $extension, $data, $field);
        }
        else
        {
            return XenForo_Link::buildBasicLinkWithIntegerParam($outputPrefix, $action, $extension, $data, $field, $title);
        }
    }
}