Рубрики
Uncategorized

Сколько шагов требуется от платформы symfony до полного проекта

Автор оригинала: David Wong.

о программе php Рамки обоих yii , symfony Или, может быть laravel Мы все увлекаемся своей работой. Для пакета ресурсов, хранящегося в папке поставщик , файлы ввода( index.php возможно app.php ) И мы все встречаемся с ними каждый день. Но действительно ли вы знакомы с этими файлами/папками? Как полный проект развивается из чистой структуры? Какую роль играет каждая часть в структуре здания?

В прошлой главе мы говорили об инъекции зависимостей, и мы не знаем, все ли это понимают? Нет проблем, если вы не понимаете. Сегодняшняя глава не имеет ничего общего с предыдущей.

Теперь мы переходим к следующей теме. Давайте поговорим об этом композитор Этот инструмент. Все не новички в этом инструменте. С его помощью очень удобно устанавливать плагины. Но знаете ли вы его принцип? Это обычный класс. Как его можно загрузить? композитор Скажи, что мы сделали это, и все зависит от тебя загрузка Работать.

2.1 __автоматическая загрузка

Это особенно важный момент в области знаний. Мы часто видим это в файле ввода фреймворка( __автозапуск и spl_autoload_регистр 。 Теперь, конечно, вы можете видеть только spl_auto_register r) 。 Но когда его спрашивают о функциях и методах этих двух методов, большинство людей все еще пребывают в замешательстве.

Что это за две функции? В чем удобство автоматической загрузки?

включить и требуется PHP-это введение двух основных методов работы с файлами. Прямое использование в маломасштабной разработке включает и требуютОднако в крупных проектах будет большое количество стеков включения и требований. (подумайте об этом, вы устали, когда я пишу сотни включений в файл? )

Такой код не является ни элегантным, ни эффективным, и его также очень трудно поддерживать.

Чтобы решить эту проблему, некоторые платформы предоставляют список конфигурации импортированных файлов, которые будут импортированы при инициализации объекта. Но это просто делает код более кратким, и эффект от введения все еще неудовлетворителен. После PHP5, с улучшением объектно-ориентированной поддержки PHP, __загрузка Функция для обеспечения возможности автоматической загрузки.

Здесь я добавляю два пункта знаний, которые не связаны с текущей главой:

  • Функция включения такая же, как и функция требования. Разница между ними заключается в том, что при возникновении ошибки включения будет сгенерировано только предупреждение, а require выдаст сценарий завершения ошибки.
  • include_ Единственное различие между once и include заключается в том, что include_ Один раз проверяет, был ли файл импортирован. Если это так, то он не будет импортироваться повторно.

Самый простой способ реализовать автоматическую загрузку-использовать __автозапуск Волшебный метод. Когда вы ссылаетесь на класс, которого не существует, __автоматическая загрузка Будет вызван, и имя вашего класса будет передано в качестве параметра. Что касается конкретной логики функции, то она должна быть реализована самим пользователем. Используя это свойство, создается механизм автоматической загрузки. Сначала создайте autoload.php Чтобы выполнить простой тест:

//When the class is not defined, the system automatically calls
function __autoload($class)
{
    /*Specific processing logic*/
    Echo $class; // simply output the undefined class name
}

new HelloWorld();

/**
 *Output HelloWorld and error message
 * Fatal error: Class 'HelloWorld' not found
 */


Through this simple example, we can find that in the process of class instantiation, the work done by the system is roughly as follows:

/*Simulation system instantiation process*/
function instance($class)
{
    //Returns an instance of a class if it exists
    if (class_exists($class, false)) {
        return new $class();
    }
    //Check whether autoload function is defined by user
    if (function_exists('__autoload')) {
        Wei Autoload ($class); // last introduced opportunity
    }
    //Check again if the class exists
    if (class_exists($class, false)) {
        return new $class();
    }Else {// system: I really have no idea
        throw new Exception('Class Not Found');
    }
}

понял __загрузка После того, как функция заработает, давайте использовать ее для реализации автоматической загрузки.

Сначала создайте файл класса (рекомендуется, чтобы имя файла совпадало с именем класса). Код выглядит следующим образом:

class [ClassName] 
{
    //Output the current class name when the object is instantiated
    function __construct()
    {
        echo '

' . __CLASS__ . '

'; } }

(Я создал Адский мир Класс для демонстрации) далее мы определим __автозапуск Чтобы включить автоматическую загрузку:

function __autoload($class)
{
    //Determine the file name according to the class name
    $file = $class . '.php';

    if (file_exists($file)) {
        Include $file; // import PHP file
    }
}

new HelloWorld();

/**
 *Output < H1 > HelloWorld
 */

Это выглядит великолепно, не так ли? Используйте этот __автозапуск Вы можете написать механизм для автоматической загрузки классов. Но вы когда-нибудь пытались записать два в один файл __автозапуск Тебе не нужно об этом думать. Это неправильно. В больших рамках вы осмеливаетесь гарантировать, что у вас есть только один __автозапуск ? Не слишком ли это хлопотно?

Не торопитесь, spl_autoload_регистр () Пришло время поиграть. Но прежде чем мы объясним это, давайте поговорим о другом важном понятии – пространстве имен.

2.3 пространство имен

На самом деле, пространство имен-это не что-то новое. Многие языки (например, C + +) уже поддерживают эту функцию. Но PHP начал работать поздно, до PHP 5.3 Позже. Короче говоря, пространство имен-это своего рода идентичность. Его основная цель-решить проблему конфликта имен. Как и в повседневной жизни, есть много людей с одинаковыми именами, как отличить этих людей? Тогда нам нужно добавить несколько дополнительных знаков. Кажется, хорошо рассматривать рабочую единицу как знак, так что вам не нужно беспокоиться о смущении из-за “удара по имени”.

Здесь у нас есть небольшая задача представить генерального директора Baidu Робина Ли:

Namespace Baidu;

Class Robin Li
{
    function __construct()
    {
        Echo 'founder of Baidu';
    }
}

Это основная информация Робина Ли. пространство имен Это логотип его подразделения, класс Это его имя. Пространство имен с помощью ключевого слова пространство имен Чтобы заявить. Если файл содержит пространство имен, он должен объявить пространство имен перед всем остальным кодом.

New Baidu Robin Li (); // restricted class name
New \ Baidu / Robin Li (); // fully qualified class name

В общем, не важно знакомить с другими "Байду Робин Ли" все равно "Байду Инк Робин Ли" Они могут понять. Если текущее пространство имен не объявлено, полное имя класса и полное имя класса эквивалентны. Потому что, если вы не укажете пробел, значение по умолчанию будет глобальным ().

Namespace Google;

New Baidu / Robin Li (); // Google \ "Baidu \" Robin Li (actual results)
New \ "Baidu \" Robin Li (); // Baidu \ "Robin Li \" (actual results)

Если вы представите Робина Ли их сотрудникам в корпорации Google, вы должны указать, что это “Робин Ли из Baidu Inc”. В противном случае он бы подумал, что Baidu-это отдел Google, а Робин Ли-всего лишь один из них. В этом примере показана разница между использованием полного имени класса и полного имени класса в пространстве имен. (полное пространство имен класса + полное имя класса)

/*Import namespace*/
Use Baidu Robin Li;
New Robin Li (); // Baidu Robin Li (actual results)

/*Set alias*/
Use Baidu Robin Li AS CEO;
New CEO (); // Baidu Robin Li (actual results)

/*In any case*/
New \ "Baidu \" Robin Li (); // Baidu \ "Robin Li \" (actual results)

Первая ситуация заключается в том, что другие уже знали Робина Ли. Вам нужно только прямо произнести имя, и он поймет, кого вы имеете в виду. Во – вторых, Робин Ли-их генеральный директор. Вы можете прямо сказать генеральному директору, он может отреагировать немедленно. Использование пространства имен создает только префикс имени класса, который нелегко конфликтовать, и система не будет автоматически импортировать. Если файл не импортирован, система сработает, прежде чем выдаст ошибку “класс не найден” __автозапуск Функция, передающая в качестве аргумента имя квалифицированного класса. Таким образом, приведенные выше примеры основаны на том факте, что вы вручную ввели связанные файлы, в противном случае система выдаст “Класс’ Baidu Robin Li ‘не найден”.

2.4 spl_autoload_регистр

Далее давайте реализуем автоматическую загрузку с пространствами имен. Здесь мы используем функцию spl_autoload_register () , для которой требуется номер версии PHP больше 5.12. spl_autoload_регистр Функция заключается в регистрации входящей функции (параметры могут быть в виде функции обратного вызова или имени функции) с помощью SPL __автозапуска Очередь функций и удалите систему по умолчанию __автозапуск() Функция. После вызова функции spl_autoload_register() при вызове неопределенных классов система вызовет и зарегистрируется в spl_autoload_register() Все функции функции, а не автоматический вызов __автозапуск() Функции.

Теперь давайте создадим класс Linux , который использует ос В качестве пространства имен (рекомендуется, чтобы имя файла соответствовало имени класса):

Namespace OS; // namespace

Class Linux // class name
{
    function __construct()
    {
        echo '

' . __CLASS__ . '

'; } }

Затем создайте файл PHP в том же каталоге и используйте spl_autoload_register Автоматическая загрузка с помощью обратного вызова функции:

spl_autoload_register(function ($class) { // class = os\Linux

    /*Qualified class name path mapping*/
    $class_map = array(
        //Qualified class name = > file path
        'os\Linux' => './Linux.php',
    );

    /*Determine the file name according to the class name*/
    $file = $class_map[$class];

    /*Import related documents*/
    if (file_exists($file)) {
        include $file;
    }
});

new \os\Linux();

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

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

2.4 спецификация psr-4

PSR-4 Это спецификация для автоматической загрузки соответствующих классов по пути к файлу. В спецификации указано, что полное имя класса должно иметь следующую структуру:

\< top level namespace > (\ < child namespace >) * \ < class name >

Если вы продолжите использовать приведенный выше пример, пространство имен верхнего уровня эквивалентно компании, подпространство эквивалентно должности, а имя класса эквивалентно имени человека. Тогда стандарт Robin Li называется “генеральный директор Baidu Inc Робин Ли”.

В спецификации psr-4 должно быть пространство имен верхнего уровня, что означает представление специального каталога (каталога файловой базы). Подпространство имен представляет путь (относительный путь) файла класса относительно каталога базы файлов, а имя класса соответствует имени файла (обратите внимание на разницу в регистре).

Например: в полном имени класса \приложение\просмотр\новости\Индекс Среда, если применимо представитель C:\Baidu , путь к этому классу C:\Baidu\view\news\Index.php

Давайте проанализируем \приложение\просмотр\новости\Индекс Например, напишите простой Демо :

$class = 'app\view\news\Index';

/*Top level namespace path mapping*/
$vendor_map = array(
    'app' => 'C:\Baidu',
);

/*Resolve class name as file path*/
$vendor = substr ($class, 0, strpos ($class, '\ \'); // fetch the top-level namespace [app]
$vendor_ dir = $vendor_ Map [$vendor]; // file base directory [C: \ Baidu]
$rel_ Path = dirname (substr ($class, strlen ($vendor)); // relative path [/ view / news]
$file_ Name = basename ($class). '. PHP'; // filename[ Index.php ]

/*Path of output file*/
echo $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;

Через это Демонстрация Вы можете увидеть процесс преобразования полного имени класса в путь. Теперь давайте реализуем автозагрузчик стандартным объектно-ориентированным способом.

Сначала мы создаем файл Сначала мы создаем файл , он находится в \app\mvc\просмотр\главная страница

namespace app\mvc\view\home;

class Index
{
    function __construct()
    {
        echo '

Welcome To Home

'; } }

Далее мы создаем класс загрузки (пространство имен не требуется), который находится в каталоге:

class Loader
{
    /*Path mapping*/
    public static $vendorMap = array(
        'app' => __DIR__ . DIRECTORY_SEPARATOR . 'app',
    );

    /**
     *Autoloader
     */
    public static function autoload($class)
    {
        $file = self::findFile($class);
        if (file_exists($file)) {
            self::includeFile($file);
        }
    }

    /**
     *Resolve file path
     */
    private static function findFile($class)
    {
        $vendor = substr ($class, 0, strpos ($class, '\ \'); // top level namespace
        $vendordir = self:: $vendormap [$vendor]; // file base directory
        $filepath = substr ($class, strlen ($vendor)). '. PHP'; // file relative path
        return strtr($vendorDir . $filePath, '\', DIRECTORY_ Separator); // file standard path
    }

    /**
     *Import file
     */
    private static function includeFile($file)
    {
        if (is_file($file)) {
            include $file;
        }
    }
}

Наконец, Загрузчик В классе загрузка Зарегистрируйтесь в spl_autoload_регистр В функции:

include ' Loader.php '; // introduce loader
spl_ autoload_ Register ('loader:: autoload '); // register to autoload

New \ app \ MVC \ view \ home \ index(); // instantiate unreferenced classes

/**
 *Output: < H1 > welcome to home
 */

2.4 композитор

Сказав так много, пришло время композитор Это на сцене. Я не собираюсь вдаваться в подробности установки. Давайте взглянем поставщик/композитор Подробности о

vendor
----autoload_classmap.php
----autoload_files.php
----autoload_namespace.php
----autoload_psr4.php
----autoload_real.php
----autoload_static.php
----ClassLoader.php
----install.json 
autoload.php

Дайте мне сначала посмотреть поставщик/autoload.php :

 $path) {
            $loader->set($namespace, $path);
        }

        $map = require __DIR__ . '/autoload_psr4.php';
        foreach ($map as $namespace => $path) {
            $loader->setPsr4($namespace, $path);
        }

        $classMap = require __DIR__ . '/autoload_classmap.php';
        if ($classMap) {
            $loader->addClassMap($classMap);
        }

        $loader->register(true);

        $includeFiles = require __DIR__ . '/autoload_files.php';
        foreach ($includeFiles as $file) {
            composerRequireff1d77c91141523097b07ee2acc23326($file);
        }

        return $loader;
    }

Ясно, что он будет autoload_namespaces.phpЯсно, что он будет autoload_namespaces.php autoload_classmap.phpautoload_files.php Включено несколько файлов конфигурации и выполняется соответствующая обработка( setPsr4 ), последняя регистрация( регистрация ) 。 Итак, давайте продолжим

    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

Эта функция состоит из одной строки, но она проста и понятна. Он напрямую вызывает собственный PHP spl_autoload_register Функции, обработка регистрации __загрузка То есть loadClass метод. Последующие действия Класс загрузки метод:

    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }
    }

Из имени функции вы можете примерно узнать поток: если есть $class Соответствующий файл $ , затем включите.

    public function findFile($class)
    {
        // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
        if ('\' == $class[0]) {
            $class = substr($class, 1);
        }

        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative) {
            return false;
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if ($file === null && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if ($file === null) {
            // Remember that this class does not exist.
            return $this->classMap[$class] = false;
        }

        return $file;
    }

Найдите файл по имени класса и, наконец, заблокируйте его в методе findFileWithExtension . Продолжение Поиск файла с расширением метод:

    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }
    }

Окончательная реализация будет Пространство имен \ класс Такое имя класса преобразуется в Имя каталога/класс name.php Такой путь и верните полный путь.

Я нахожу композитора Из автопогрузка И php Автономный spl_autoload , есть небольшая разница при включении файлов. То есть spl_autoload Найдет .невероятно Наберите, но композитор не может.

Также можно обнаружить, что, хотя имя файла конфигурации autoload_psr4.php , но на самом деле psr0 Также поддерживается автоматическая загрузка форматов. Самая большая разница между ними – psr0 Использовать “? В “Вместо” “между каталогами”..

Итак, все вышесказанное, пришло время подвести итоги. из __автозагрузка охват spl_autoload_регистр Снова композитор и psr4 метод. Какова цель официального дизайна PHP и сообщества? Они там, чтобы решить эту проблему включают Неудобные документы. Один за другим включить Это не очень удобно. Я использую его сейчас spl_autoload_регистр Прямое автоматическое включение Да. Но мы не можем просто писать, у нас есть правила, поэтому они у нас есть psr4

Оригинал: “https://developpaper.com/how-many-steps-does-it-take-from-symfony-framework-to-a-complete-project/”