XF 2.2 Is there an already best practice to do dependency injection in XF?

Cylon

Member
Hi!
I'm in the process of developing an addon. And I have wroten many helper classes to perform some tasks. These classes are not Repositories, nor Finders, nor Entities. Because of that when I need one of these helper classes, I get an instance of them with new MyHelperClass() (for the finders and repositories, I use the xf way of getting instances).

I was wondering if there is already a way to get an instance of my helper classes per DI, o maybe there is a recommended way? When not, then I'm considering implementing a third party DI manager, or not implementing it at all, because they are only five or six classes, without complex interdependencies... Maybe in the future the complexity of my addon grows... but not at the moment.

What do you think?

Thanks.
 

Chris D

XenForo developer
Staff member
XF supports dependency injection containers.

The recommended way to do this for add-ons is to create an app_setup event listener which gives you access to the XF\App object and the dependency injection XF\Container object.

The method would look something like this:

PHP:
public static function appSetup(\XF\App $app)
{
   $container = $app->container();

   $container['yourHelperClass'] = function($c) use ($app)
   {
      return new YourHelperClass();
   };
}

You can then call your helper class from anywhere like this:

PHP:
$app = \XF::app();
$yourHelperClass = $app['yourHelperClass'];

By default - though it can be toggled - the object is cached in the yourHelperCache entry in the container which means you can call that same instance of the object anywhere in your code without it instantiating multiple instances of it.
 
Last edited:

Chris D

XenForo developer
Staff member
Just for the avoidance of doubt there I accidentally submitted the message too early. I've finished now :p

Hope that helps :)
 

Cylon

Member
Thank you very much for the example! It seems a very convenient and easy way to replace all my "new MyHelperClass()".

Thanks a lot!
 

Sim

Well-known member
There is also a very nice pattern used in the core of XF called a "SubContainer" - which is a kind of nested container that you define to hold your own dependencies.

I've found SubContainers very helpful in my addons - you can use them to define as many dependencies as you like without needing to worry about container name clobbering.

Have a look at the classes under XF\SubContainer\* ... they extend XF\SubContainer\AbstractSubContainer.

You can also look through my addons to see examples of how I use them - my Geoblock Registrations, CLI Job Runner, Known Bots, Log Digest, Monolog, SparkPost Mail and Whats New Digest addons all use SubContainers.

I could have achived all of this without using SubContainers - I just find them convenient and it gives me confidence to know that I can throw anything into my subcontainer and it won't affect anything else in the core or any other addon, because it is self-contained and independent of the main container.

Dependency injection in general is extremely useful for unit testing too - it makes it trivial to swap out real classes for mocks so you can isolate the class you are testing.
 

Cylon

Member
Thanks again for the answers, I will try to include this way of programming in my (never-ending) addon.
 
Top