1. 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?

Discussion in 'XenForo Development Discussions' started by Jaxel, Mar 2, 2011.

  1. Jaxel

    Jaxel Well-Known Member

    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.
     
  2. Onimua

    Onimua Well-Known Member

  3. Mike

    Mike XenForo Developer Staff Member

    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.
     
  4. Jaxel

    Jaxel Well-Known Member

    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.
     
  5. Jaxel

    Jaxel Well-Known Member

    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);
            }
        }
    }
     
    Treasurer, Darkimmortal and Bob like this.

Share This Page