Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

autoloader.md 5.5 KiB

pirms 3 gadiem
pirms 3 gadiem
pirms 3 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. Autoloader with Composer
  2. ==========
  3. * [Home](help)
  4. * [Developer Intro](help/Developers-Intro)
  5. Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes.
  6. 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 through `boot.php`.
  7. * [Using Composer](help/Composer)
  8. ## A quick introduction to class autoloading
  9. 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".
  10. 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`)
  11. 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.
  12. For more info about PHP autoloading, please refer to the [official PHP documentation](http://php.net/manual/en/language.oop5.autoload.php).
  13. ### Example
  14. Let's say you have a PHP file in `src/` that define a very useful class:
  15. ```php
  16. // src/ItemsManager.php
  17. <?php
  18. namespace Friendica;
  19. class ItemsManager {
  20. public function getAll() { ... }
  21. public function getByID($id) { ... }
  22. }
  23. ```
  24. The class `ItemsManager` has been declared in the `Friendica` namespace.
  25. 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)
  26. Let's say now that you need to load some items in a view, maybe in a fictional `mod/network.php`.
  27. In order for the Composer autoloader to work, it must first be included.
  28. In Friendica this is already done at the top of `boot.php`, with `require_once('vendor/autoload.php');`.
  29. The code will be something like:
  30. ```php
  31. // mod/network.php
  32. <?php
  33. function network_content(App $a) {
  34. $itemsmanager = new Friendica\ItemsManager();
  35. $items = $itemsmanager->getAll();
  36. // pass $items to template
  37. // return result
  38. }
  39. ```
  40. That's a quite simple example, but look: no `require()`!
  41. If you need to use a class, you can simply use it and you don't need to do anything else.
  42. Going further: now we have a bunch of `*Manager` classes that cause some code duplication.
  43. Let's define a `BaseManager` class, where we move all common code between all managers:
  44. ```php
  45. // src/BaseManager.php
  46. <?php
  47. namespace Friendica;
  48. class BaseManager {
  49. public function thatFunctionEveryManagerUses() { ... }
  50. }
  51. ```
  52. and then let's change the ItemsManager class to use this code
  53. ```php
  54. // src/ItemsManager.php
  55. <?php
  56. namespace Friendica;
  57. class ItemsManager extends BaseManager {
  58. public function getAll() { ... }
  59. public function getByID($id) { ... }
  60. }
  61. ```
  62. 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.
  63. It works with the "BaseManager" example here and it works when we need to call static methods:
  64. ```php
  65. // src/Dfrn.php
  66. <?php
  67. namespace Friendica;
  68. class Dfrn {
  69. public static function mail($item, $owner) { ... }
  70. }
  71. ```
  72. ```php
  73. // mod/mail.php
  74. <?php
  75. mail_post($a){
  76. ...
  77. Friendica\Protocol\DFRN::mail($item, $owner);
  78. ...
  79. }
  80. ```
  81. If your code is in same namespace as the class you need, you don't need to prepend it:
  82. ```php
  83. // include/delivery.php
  84. <?php
  85. namespace Friendica;
  86. // this is the same content of current include/delivery.php,
  87. // but has been declared to be in "Friendica" namespace
  88. [...]
  89. switch($contact['network']) {
  90. case NETWORK_DFRN:
  91. if ($mail) {
  92. $item['body'] = ...
  93. $atom = DFRN::mail($item, $owner);
  94. } elseif ($fsuggest) {
  95. $atom = DFRN::fsuggest($item, $owner);
  96. q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id']));
  97. } elseif ($relocate)
  98. $atom = DFRN::relocate($owner, $uid);
  99. [...]
  100. ```
  101. 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.
  102. But if you want to use classes from another library, you need to use the full namespace, e.g.
  103. ```php
  104. // src/Diaspora.php
  105. <?php
  106. namespace Friendica;
  107. class Diaspora {
  108. public function md2bbcode() {
  109. $html = \Michelf\MarkdownExtra::defaultTransform($text);
  110. }
  111. }
  112. ```
  113. 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
  114. ```php
  115. // src/Diaspora.php
  116. <?php
  117. namespace Friendica;
  118. use \Michelf\MarkdownExtra;
  119. class Diaspora {
  120. public function md2bbcode() {
  121. $html = MarkdownExtra::defaultTransform($text);
  122. }
  123. }
  124. ```
  125. Note that namespaces are like paths in filesystem, separated by "\", with the first "\" being the global scope.
  126. You can go deeper if you want to, like:
  127. ```
  128. // src/Network/Dfrn.php
  129. <?php
  130. namespace Friendica\Network;
  131. class Dfrn {
  132. }
  133. ```
  134. 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`.
  135. or
  136. ```
  137. // src/Dba/Mysql
  138. <?php
  139. namespace Friendica\Dba;
  140. class Mysql {
  141. }
  142. ```
  143. So you can think of namespaces as folders in a Unix file system, with global scope as the root ("\").
  144. ## Related
  145. * [Using Composer](help/Composer)
  146. * [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src)