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

Question about resolveDynamicClass()

Discussion in 'XenForo Development Discussions' started by CaseLogic, May 30, 2013.

  1. CaseLogic

    CaseLogic New Member

    I've been going through the source so I can understand the XF architecture, in order to prep myself to start making some new add-ons.

    I was looking through resolveDynamicClass() in order to understand how the autoloading and class proxy stuff works. I get it now, except for the following snippet:

                    foreach ($extend AS $dynamicClass)
                        // XenForo Class Proxy, in case you're wondering
                        $proxyClass = 'XFCP_' . $dynamicClass;
                        eval('class ' . $proxyClass . ' extends ' . $createClass . ' {}');
                        $createClass = $dynamicClass;
    Does this mean that if you create a bunch of classes that get loaded dynamically via listeners, then the LAST dynamic one is the one that gets returned out from this function, instead of the original?

    For example, if the codebase is doing resolveDynamicClass(ControllerPublic_Thread), but I have a class called MyAddon_Controller_Thread that extends it, does that mean this routine will return my child class instead of the originally requested class?

    What's the purpose? Is this to allow the system to return a dynamically created child class instead of the original base, to allow for overloads? What if there are multiple products that are attempting to overload a base class's routine, does that mean the last one loaded is the one who wins?
  2. Jake Bunce

    Jake Bunce XenForo Moderator Staff Member

    The system extends the original class using addon classes. An original class A can be extended with addon classes B and C. If C is the last extension then that is the class that will be returned. Extended classes often call on the parent so that the original code is executed in addition to your code. Here is a code example where my extended class calls on the parent function first, then it executes my code to do additional saving:


    In the case of multiple extensions, all of the extended classes can call on the parent, all the way up the inheritance chain.
  3. CaseLogic

    CaseLogic New Member

    My concern is this: if I develop an addon that extends on ControllerPublic_Thread, then it can safely overload an action. However, what happens if I later install an addon which also extends the ControllerPublic to overload an action? Then this add-on will supersede my addon, and my addon will no longer work correctly because it is not the class that gets returned from this routine.

    Essentially it seems like it's a race to be last when it comes to overloading XF methods?
    xf_phantom likes this.
  4. Jake Bunce

    Jake Bunce XenForo Moderator Staff Member

    That is the expectation when an addon extends a controller action. C calls B, B calls A.
  5. xf_phantom

    xf_phantom Well-Known Member

    Addons should "always" call the parent method, instead of overloading the complete action without calling the parent method.
    With calling the parent method, you make sure that other addons code is called.
    You can change the routine via

    function actionFoo(){
    $parentReturn parent::actionFoo();
    //do now your stuff;
    // you can call methods, change the parent return
    //and last but not least, RETURN it again
    return $parentReturn;
    //you can also set something before you call the parent, to use it later in the model or datawriter
    function actionFoo(){
    $inputFoo $this->_input->filterSingle('foo'.....);
    //you can use globals, or the xenforo_application registry, or use e.g. $_POST inside the datawriter
    $_GLOBALS['foo'] = $inputFoo;

    It's IMO a shame, that there's no official tutorial for this:p
    DeltaHF likes this.
  6. CaseLogic

    CaseLogic New Member

    I don't think I'm understanding, sorry.

    Let's say I have two different addons extending from XenForo_ControllerPublic_Thread. These addons have no knowledge of each other.

    With the way the resolve routine is coded, it will return the last class extended from foreach() out to the code. That means only one of the addons will be able to execute its 'unique' code. The other addon will be superseded and will never execute its code, so the addon will presumably fail. Only if the addons knew about each other could we subvert this. We would have to change it to instead of both extending XenForo_ControllerPublic_Thread, only one would extend the XF class and the other would extend the addon class, i.e. class A extends class B extends XenForo_ControllerPublic_Thread. Then each can run its code then call the parent.

    But if you install two addons from the resources, presumably they have no idea they both exist and only one would work, right?
  7. Jake Bunce

    Jake Bunce XenForo Moderator Staff Member

    No. C extends B extends A. C is returned and instantiated, and C is based on the other two and can call on the other classes through the 'parent' like in my code example:


    Notice the parent being called at the beginning of my action:

    		$response = parent::actionSave();
  8. CaseLogic

    CaseLogic New Member

    I'm at work so I don't have the XF code in front of me to look at. You're saying that if I code up two listeners to setup two classes to extend from XenForo_ControllerPublic_Thread, then it will do

    class C extends class B extends class XenForo_ControllerPublic_Thread

    return C

    and not

    class B extends XenForo_ControllerPublic_Thread
    class C extends XenForo_ControllerPublic_Thread

    return C (masking out B completely)


    I thought that it would do the latter, which would cause the issues I am describing.
  9. Jake Bunce

    Jake Bunce XenForo Moderator Staff Member

    CaseLogic likes this.
  10. CaseLogic

    CaseLogic New Member

    Thanks for your help
  11. tyteen4a03

    tyteen4a03 Well-Known Member

    Plus you have less work when XenForo updates, so you don't have to update the method in case the official one is updated.
    xf_phantom likes this.

Share This Page