Understanding the XenForo Class Proxy System

Understanding the XenForo Class Proxy System


Well-known member
King Kovifor submitted a new resource:

Understanding the XenForo Class Proxy System - A brief explaination of XenForo's add-on execution chain.

Disclaimer: This is a technical explaination and is geared towards developers. A working knowledge of PHP, OOP, and MVC is assumed.

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)....
Read more about this resource...


Well-known member
It depends on what you are trying to do. The Class Proxy System is designed to allow extension of a pre-existing class. So if you wanted to add an action to threads, you need to extend XenForo_ControllerPublic_Thread. This is where you use the class proxy (as described).

If you are created MyAddon_ControllerPublic_NEWCONTROLLER, you will extend Abstract directly.


Well-known member
I saw some addons updated for xenforo 1.2 but without using hints. Hints make programming much easier, it is also easier to understand what you are doing when you are a beginning to program for xenforo, as it is pointing out: This listener is just for this one existing xenforo class, the class you mention in the hint field. Also the Listener file is much easier to understand using hints. Maybe you could point that out in the explanation.


Well-known member
Both work, however, I still feel that the way it describes it in the article is clearer and easier to understand in relation to what is actually occurring when someone is first attempting to learn the system. I may add in a comment about hints later.
"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."

Any chance you could add in an example of exactly how to do that in your example code? If it should always happen, then it stands to reason that it would happen before or after the comment saying "// add-on code". I'm not entirely sure how to do that.

Here's another question. It seems like these functions are running separately from one another. What I want to be able to do is to read a post as it's posted, run through some keywords and email certain people if those keywords are used. What I need to know is, is there any way to use the variables that are already set in a function? Or would I have to re-run the same code again?

Basically, I've extended XenForo_ControllerPublic_Forum::actionAddThread(), and I need to get the message text, and the thread info (I assume I need to run the same checks (if (!$this->_getThreadModel()->canViewThread($thread, $forum))), right? I wouldn't want to fire my code off if the thread/post won't be created.

So, should I just extend that function directly and overwrite it, copying the same code and then adding my own at the end? Or is there some way to say, "first, run the default function, then run this function and keep/pass the variables"?


Well-known member
You only have access to the return of the function. You have access to the input values, but need to write your own code to fetch them.

The function order is dependent on the call tree and where you place the call to parent::function().
So I only get this back from XenForo_ControllerPublic_Forum::actionAddThread() a copy of the $controllerResponse object:

return $this->responseRedirect(
            new XenForo_Phrase('your_thread_has_been_posted')
So, it looks like I have to parse the input, but since the function is running on the first line, then I can assume that the post/thread has been created successfully? I just don't want to recreate much of the code in that function if it's unncessary. Am I understanding this correctly finally?
Hello Guys,

I'm having bit of difficult time understanding the XFCP system.

@Jeremy, can you please explain what is the benefit of creating blank proxy class? Don't you think so the following class hierarchy should do the required stuff?
  • XenForo_Controller
  • XenForo_ControllerPublic_Abstract
  • XenForo_ControllerPublic_Thread
  • RandomAddon_ControllerPublic_Thread
  • YouAddon_ControllerPublic_Thread
  • MyAddon_ControllerPublic_Thread
So, I just don't getting the point of creating blank proxy classes, if every class extend the previous class in the hierarchy, we could achieve the same using above list as well.


Well-known member
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.
So, it won't be a problem if you do it without proxy classes, if you were the only one who extends that classes. But not only you will want extend classes, other developers will want it too. And then there could be a problem when 2 or more people extend the same classes. At least this is what I understood and why the XFCP is introduced.
@sbj thanks for the reply.

Yeah, I understand that there's a problem when 2 or more addon extend the same class. But, what I'm confused about is why creating blank proxy classes. Can't we use just the following hierarchy without proxy classes?

  • XenForo_Controller
  • XenForo_ControllerPublic_Abstract
  • XenForo_ControllerPublic_Thread
  • RandomAddon_ControllerPublic_Thread
  • YouAddon_ControllerPublic_Thread
  • MyAddon_ControllerPublic_Thread

MyAddon_ControllerPublic_Thread extends YouAddon_ControllerPublic_Thread
YouAddon_ControllerPublic_Thread extends RandomAddon_ControllerPublic_Thread
RandomAddon_ControllerPublic_Thread extends XenForo_ControllerPublic_Thread

and so on....

Why we just create blank proxy classes in between?


Well-known member
I'm also new to this stuff, so I could be wrong, but your way makes no sense at all.

Cause with the way you do it, you require that the user must have installed other addons, so the last one in the hiararchy can extend the one above him.

In this scenario MyAddon_ControllerPublic_Thread would only work if a class called YouAddon_ControllerPublic_Thread exists. If it doesn't, then your addon won't work as the parent class is not existing. And by the way how do you know the name of other addons' class names? First of all you need to know their exact name, so you can extend them. And again, if u knew their name, why do you make your addon dependant to other addons, cause if they are not installed, your addon won't work.

And let's say you know other addons' class names and you do this scenario, do you really want to inherit their methods and attributes? Cause when you extend them, all of the parent classes stuff are open to you. But he could have declared abstract classes. So as you extend their class, you are forced to declare all the methods used in the parent, you must also declare them.

So the idea of extending other addons classes makes no sense, as it would not work (you don't know their class names and even if you do, they are maybe not installed) and it would just hurt your class.
The idea of extending the grandparent class, e.g. XenForo_ControllerPublic_Thread, so all addons extend this class would not work, as the parent would have many children and it would get problematic as in PHP you don't have multiple inheritance classes.
So XF introduced the proxy classes as a solution. Now everybody can extend whatever core class they want, and no addon classes would interfere with each other.