Skip to content

Commit 71a9a04

Browse files
authored
Converted from existing J4 Document
This is just to test to see how to do conversion of an existing tutorial goes using pandoc.
1 parent d28031a commit 71a9a04

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed

docs/general-concept/dependencies.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,169 @@ Description of dependency injection in Joomla
66
This 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

Comments
 (0)