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

Dynamic ControllerPublic

Discussion in 'XenForo Development Discussions' started by silence, Mar 3, 2014.

  1. silence

    silence Well-Known Member

    So here is my actionIndex:
    Code:
        public function actionIndex()
        {
            $sectionId = $this->_input->filterSingle('section_id', XenForo_Input::STRING);
    
            if ($sectionId)
            {
                return $this->responseReroute(__CLASS__, 'section');
            }
    
            $this->canonicalizeRequestUrl(
                XenForo_Link::buildPublicLink('monkey')
            );
    
            $viewParams = array();
    
            return $this->responseView('monkey_ViewPublic_Index', 'monkey_index', $viewParams);
        }
    However, when I do put a parameter in the URL '/monkey/test/' it tells me it cannot find that action defined.
    While that normally makes sense, how would I make it redirect to actionSection if there is something there, since the way I'm doing it isn't working :(

    Thanks!
     
  2. Chris D

    Chris D XenForo Developer Staff Member

    If that isn't working, the problem probably lies within your route prefix controller.
     
  3. silence

    silence Well-Known Member

    I gotta be honest, I'm not 100% clear about the routing system in XF so I can't say I know if that's it :|
    Code:
        /**
         * Match a specific route for an already matched prefix.
         *
         * @see XenForo_Route_Interface::match()
         */
        public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
        {
            $action = $router->resolveActionWithStringParam($routePath, $request, 'section_id');
            return $router->getRouteMatch('monkey_ControllerPublic_Index', $action, 'monkey');
        }
    
        /**
         * Method to build a link to the specified page/action with the provided
         * data and params.
         *
         * @see XenForo_Route_BuilderInterface
         */
        public function buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, array &$extraParams)
        {
            if (is_array($data) && !empty($data['section_id']))
            {
                return XenForo_Link::buildBasicLinkWithStringParam($outputPrefix, $action, $extension, $data, 'section_id');
            }
        }
     
  4. Chris D

    Chris D XenForo Developer Staff Member

    Are you navigating to '/monkey/test/' or '/monkey/test' (without trailing slash)?
     
  5. silence

    silence Well-Known Member

    Without the trailing slash. With the trailing slash it works :confused:
    Uhhh why would this be happening?
     
  6. Chris D

    Chris D XenForo Developer Staff Member

    It's a XenForo... quirk. It's not a bug.

    It's basically as designed.

    I do this in the match() function:

    PHP:
            $parts explode('/'$routePath2);
            if (isset(
    $parts[0], $parts[1]))
            {
                if (
    $parts[0] == 'tags')
                {
                    if (
    utf8_substr($parts[1], -1) != '/')
                    {
                        
    $parts[1] .= '/';
                    }

                    
    $routePath implode('/'$parts);
                }
            }
    That adds the trailing slash if it is missing.
     
    silence likes this.
  7. silence

    silence Well-Known Member

    I'm confused, I don't see it in any of XF's routes nor in any addons I've come across. Also I just plopped that wonderful snippit in but I'm stilling suffering from the same issue.
     
  8. Chris D

    Chris D XenForo Developer Staff Member

    Sorry there's a conditional in it:

    PHP:
    if ($parts[0] == 'tags')
    You don't need that bit. Just the bit inside that statement.

    There are no XF public routes which use resolveActionWithStringParam. They're all in the Admin CP. Search the XenForo/Route directory for resolveActionWithStringParam to see.

    Also, typically, they are used with some sort of action e.g. /edit so the trailing slash issue isn't obvious.

    You will get a route error with:

    http://localhost/admin.php?bb-code-media-sites/youtube

    But not with:

    http://localhost/admin.php?bb-code-media-sites/youtube/
     
  9. silence

    silence Well-Known Member

    Ah that's strange!
    However, it still won't work for me :(
    Code:
        public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
        {
            $parts = explode('/', $routePath, 2);
    
            if (isset($parts[0], $parts[1]))
            {
                if (utf8_substr($parts[1], -1) != '/')
                {
                    $parts[1] .= '/';
                }
    
                $routePath = implode('/', $parts);
            }
    
            $action = $router->resolveActionWithStringParam($routePath, $request, 'section_id');
            return $router->getRouteMatch('monkey_ControllerPublic_Index', $action, 'monkey');
        }
    It doesn't seem to be redirecting me at all like your bug report snippit does so I'm confused.
     
  10. Chris D

    Chris D XenForo Developer Staff Member

    silence likes this.
  11. silence

    silence Well-Known Member

  12. silence

    silence Well-Known Member

    Oh one more thing about that bug report.
    Code:
    return $router->getRouteMatch($controller, $action, 'tab_id');
    You never define controller anywhere so which is used?
     
  13. Chris D

    Chris D XenForo Developer Staff Member

    $controller is passed by reference to the $router->getSubComponentAction function.
     
    silence likes this.
  14. silence

    silence Well-Known Member

    Yeah but if I don't define it in match() it tells me the route could not be found for everything.
     
  15. Chris D

    Chris D XenForo Developer Staff Member

    I think this will work with your original code:
    PHP:
            $parts explode('/'$routePath2);
            if (isset(
    $parts[0]))
            {
                if (
    utf8_substr($parts[0], -1) != '/')
                {
                    
    $parts[0] .= '/';
                }

                
    $routePath implode('/'$parts);
            }
     
    silence likes this.
  16. silence

    silence Well-Known Member

    That completed the process!
    here is the full thing working :)
    Code:
        protected $_subComponents = array(
            'charlist' => array(
                'controller' => 'monkey_ControllerPublic_CharList'
            )
        );
    
        public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
        {
            $controller = 'monkey_ControllerPublic_Index';
    
            $parts = explode('/', $routePath, 2);
            if (isset($parts[0]))
            {
                if (utf8_substr($parts[0], -1) != '/')
                {
                    $parts[0] .= '/';
                }
    
                $routePath = implode('/', $parts);
            }
    
            $action = $router->getSubComponentAction($this->_subComponents, $routePath, $request, $controller);
    
            if (!$action)
            {
                $action = $router->resolveActionWithStringParam($routePath, $request, 'section_id');
            }
    
            return $router->getRouteMatch($controller, $action, $parts[0], $routePath);
    }
     

Share This Page