1. An Nguyen

    An Nguyen bụi Ban quản trị

    22/4/19
    #1

    Understanding the XenForo Class Proxy System



    What is the XenForo Class Proxy System?
    In a nutshell, this system allows several add-ons to extend the same class within XenForo using its code event listener system, which allows an extension chain to be constructed (with the last link in the chain being the class that is instantiated when XenForo creates the necessary class).

    The Listener
    For this example, we will be working with the following listener, which is adding an example class toXenForo_ControllerPublic_Thread's extension chain (this is being executed onload_class_controller):
    PHP:
    1. <?php
    2. class MyAddon_Listener
    3. {
    4.     public static function loadClassController($class, array &$extend)
    5.     {
    6.         if ($class == "XenForo_ControllerPublic_Thread") {
    7.             $extend[] = "MyAddon_ControllerPublic_Thread";
    8.         }
    9.     }
    10. }

    So, if we look into this function we can see that $extend is passed by reference, meaning that any execution of a listener on the load_class_controller code event will receive and modify the same $extend array. So, if this listener executes last, and two others extend XenForo_ControllerPublic_Thread, the array will contain the following elements (in this order):
    • RandomAddon_ControllerPublic_Thread
    • YourAddon_ControllerPublic_Thread
    • MyAddon_ControllerPublic_Thread
    What this means, is that when XenForo attempts to instantiate XenForo_ControllerPublic_Thread it will actually instantiate an instance of MyAddon_ControllerPublic_Thread.

    Resolving the Issue of Multiple Inheritance
    PHP does not have multiple inheritance classes. Each class needs exactly one class to extend, and any class extending a class will not receive any other classes (besides the class its extending's ancestors) functionality. This poses a problem when 2 or more add-ons want to extend the same functionality within XenForo. It isn't possible to have all three instances of the extended XenForo_ControllerPublic_Thread running and have it function properly (for example, getting all 3 changes to return to XenForo_Application to properly display on the front end) without running all three classes in the same execution tree.


    The Solution
    The solution is the Proxy Class system. Any class that is being used as an extension in the listener system should extend a non-existant class of the format XFCP_ClassName. This is the Class Proxy. So, for MyAddon_ControllerPublic_Thread, I want to extendXFCP_MyAddon_ControllerPublic_Thread. So, the code for MyAddon_ControllerPublic_Thread will look like the following:
    PHP:
    1. <?php
    2. class MyAddon_ControllerPublic_Thread extends XFCP_MyAddon_ControllerPublic_Thread
    3. {
    4.     public function actionMyAction()
    5.     { // add-on code}
    6.     }

    The magic of this solution occurs in XenForo_Application::resolveDynamicClass(). What happens is that XenForo fires the necessary code events (in this example, load_class_controller) and retrieves the extension tree for it (the list provided above). What it then does is create the necessary proxy classes and load the necessary extensions into the current execution tree. At the end of this, it returns the last link in the chain to whatever called it to instantiate. By the end, the extension tree will look like this (including XenForo classes), with each list item extending the previous list item:
    • XenForo_Controller
    • XenForo_ControllerPublic_Abstract
    • XenForo_ControllerPublic_Thread
    • XFCP_RandomAddon_ControllerPublic_Thread
    • RandomAddon_ControllerPublic_Thread
    • XFCP_YourAddon_ControllerPublic_Thread
    • YouAddon_ControllerPublic_Thread
    • XFCP_MyAddon_ControllerPublic_Thread
    • MyAddon_ControllerPublic_Thread
    The classes that XenForo creates for the proxies are empty classes that extend the previous link in the chain. An example for XFCP_YourAddon_ControllerPublic_Thread:
    PHP:
    1. <?php
    2. class XFCP_YourAddon_ControllerPublic_Thread extends RandomAddon_ControllerPublic_Thread
    3. { }

    Things to Note While using the Class Proxy System
    • parent::function() should always be called and used (ie, getting the returned view and adding in parameters) and be the return of your extended function. This will allow any other add-ons that function on the same function to properly work with your add-on.
    • No add-on should extend a XenForo class directly (unless the class proxy system doesn't function).
    • If you need your class to execute early in the execution chain, be sure to set your event listener's execution order to a low number. XenForo defaults this to 10 and will execute them with lowest to highest execution order.
     
    Sửa lần cuối: 22/4/19
    Đang tải...
Đã lưu nháp Draft deleted
Đang tải...