]> git.mxchange.org Git - friendica.git/blob - doc/autoloader.md
Merge pull request #13146 from MrPetovan/bug/deprecated
[friendica.git] / doc / autoloader.md
1 Autoloader with Composer
2 ==========
3
4 * [Home](help)
5   * [Developer Intro](help/Developers-Intro)
6
7 Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes.
8
9 It's a command-line tool that downloads required libraries into the `vendor` folder and makes any namespaced class in `src` available through the whole application.
10
11 * [Using Composer](help/Composer)
12
13 ## A quick introduction to class autoloading
14
15 The autoloader dynamically includes the file defining a class when it is first referenced, either by instantiating an object or simply making sure that it is available, without the need to explicitly use "require_once".
16
17 Once it is set up you don't have to directly use it, you can directly use any class that is covered by the autoloader (currently `vendor` and `src`)
18
19 Under the hood, Composer registers a callback with [`spl_autoload_register()`](http://php.net/manual/en/function.spl-autoload-register.php) that receives a class name as an argument and includes the corresponding class definition file.
20 For more info about PHP autoloading, please refer to the [official PHP documentation](http://php.net/manual/en/language.oop5.autoload.php).
21
22 ### Example
23
24 Let's say you have a PHP file in `src/` that define a very useful class:
25
26 ```php
27 // src/ItemsManager.php
28 <?php
29 namespace Friendica;
30
31 class ItemsManager {
32         public function getAll() { ... }
33         public function getByID($id) { ... }
34 }
35 ```
36
37 The class `ItemsManager` has been declared in the `Friendica` namespace.
38 Namespaces are useful to keep classes separated and avoid names conflicts (could be that a library you want to use also defines a class named `ItemsManager`, but as long as it is in another namespace, you don't have any problem)
39
40 Let's say now that you need to load some items in a view, maybe in a fictional `mod/network.php`.
41 In order for the Composer autoloader to work, it must first be included.
42
43 The code will be something like:
44
45 ```php
46 // mod/network.php
47 <?php
48
49 use Friendica\App;
50
51 function network_content(App $a) {
52         $itemsmanager = new \Friendica\ItemsManager();
53         $items = $itemsmanager->getAll();
54
55         // pass $items to template
56         // return result
57 }
58 ```
59
60 That's a quite simple example, but look: no `require()`!
61 If you need to use a class, you can simply use it and you don't need to do anything else.
62
63 Going further: now we have a bunch of `*Manager` classes that cause some code duplication.
64 Let's define a `BaseManager` class, where we move all common code between all managers:
65
66 ```php
67 // src/BaseManager.php
68 <?php
69 namespace Friendica;
70
71 class BaseManager {
72         public function thatFunctionEveryManagerUses() { ... }
73 }
74 ```
75
76 and then let's change the ItemsManager class to use this code
77
78 ```php
79 // src/ItemsManager.php
80 <?php
81 namespace Friendica;
82
83 class ItemsManager extends BaseManager {
84         public function getAll() { ... }
85         public function getByID($id) { ... }
86 }
87 ```
88
89 Even though we didn't explicitly include the `src/BaseManager.php` file, the autoloader will when this class is first defined, because it is referenced as a parent class.
90 It works with the "BaseManager" example here and it works when we need to call static methods:
91
92 ```php
93 // src/Dfrn.php
94 <?php
95 namespace Friendica;
96
97 class Dfrn {
98         public static function  mail($item, $owner) { ... }
99 }
100 ```
101
102 ```php
103 // mod/mail.php
104 <?php
105
106 mail_post($a){
107         ...
108         Friendica\Protocol\DFRN::mail($item, $owner);
109         ...
110 }
111 ```
112
113 If your code is in same namespace as the class you need, you don't need to prepend it:
114
115 ```php
116 // include/delivery.php
117 <?php
118
119 namespace Friendica;
120
121 use Friendica\Protocol\DFRN;
122
123 // this is the same content of current include/delivery.php,
124 // but has been declared to be in "Friendica" namespace
125
126 [...]
127 switch($contact['network']) {
128         case NETWORK_DFRN:
129                 if ($mail) {
130                         $item['body'] = ...
131                         $atom = DFRN::mail($item, $owner);
132                 } elseif ($fsuggest) {
133                         $atom = DFRN::fsuggest($item, $owner);
134                         q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id']));
135                 } elseif ($relocate)
136                         $atom = DFRN::relocate($owner, $uid);
137 [...]
138 ```
139
140 This is the current code of `include/delivery.php`, and since the code is declared to be in the "Friendica" namespace, you don't need to write it when you need to use the "Dfrn" class.
141 But if you want to use classes from another library, you need to use the full namespace, e.g.
142
143 ```php
144 // src/Diaspora.php
145 <?php
146
147 namespace Friendica;
148
149 class Diaspora {
150         public function md2bbcode() {
151                 $html = \Michelf\MarkdownExtra::defaultTransform($text);
152         }
153 }
154 ```
155
156 if you use that class in many places of the code and you don't want to write the full path to the class every time, you can use the "use" PHP keyword
157
158 ```php
159 // src/Diaspora.php
160 <?php
161 namespace Friendica;
162
163 use \Michelf\MarkdownExtra;
164
165 class Diaspora {
166         public function md2bbcode() {
167                 $html = MarkdownExtra::defaultTransform($text);
168         }
169 }
170 ```
171
172 Note that namespaces are like paths in filesystem, separated by "\", with the first "\" being the global scope.
173 You can go deeper if you want to, like:
174
175 ```
176 // src/Network/Dfrn.php
177 <?php
178 namespace Friendica\Network;
179
180 class Dfrn {
181 }
182 ```
183
184 Please note that the location of the file defining the class must be placed in the appropriate sub-folders of `src` if the namespace isn't plain `Friendica`.
185
186 or
187
188 ```
189 // src/Dba/Mysql
190 <?php
191 namespace Friendica\Dba;
192
193 class Mysql {
194 }
195 ```
196
197 So you can think of namespaces as folders in a Unix file system, with global scope as the root ("\").
198
199 ## Related
200
201 * [Using Composer](help/Composer)
202 * [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src)