@@ -6,3 +6,169 @@ Description of dependency injection in Joomla
66This page is unfinished, please use the ** Edit this Page** link at the bottom of this page to help make it more useful.
77
88:::
9+
10+ ## Introduction
11+
12+ Joomla 4 introduces the practice of Dependency Injection Containers
13+ (DIC's) into Joomla. This article aims to explain why we are introducing
14+ them and how to use them in Joomla.
15+
16+ DIC's have been around in the PHP ecosystem for a long time now to
17+ support the goals of dependency injection. For example Symfony
18+ [ introduced the concept
19+ in 2009] ( http://fabien.potencier.org/do-you-need-a-dependency-injection-container.html ) .
20+
21+ There's a variety of reasons why now is the right time to introduce
22+ these into Joomla 4:
23+
24+ 1 . ** Testing** - one of the themes of Joomla 3 has been buggy releases.
25+ We need to be able to test classes and components in an easier
26+ fashion. Dependency injection allows significantly easier injection
27+ of Mock classes hopefully allowing us to reduce the amount of bugs.
28+ 2 . ** Reduce the amount of magic in Joomla** - Joomla has a large number
29+ of magic files you need to guess the names of. This increases the
30+ amount of time people new to Joomla have to take researching these
31+ conventions. Exposing a concrete class in extensions allows us to
32+ easily test extensions compatibility with other extensions (for
33+ example categories and associations).
34+
35+ ## The global container
36+
37+ The Global Dependency injection is very loosely a replacement for the
38+ JFactory class. However it shouldn't be mistaken for a direct
39+ replacement.
40+
41+ So for example in your Controllers in the CMS instead of substituting
42+
43+ ``` php
44+ \Joomla\CMS\Factory::getDocument()
45+ ```
46+
47+ consider using
48+
49+ ``` php
50+ $this->app->getDocument()
51+ ```
52+
53+ . This uses the injected application and therefore allows for easier
54+ testing.
55+
56+ ### Creating an object in a container
57+
58+ To place something in the Global DIC the most simple way is to pass in
59+ an anonymous function. An example for a logger is below
60+
61+ ``` php
62+ // Assuming we have an instance of a Joomla Container
63+ $container->share(
64+ LoggerInterface::class,
65+ function (Container $container)
66+ {
67+ return \Joomla\CMS\Log\Log::createDelegatedLogger();
68+ },
69+ true
70+ );
71+ ```
72+
73+ The share function takes two compulsory parameters and an optional third
74+ parameter.
75+
76+ - A name for the service is nearly always the class name that you're
77+ creating
78+ - An anonymous function takes a single parameter - the container
79+ instance (this allows you to retrieve any dependencies out the
80+ container). The return is the service that you want to place into
81+ the container
82+ - (optional) This boolean controls whether the service is protected
83+ (i.e. whether anyone else is allowed to override it in the
84+ container). Generally for Joomla core services, such as session
85+ objects, this is true.
86+
87+ Let's now look at a more complicated
88+ example:
89+
90+ ``` php
91+ $container->alias('AmazingApiRouter', Joomla\CMS\Router\ApiRouter::class)
92+ ->share(
93+ \Joomla\CMS\Router\ApiRouter::class,
94+ function (Container $container)
95+ {
96+ return new \Joomla\CMS\Router\ApiRouter($container->get(\Joomla\CMS\Application\ApiApplication::class));
97+ },
98+ true
99+ );
100+ ```
101+
102+ Here you can see we've done two extra things - we've started using
103+ dependencies (the api router gets the api application out the container)
104+ and we've also created an alias for the ApiRouter. That means whilst the
105+ container recognises that if it needs to build an ApiRouter instance it
106+ can do that. But in our code to keep things simple we can also run
107+
108+ ``` php
109+ Factory::getContainer()->get('AmazingApiRouter')
110+ ```
111+
112+ to retrieve our router.
113+
114+ Whilst in Joomla our providers can look more complicated than this
115+ because the logic to create objects inside the anonymous function is
116+ more complicated - all of them follow this base idea.
117+
118+ ### Providers
119+
120+ Providers in Joomla are a way of registering a dependency into a service
121+ container. To do this create a class that implements
122+
123+ ``` php
124+ Joomla\DI\ServiceProviderInterface
125+ ```
126+
127+ . This gives you a register method which contains the container. You can
128+ then use the share method again to add any number of objects into the
129+ container. You can then register this into the container with the
130+ \`\\ Joomla\\ DI\\ Container::registerServiceProvider\` method in the
131+ container. You can see where we register all the core service providers
132+ [ here in the \\ Joomla\\ CMS\\ Factory::createContainer
133+ method] ( https://github.com/joomla/joomla-cms/blob/4.0-dev/libraries/src/Factory.php#L570-L594 )
134+
135+ ## Component Containers
136+
137+ Every component also has its own container (which is located in the
138+ administrator section of Joomla). However this container is not exposed.
139+ It's just there to get the system dependencies and allow a class to
140+ represent your extension. This class is the Extension class and at a
141+ minimum must implement the relevant extensions type interface. For
142+ example a component must implement the
143+
144+ ``` php
145+ \Joomla\CMS\Extension\ComponentInterface
146+ ```
147+
148+ (found on [ here on
149+ GitHub] ( https://github.com/joomla/joomla-cms/blob/4.0-dev/libraries/src/Extension/ComponentInterface.php ) ).
150+ For full information on implementing this in your extension, we
151+ recommend reading [ Developing an MVC
152+ Component] ( S:MyLanguage/J4.x:Developing_an_MVC_Component " wikilink ")
153+
154+ ### Using a component container in another extension
155+
156+ You can easily grab the container of another extension through the
157+ CMSApplication object. For
158+ example
159+
160+ ``` php
161+ Factory::getApplication()->bootComponent('com_content')->getMVCFactory()->createModel('Articles', 'Site');
162+ ```
163+
164+ Will get the com\_ content container, get the MVC Factory and get the
165+ ArticlesModel from the frontend of Joomla. And this will work in any
166+ extension in frontend, backend or the API of Joomla (unlike the old
167+ LegacyModel::getInstance() method)
168+
169+ ## Read More
170+
171+ There's a great example in the Joomla Framework docs on why Dependency
172+ Injection is good for your Application and how DIC's help structure it.
173+ [ Read it
174+ here] ( https://github.com/joomla-framework/di/blob/2.0-dev/docs/why-dependency-injection.md )
0 commit comments