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

How to Add More Actions to an Existing Controller

Discussion in 'Official Development Tutorials and Resources' started by Kier, Jan 27, 2011.

  1. Kier

    Kier XenForo Developer Staff Member

    Some add-ons warrant having their own controllers, but others provide little snippets of functionality that don't really need to have their own route prefix and controller. For these, it can be useful to add their actions to an existing controller.

    For example, you might want to have a new member action that simply displays a member's username and user title, and have it respond to requests for /members/{username}.{user_id}/title. The XenForo code event listener system makes this easy to do, without having to go and edit the existing controller code. Let's see how we can go about adding an additional action to the XenForo_ControllerPublic_Member class to achieve our goal.

    We will start by creating our extended controller class. This will act as though it has extended the member controller, inheriting all of XenForo_ControllerPublic_Member's methods and properties. Normally, a class like this would be declared as follows:
    PHP:
    class Dev_ControllerPublic_Member extends XenForo_ControllerPublic_Member
    But for a dynamic system where there might be dozens of classes attempting to extend the member controller, this is unworkable.

    Instead, we must make use of the XenForo Class Proxy system, which allows the system to effectively have multiple inheritance capabilities. To use it, we must declare the class as ClassName, and have it extend XFCP_ClassName, like this:
    PHP:
    class Dev_ControllerPublic_Member extends XFCP_Dev_ControllerPublic_Member
    Don't worry that the declaration does not mention XenForo_ControllerPublic_Member, we'll handle that later.

    We now need to define our action and our extended controller is done.
    PHP:
    <?php

    class Dev_ControllerPublic_Member extends XFCP_Dev_ControllerPublic_Member
    {
        public function 
    actionTitle()
        {
            
    $userId $this->_input->filterSingle('user_id'XenForo_Input::UINT);
            
    $user $this->getHelper('UserProfile')->assertUserProfileValidAndViewable($userId);

            return 
    $this->responseView(
                
    'Dev_ViewPublic_Member_Title''dev_member_title',
                array(
    'user' => $user)
            );
        }
    }
    Next, we need to tell XenForo that you intend for Dev_ControllerPublic_Member to extend XenForo_ControllerPublic_Member. In the Development tab of the XenForo Admin Control Panel, create a new Code Event Listener. Tell it to listen to load_class_controller and give it the name of a class and method that you will create next in order to do specify the extension. When you're done, save the event listener.

    Screen shot 2011-01-27 at 13.57.12.png

    Finally, we need to create Dev_Listener_LoadClassController::extendMemberController() as specified in the code event listener. This will be a very simple class with a single method that simply sets an entry in an array if the class name passed to it matches the one we want.
    PHP:
    <?php

    class Dev_Listener_LoadClassController
    {
        
    /**
         * Instruct the system that XenForo_ControllerPublic_Member
         * should be extended by Dev_ControllerPublic_Member
         *
         * @param string $class
         * @param array $extend
         */
        
    public static function extendMemberController($class, array &$extend)
        {
            if (
    $class == 'XenForo_ControllerPublic_Member')
            {
                
    $extend[] = 'Dev_ControllerPublic_Member';
            }
        }
    }
    With that class and method created, we can now request /title as an action from the members route prefix and have it perform our actionTitle() controller action. Hooray!

    Screen shot 2011-01-27 at 14.11.44.png

    It is worth noting that the principles described here can apply to many of XenForo's important classes. You can extend Controller, DataWriter, Model, View, RoutePrefix and several other types of class using the very same methods as were used to add more methods to the controller in this tutorial.
     
    wang, Eagle, Geca and 18 others like this.
  2. ragtek

    ragtek Guest

    Quick Note:

    This tutorial doesn't work:p

    You need to create as FIRST the file and then you can create the event listener in the acp.

    If the file doesn't exist, xenforo wont save the event listener
     
    Sean Kendle likes this.
  3. Kier

    Kier XenForo Developer Staff Member

    Meh, pedantic.
     
    Rigel Kentaurus likes this.
  4. ragtek

    ragtek Guest

    Sean Kendle likes this.
  5. EQnoble

    EQnoble Well-Known Member

    If I was trying to add some other functionality to the uploader, is this thread a good place to start?
     
  6. Kier

    Kier XenForo Developer Staff Member

    Depends what you want to do?
     
  7. EQnoble

    EQnoble Well-Known Member

    I am trying to make my addon use the xf uploader instead of my standalone uploader.php.

    I need to use 4 file types not accepted by default and each one upon finishing uploading should display text that can be copied or simply be clicked to insert into the editor like an image upload would be.
     
  8. Kier

    Kier XenForo Developer Staff Member

    It sounds like you're going to need a lot more than just an extended controller to be honest.
     
  9. Panupat

    Panupat Well-Known Member

    Hi Kier.

    Can you demonstrate a bit how to add some extra condition checker to use in the template? For example, when looping $threads, how can I have an extra <xen:if is="{$thread.myCondition}"> ?
     
  10. Kier

    Kier XenForo Developer Staff Member

    I'm not sure I fully understand the question, but I will try to answer - you may check any available data using the standard <xen:if ... > tag. If you need to check other data, you need to add that data to the view parameters in an extended controller.
     
  11. EQnoble

    EQnoble Well-Known Member

    I figured as much but I have no clue where to start. :)

    If you we're to look at my uploader.php that does the complete of what I need it to for me to consider my addon done for now, could you sum up what I would need to do generally or tell me if it is something that is way beyond my scope of knowledge at this point?

    I am calling the uploader into the sidebar wrapped in an iframe and I don't know really that is the best way to do it..if there is nothing wrong with doing that for now (I am asking here) I suppose I could just use the same method I was using before unless there is something utterly wrong with doing it that way.
     
  12. Kier

    Kier XenForo Developer Staff Member

    I can't really comment on whether anything is beyond your ability to achieve, but I will say that extending the XenForo uploader is not for the faint of heart. If your current uploader is working, I'd say you've done well and there's no real imperative to change it. :)
     
    EQnoble likes this.
  13. EQnoble

    EQnoble Well-Known Member

    Well that is a relief to hear let me tell you (not editing the uploader part but that if mine works for it's purposes to use it)...I mean I don't run away from things much but I will take your word on it. Besides, I can always upgrade the mod later once I figure out what I am doing. (And now I can update Xenforo and not have to redo any template edits :D, xen hooks are my new best friend.)

    Well then...now I am going to tie in my uploader and call it an addon for now.

    Thanks!

    :D
     
    Kier likes this.
  14. Panupat

    Panupat Well-Known Member

    Hi Kier. I mean I want to add extra data in addition to the already available ones.
     
  15. Kier

    Kier XenForo Developer Staff Member

    You will need to fetch that extra data with an extended controller, unless the data simply appears in the thread table, in which case it may be fetched automatically by the existing code (due to SELECT *)
     
  16. nrep

    nrep Well-Known Member

    I can't seem to get this working in 1.1, I just get a generic template page when requesting xxxxxx/title - it's doesn't even got the username in the breadcrumb. Has anyone else got this working or have it available as a plugin? I've created the Dev/ControllerPublic/Member.php and Dev/Listener/LoadClassController.php files according to the instructions here and added the listener.
     
  17. Fuhrmann

    Fuhrmann Well-Known Member

    Have you created the template?

    dev_member_title
     
    esbes and nrep like this.
  18. nrep

    nrep Well-Known Member

    Thanks Fuhrmann - I've not created that! I'll do that now and continue working on it :)
     
    Fuhrmann likes this.
  19. DeltaHF

    DeltaHF Well-Known Member

    This is probably obvious to everyone else, but as a beginner, it wasn't clear to me how or where the above code defined "/title" as a new URL path in the software. After some inspection and testing, apparently it's pulled from the method name, actionTitle().

    I was adding an action to another ControllerPublic and found it to function the same way, although it's still not clear to me exactly how this system works.
     
    rugk, fly and Fuhrmann like this.
  20. LordsKing

    LordsKing Active Member

    Hi Kier :)
    And for add a route like this : domain.com/account/RouteHere How can I Do that ?

    Thanks
     

Share This Page