1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. This forum has been archived. New threads and replies may not be made. All add-ons/resources that are active should be migrated to the Resource Manager. See this thread for more information.

[Guide] Override default XenForo routes (using hooks)

Discussion in 'Development Tutorials [Archive]' started by CJ.Wurtz, Nov 16, 2011.

  1. CJ.Wurtz

    CJ.Wurtz Member

    I made a post for this in another thread about renaming the "members" route to something else, and was asked to create a new thread about it. That is to say instead of "http://yoursite.com/xenforo/members/username.id" you can make it "http://yoursite.com/xenforo/users/username.id". In theory the method I am about to explain can be used to override any default routes (potentially custom ones as well, but I haven't tried that).

    Note: I assume you have a working directory for files with the addon already set up.

    Step 1)
    We need to create a new listener, so in lets create a file "MyMod/Listener/LoadRoutePrefix.php", adding the following code to the file:
    PHP:
    <?php
    class MyMod_Listener_LoadRoutePrefix
    {
        
    /**
        * Instruct the system that XenForo_ControllerPublic_Member
        * should be extended by Dev_ControllerPublic_Member
        *
        * @param string $class
        * @param array $extend
        */
        
    public static function extendMembersRoute($class, array &$extend)
        {
            if (
    $class == 'XenForo_Route_Prefix_Members')
            {
                
    $extend[] = 'MyMod_Route_Members';
            }
        }
    }
    ?>
    Step 2)
    Now we need to override the default route, in this guide it will be the "members" route.
    Lets create the file, "MyMod/Route/Members.php", adding the following code to it.
    PHP:
    <?php
    class MyMod_Route_Members extends XFCP_MyMod_Route_Members
    {
        
    /**
        * Match a specific route for an already matched prefix.
        *
        * @see XenForo_Route_Interface::match()
        */
        
    public function match($routePathZend_Controller_Request_Http $requestXenForo_Router $router)
        {
            
    $action $router->resolveActionWithIntegerParam($routePath$request'user_id');
            return 
    $router->getRouteMatch('XenForo_ControllerPublic_Member'$action'members');
        }
     
        
    /**
        * 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)
        {
            
    $outputPrefix "players"// this is what "members" will be renamed to
            
    return parent::buildLink($originalPrefix$outputPrefix$action$extension$data$extraParams);
        }
    }
    ?>
    You can change $outputPrefix to be whatever new name for the route that you would like.

    Step 3)
    Now we need to create a route for the new name we will be using instead of the default one (In this example "players"). We'll follow the normal file naming convention and create a file called "MyMod/Route/Players.php", adding the following code to it:
    PHP:
    <?php
    class MyMod_Route_Players implements XenForo_Route_Interface
    {
        
    /**
        * Match a specific route for an already matched prefix.
        *
        * @see XenForo_Route_Interface::match()
        */
        
    public function match($routePathZend_Controller_Request_Http $requestXenForo_Router $router)
        {
            
    $action $router->resolveActionWithIntegerParam($routePath$request'user_id');
            return 
    $router->getRouteMatch('XenForo_ControllerPublic_Member'$action'players');
        }
     
        
    /**
        * 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 (isset(
    $extraParams['page']))
            {
                if (
    strval($extraParams['page']) !== XenForo_Application::$integerSentinel && $extraParams['page'] <= 1)
                {
                    unset(
    $extraParams['page']);
                }
            }
     
            return 
    XenForo_Link::buildBasicLinkWithIntegerParam($outputPrefix$action$extension$data'user_id''username');
        }
    }
    ?>
    The above code is basically the code from "Xenforo/Route/Prefix/Members.php", with some modifications.

    Step 4)
    Now we need to create the listener for the hook that will change the "members" route to be "players".

    Go into the admin panel -> "Development" -> "Code Event Listeners"

    Set the "Listen to Event" field to: "load_class_route_prefix"
    Set the "Execute Callback" field to: "MyMod_Listener_LoadRoutePrefix"::"extendMembersRoute"

    Step 5)
    Lastly we need to add the new "players" route.

    In the admin panel go to -> "Development" -> "Route Prefixes"

    Set the "Route Prefix" to "players" (or whatever you set $outputPrefix to in step 2)

    That's It!

    ---------------------------

    Basically this will still use the default XF route prefix for "members" except it will change it to "players" (or whatever you set it to), when it builds the links. So assuming everywhere on the forum you are using "{xen:link members}" it should automatically redirect the link. And then when you go to that URL, the code above is a copy of the members route, so you'll need to keep "MyMod/Route/Members.php" up to date with whatever is in "XenForo/Route/Prefix/Members.php" when you upgrade, although I can't see it changing that often. You can probably just call the parent for the match() method as well in the "Player.php" (or whatever you want to call yours), however I needed to add a bunch of other options so I need to route mine to a different controller, so I didn't do it that way. Should just be a matter of calling the parent match() method, and then updating the "majorSection" or the router object to whatever you rename it to.

    If your forum has been around for a while, you will probably want to do some mod_rewrites on the existing "members" URLs, as people could still be linking to them, however they should still work just fine since we didn't do any code modifications to them.

    Anyway, I hope that helps. Let me know if you have any questions or if anyone sees a problem with my implementation I would appreciate if you point it out. I did this back almost two months ago. I haven't noticed any problems since, but my site is still in development so I can't say this has been 100% tested yet. Lastly sorry for the delay of making a thread about this, I've been quite busy.
     
    Earl, Sadik B, Fuhrmann and 4 others like this.
  2. Floris

    Floris Guest

    Very awesome. Thanks for writing this out.
     

Share This Page