Загрузка файлов с помощью composer

PHP содержит два метода для загрузки файлов : include and require. Начиная с php5 между ними нет большой разницы - оба подгружают файл имя которого передано. Современные php фреймворки содержат сотни файлов. Значит, где-то есть файл с сотнями инклудов?

Нет. Вместо этого в php есть механизм работы с автозагрузчиком файлов. Когда php обращается к имени класса, он проверяет знае ли он, что это за класс. Если класс неизвестен, то php обращается к автозагрузчику чтобы найти нужный класс и загрузить класс.

Такое поведение позволяет создавать любые удобные структуры проектов. С другой стороны, такое поведение не позволяет иметь два класса с одним именем ( и namaspace), но с разными телами. Это в частности не позволяет поставить две версии одного пакета через composer( в отличии от nodejs).

Одним из самых распространенных загрузчиков является composer autoloader. Его можно использовать отдельно от фреймворков и больших проектов, поэтому я решил рассказать про работу с ним.

Сomposer autoloader имеет 5 основных секций:

{
    "autoload": {
        "psr-4": {"Acme\\": "src/"},
        "psr-0": {
            "MyVendor": "vendor/",
            "Monolog\\": ["src/", "lib/"]
        },
        "classmap": ["src/", "lib/", "Something.php"],
        "files": ["src/MyLibrary/functions.php"],
        "exclude-from-classmap": ["/Tests/", "/test/", "/tests/"]
    }
}

Каждая из них предназначена для загрузки своих типов файлов.

  • "exclude-from-classmap": содержит список файлов и папок, которые должны быть исключены из автолоудера. Например файл деклараций для подсветки в IDE.
  • "files": содержит список файлов, которые дожны быть подключены сразу, в месте подключения автолоудера. Например файлы конфигов.
  • "classmap": содержит те имена классов, которые были названы ни по стандарту psr-0, ни по стандарту psr-4. Например вы можете назвать класс по какому, то принятому у вас в компании стандарту и composer все равно его загрузит.
  • "psr-0": содержит имена файлов и папок, в которых лежат классы формата psr-0. В psr-0 полностью определённое пространство имён и имя класса должны иметь следующую структуру: "\()*".
  • "psr-4": содержит имена файлов и папок, в которых лежат классы формата psr-4. В psr-4 полностью определённое имя класса должно иметь следующую структуру: "\<ПространствоИмён>(\<ПодпространствоИмён>)*\<ИмяКласса>". Фраза подпространство имен немного вводит в замешательство, но если посмотреть на примеры, то все становится понятно(пример взят с оффициального сайта pfg):
<?php
namespace Example;

/**
 * An example of a general-purpose implementation that includes the optional
 * functionality of allowing multiple base directories for a single namespace
 * prefix.
 * 
 * Given a foo-bar package of classes in the file system at the following
 * paths ...
 * 
 *     /path/to/packages/foo-bar/
 *         src/
 *             Baz.php             # Foo\Bar\Baz
 *             Qux/
 *                 Quux.php        # Foo\Bar\Qux\Quux
 *         tests/
 *             BazTest.php         # Foo\Bar\BazTest
 *             Qux/
 *                 QuuxTest.php    # Foo\Bar\Qux\QuuxTest
 * 
 * ... add the path to the class files for the \Foo\Bar\ namespace prefix
 * as follows:
 * 
 *      <?php
 *      // instantiate the loader
 *      $loader = new \Example\Psr4AutoloaderClass;
 *      
 *      // register the autoloader
 *      $loader->register();
 *      
 *      // register the base directories for the namespace prefix
 *      $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src');
 *      $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests');
 * 
 * The following line would cause the autoloader to attempt to load the
 * \Foo\Bar\Qux\Quux class from /path/to/packages/foo-bar/src/Qux/Quux.php:
 * 
 *      <?php
 *      new \Foo\Bar\Qux\Quux;
 * 
 * The following line would cause the autoloader to attempt to load the 
 * \Foo\Bar\Qux\QuuxTest class from /path/to/packages/foo-bar/tests/Qux/QuuxTest.php:
 * 
 *      <?php
 *      new \Foo\Bar\Qux\QuuxTest;
 */

Сomposer autoloader имеет два варианта генерации файлов:

> composer dumpautoload # простой вариант
> composer dumpautoload -o # вариант с оптимизацией

При простом варианте, композер просто запоминает какие папки есть в проекте, какие неймспесы в каких папках лежат. При обращении к классу, composer autoloader по неймспейсу находит нужную папку и файл. Основным минусом такого варианта является то, что композер при каждой загрузке файла проверяет, есть ли такой файл. Проверка существования файла - это достаточно медленная операция

В оптимизированном варианте композер создает массив всех файлов и классов, которые есть в проекте. При обращении к классу из массива получается имя файла и файл загружается. При этом время загрузки файлов уменьшается почта в 2 раза. Однако при этом для большого проекта значительное время может занимать процесс генерации массива.

Сomposer один из тех проектов, который изменил почти все в мире php. Использование всех его возможнстей позволит упростить процесс разработки и сделать его значительно более понятным и приятным.

Posted in PHP on Apr 02, 2016

comments powered by Disqus