Интерпретация исходного кода Laravel

PHP Laravel

дата: 2017-12-10 22:24:18 название: интерпретация исходного кода laravel

Исходный код yii/laravel высокого качества, phper должен внимательно его прочитать

Интерпретация исходного кода:Карта мозга Baidu.com/file/9's 4 не 5...

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

жизненный цикл

Если вы знакомы с моими одноклассниками, то знаете, что я уделяю особое внимание этой концепции.Жизненный цикл является хорошим мостом, соединяющим конкретный бизнес и лежащую в его основе реализацию.Знание жизненного цикла может не только развивать способности разработки программного обеспечения, но также развивать способность понимать бизнес.

Важная вещь зацикливается бесконечно: жизненный цикл.

жизненный цикл ларавеля:

инициализация

  • использовать$basePathинициализация(new) Illuminate\Foundation\Application, класс приложения на самом деле является контейнером для разрешения зависимостей классов, следуйтеPSRстандартный
  • Привязка приложения (bind) 3 синглтона:App\Http\Kernel, App\Console\Kernel, App\Exceptions\Handler, запрос выполняется конкретным ядром. Зависимости, используемые контейнером для разрешения класса,По требованиюДа, здесь указаносинглтонОбратите внимание на laravel Основные моменты: Привязка выполняется в соответствии сIlluminate\Contracts\Xxx -> App\xxxОграничения для достижения, глобальное единство.Контракт мы продолжим говорить об этом позже.

специфическое лечение

  • Приложение в зависимости от сцены (веб/консоль), создание экземпляра (make) в соответствующее ядро
  • В процессе инстанцирования ядра сначала войдите в этап начальной загрузки: регистрация (register) ServiceProvider, выполняемый Приложением, примечаниерегистрЭто необходимозаявление об отношениях, на самом деле выполняется контейнеромПо требованиюнагрузка.
  • Используйте информацию в глобальной переменной php для инициализации объекта запроса, например$_SERVER
  • Ядро обрабатывает объект Request и возвращает объект Response.
  • Наконец, ядро ​​выполняет метод terminate() для завершения

Ядро обрабатывает процесс запроса

  • Сначала запустите определенное ПО промежуточного слоя
  • Передайте его объекту Router для обработки: сопоставление маршрута, сопоставление с замыканием/контроллером для логической обработки и возврата данных.
  • Соберите данные, возвращенные выше, и соберите их в объект Response в соответствии с некоторыми другими конфигурациями, такими как формат

Вы обнаружите, что знакомый MVC не упоминается, потому что MVC также имеет приложение для управления объектами один за другим, а также все другие службы.

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

Контракт Контракт

Жизненный цикл и контейнер в основном одинаковы для современных фреймворков.Давайте поговорим о разнице между laravel и Contract.

Сначала представим две идеи программирования:

интерфейсно-ориентированное программирование

соглашение о конфигурации

Эти две идеи на самом деле пересекаются, подчеркивая, что в спецификации проекта системыопределениеа такжевыполнитьдолжны быть разделены.

laravel всегда практиковал эту идею, навсегдаопределениеВо-первых, все функции, предоставляемые фреймворком, можно найти здесь.источник, Некоторые люди также любят говорить «да».тень.

Проще говоря: мне все равно, как этого добиться, я все равно должен следовать тому, что говорю.

Да, реальность на самом деле такова, она нужна всемтанцевать в цепях.

В laravel для определения функции/сервиса вам необходимо выполнить следующие шаги:

  • Определить интерфейс в контракте
  • Foundation определяет базовую реализацию, большое количество Traits и основных функций, связанных с этим сервисом.
  • Реализация конкретной функции/службы должна быть реализована в соответствии с определением в контракте, и необходимо добавить ServiceProvider для регистрации службы в контейнере.
  • Поддержка предоставляет некоторые общие, неспецифические независимые от бизнеса/сервиса вспомогательные методы для использования при реализации конкретных функций/сервисов.

После того, как этот набор завершен, мы можем следоватьXxxServiceProviderопределенный в методе register(), используйте$app['xxx']Эта форма для доступа к нужным нам услугам.

Например:

// AuthServiceProvider
protected function registerAuthenticator()
{
    $this->app->singleton('auth', function ($app) {
        // Once the authentication service has actually been requested by the developer
        // we will set a variable in the application indicating such. This helps us
        // know that we need to set any queued cookies in the after event later.
        $app['auth.loaded'] = true;

        return new AuthManager($app);
    });

    $this->app->singleton('auth.driver', function ($app) {
        return $app['auth']->guard();
    });
}

// 需要使用 Auth 服务
$auth = $app['auth']

Вот подсказка, обычно устанавливает свойство класса$app, назначаемый приложению при инициализации фреймворка, чтобы можно было использовать все зависимости$appПеременные обрабатываются единообразно, лаконично и просто.

Почему на laravel так удобно писать

Этот заголовок на самом деле объясняет слоган laravel:

Love beautiful code? We do too. The PHP Framework For Web Artisans

С частями, представленными выше, все основные функции, которые нам нужны, были использованы, а остальное зависит от того, как мы планируем его использовать.Фактически, был введен метод:$app['auth'], вызовите зарегистрированную службу аутентификации.

DI

DI, внедрение зависимости, внедрение зависимости.Этот метод более распространен:

// 框架提供的注册功能
/**
 * Handle a registration request for the application.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function register(Request $request)
{
    $this->validator($request->all())->validate();

    event(new Registered($user = $this->create($request->all())));

    $this->guard()->login($user);

    return $this->registered($request, $user)
                    ?: redirect($this->redirectPath());
}

Передаем нужный нам класс прямо в параметре функции\Illuminate\Http\Request $request, то контейнер автоматически предоставит нам этот класс для использования

helper function

Поговорим о вспомогательной функции в широком смысле, которая реализуется автоматической загрузкой composer:

// laravel/framework/src/composer.json
"autoload": {
    "files": [
        "src/Illuminate/Foundation/helpers.php",
        "src/Illuminate/Support/helpers.php"
    ],
    "psr-4": {
        "Illuminate\\": "src/Illuminate/"
    }
},

Как вы можете видеть здесь, laravel зарегистрировал 2 типа вспомогательных функций:

  • Foundation/helpers.php: Вспомогательные функции, связанные с функциями фреймворка.
  • Support/helpers.php: общие вспомогательные функции, независимые от функций фреймворка, такие как обработка массивов, обработка строк.

Вот вспомогательные функции, связанные с функциями фреймворка:

// 核心函数
function app($abstract = null, array $parameters = [])
{
    if (is_null($abstract)) {
        return Container::getInstance(); // 相当于上面的 $app
    }

    return Container::getInstance()->make($abstract, $parameters); // 相当于上面的 $app['auth']
}

// 使用效果
app() -> $app
app('auth') -> $app['auth']

Посмотрите, как это удобно, на примере службы кэширования:

// 实现
function cache()
{
    $arguments = func_get_args();

    if (empty($arguments)) {
        return app('cache');
    }

    if (is_string($arguments[0])) {
        return app('cache')->get($arguments[0], $arguments[1] ?? null);
    }

    if (! is_array($arguments[0])) {
        throw new Exception(
            'When setting a value in the cache, you must pass an array of key / value pairs.'
        );
    }

    if (! isset($arguments[1])) {
        throw new Exception(
            'You must specify an expiration time when setting a value in the cache.'
        );
    }

    return app('cache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1]);
}

// 使用效果
cache($key); // 获取缓存
cache($key, $value); // 设置缓存

Разве это не удобно?

Facade

Шаблон проектирования фасадов: упростите приложение, обернув фасады, скрыв определенные детали объектов.

Давайте сначала посмотрим на эффект, также используя приведенный выше Cache в качестве примера:

\Cache::get($key);
\Cache::set($key, $value);

Кажется, это немного сложнее, чем вспомогательная функция. Давайте сделаем это в конце. Посмотрим, как реализован Facade.

Сначала настройте новый Facede в соответствии с официальной документацией:

  • первый пришелconfig/app.phpРегистрация в, регистрация ServiceProvider также здесь
  • Создайте новый класс Facede, унаследованный отIlluminate\Support\Facades\Facade

Например, фасад кэша здесь:

namespace Illuminate\Support\Facades;

class Cache extends Facade
{
    protected static function getFacadeAccessor() // 只需要实现这个函数就好
    {
        return 'cache';
    }
}

В чем принцип?Illuminate\Support\Facades\Facadeкод:

// 魔法函数
public static function __callStatic($method, $args)
{
    $instance = static::getFacadeRoot(); // 上面实现的 getFacadeAccessor() 就在这里使用到, 最后其实返回的 $app['cache']

    if (! $instance) {
        throw new RuntimeException('A facade root has not been set.');
    }

    return $instance->$method(...$args);
}

Итак, выполнить\Cache::get($key);наконец казнен$app['cache']->get($key);

Проанализировав это, каждый обнаружит, что на самом деле все крутится вокруг$appвращаться,заверните, реализует множество различных методов записи.

3 способа сравнить

Прежде всего, давайте посмотрим на DI и Facade, интересно, у всех ли будет такой же вопрос, как у меня:

// 书写控制器代码时, 有 2 种方式:

public function index(Request $request)
{
    $input = $request->all();
}

public function index()
{
    $input = Request::all();
}

Когда напишем Запрос, редактор предложит выйти 2\Illuminate\Http\Requestа также\Request.Когда я впервые соприкоснулась с этим местом, то долго недоумевала, его теперь все могут отличить, один ДИ, другой Фасад, хотя названиеТакой же.

В этом примере также можно увидеть разницу между DI и Facade.

Давайте посмотрим на Facade и вспомогательную функцию.На самом деле, некоторые из вышеперечисленных перечислены.По крайней мере, приведенный выше пример кажется немного более кратким для вспомогательной функции, но это ограничено:

Cache::get($key, $timeout); // 缓存可以设置过期时间, Cache Facade 直接加一下参数就行了

cache()->get($key, $timeout); // Cache helper function 没有封装, 所有要先用 cache() 来返回 $app['cache'], 然后再调用

Так много способов достичь, вы чувствуетеНемного кружится голова, как сказал чиновникИзобразительное искусство ?

С большей свободой написания (аббревиатуры) совершенно очевидно, что повышается производительность.

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

Последний взгляд

Например, сервис Cache можно использовать по-разному, но когда мы его используем, мы все одинаковы, как это реализовано?

  • Первый, или Контракт,Мне все равно, как этого добиться, это просто то, что я говорю, это последовательно во всем
  • Затем, когда есть несколько способов реализовать это, laravel идиоматическиmanager-driverСюда

Или возьмем в качестве примера службу Cache:

// CacheServiceProvider 中这样注册的服务
public function register()
{
    $this->app->singleton('cache', function ($app) { // 这就是我们常用的 $app['cache'], 实际使用的 CacheManager
        return new CacheManager($app);
    });

    $this->app->singleton('cache.store', function ($app) { // 继续看
        return $app['cache']->driver();
    });

    ...
}

// CacheManager
// 魔法函数, 比如执行 $app['cahe']->get($key), 其实最终执行的 $this->store()->get($key)
public function __call($method, $parameters)
{
    return $this->store()->$method(...$parameters); 
}
public function store($name = null)
{
    $name = $name ?: $this->getDefaultDriver();

    return $this->stores[$name] = $this->get($name);
}

Продолжайте читать код, вы обнаружите, что окончательный проход$nameнайти классcreate{$ame}()метод создания экземпляра$this->store()

этоmanager-driverспособ, широко используемый в laravel, например файловая система, уведомление, очередь

напиши в конце

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

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