[Laravel Series 6.4] Фильтр каналов
[Laravel Series 6.4] Фильтр каналов

трубчатый фильтр

В предыдущих трёх статьях мы уже изучили контент, связанный с контейнером сервисов. Можно сказать, что контейнер сервисов — это душа всей платформы Laravel. С первого этапа запуска необходимо создать контейнер и загрузить его. все объекты обслуживания. Говоря о конвейерах, с ними все знакомы. В мире разработки программ приложения с конвейерным режимом можно увидеть повсюду. Аналогично, в среде Laravel он также является основным. Можно даже сказать, что сочетание конвейеров и сервисных контейнеров дает нам такую ​​основу для использования.

что такое трубопровод

Как упоминалось ранее, конвейерный режим очень распространен. Почему вы так говорите?

Язык кода:javascript
копировать
ps -ef | grep php

Это распространено? Часто пользуетесь? Эта команда Linux является командой канала. Результат предыдущей команды передается для выполнения следующей команде, как по каналу, позволяя результату запроса команды течь вниз. Это применение шаблона конвейера.

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

Конвейерный режим обычно используется вместе с фильтрами. Что такое фильтр? По сути, нам нужны промежуточные методы для обработки запросов, такие как grep в приведенной выше команде, или такие команды, как wc и awk. Фактически, вы быстро обнаружите, что в среде Laravel наше промежуточное программное обеспечение представляет собой фильтр. Данные, которые мы хотим обработать, — это объект запроса Request.

Загрузка приложения конвейера в Laravel

Помните метод sendRequestThroughRouter(), который мы видели в сервисном контейнере? Кроме того, мы также говорили об этом, когда впервые говорили о промежуточном программном обеспечении. Давайте еще раз взглянем на его код.

Язык кода:javascript
копировать
protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);

    Facade::clearResolvedInstance('request');

    $this->bootstrap();

    return (new Pipeline($this->app))
                ->send($request)
                ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                ->then($this->dispatchToRouter());
}

В этом коде последний возвращенный объект Pipeline является объектом конвейера. Давайте посмотрим, что означают эти методы.

Язык кода:javascript
копировать
public function __construct(Container $container = null)
{
    $this->container = $container;
}

public function send($passable)
{
    $this->passable = $passable;

    return $this;
}

public function through($pipes)
{
    $this->pipes = is_array($pipes) ? $pipes : func_get_args();

    return $this;
}

Методы конструктора, send() иthrough() относительно просты. Они просто присваивают значения свойствам текущего объекта. В этом нет ничего особенного. Однако в объекте Pipeline все методы возвращают $this, что фактически реализует цепной вызов объекта.

Основное внимание уделяется методу then().

Язык кода:javascript
копировать
public function then(Closure $destination)
{
    $pipeline = array_reduce(
        array_reverse($this->pipes()), $this->carry(), $this->prepareDestination($destination)
    );

    return $pipeline($this->passable);
}

Этот метод удивительно прост, не так ли? В нем используется только один array_reduce(). Хорошо, теперь вы можете похвастаться перед интервьюером. Ядром конвейера или промежуточного программного обеспечения в Laravel на самом деле является метод array_reduce(). Чтобы понять, что делает метод then(), мы должны сначала понять, что делает array_reduce().

array_reduce

Сигнатура функции array_reduce() в официальной документации следующая:

Язык кода:javascript
копировать
array_reduce(array $array, callable $callback, mixed $initial = null): mixed

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

обратный вызов Эта функция обратного вызова будет иметь два параметра, а именно: функция переноса переносит возвращаемое значение последней итерации. Если итерация происходит впервые, то это значение является начальным. Другой параметр — item, который представляет собой каждое значение в массиве.

Разве ты не понимаешь? Это нормально, я тоже не могу этого понять, не паникуйте, просто посмотрите на примеры.

Язык кода:javascript
копировать
function sum($carry, $item)
{
    $carry += $item;
    return $carry;
}

function product($carry, $item)
{
    $carry *= $item;
    return $carry;
}

$a = array(1, 2, 3, 4, 5);
$x = array();

var_dump(array_reduce($a, "sum")); // int(15)
var_dump(array_reduce($a, "product", 10)); // int(1200), because: 10*1*2*3*4*5
var_dump(array_reduce($x, "sum", "No data to reduce")); // string(17) "No data to reduce"

Этот код является примером с официального сайта. Мы определяем метод sum() для накопления и метод product() для факториала. По результатам первых двух тестов видно, что передавая первый массив и затем вызывая метод sum(), мы завершаем функцию накопления и выводим уникальное значение результата. Во втором абзаце добавляется третий параметр, дающий значение по умолчанию 10. Результатом является дополнительный совокупный результат умножения 10. Последний абзац представляет собой пустой массив, возвращающий результат, заданный параметром Initial.

Параметры array_reduce в рамках

Разобравшись с array_reduce(), давайте вернемся и посмотрим на параметры, указанные в исходном коде фреймворка. Первый параметр — это содержимое каналов, возвращаемых после использования array_reverse(). Эти каналы передаются через методthrough(). Возвращаясь к ядру, мы обнаружим, что параметр, передаваемый этим методом, является переменной-членом $middleware промежуточного программного обеспечения, загруженного в нашу платформу.

Во время предыдущего процесса bootstrap() мы зарегистрировали все привязки промежуточного программного обеспечения, зарегистрированные в app/Http/Kernel.php, в контейнере службы. Таким образом, этот массив каналов содержит всю информацию о промежуточном программном обеспечении.

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

Язык кода:javascript
копировать
protected function carry()
{
    return function ($stack, $pipe) {
        return function ($passable) use ($stack, $pipe) {
            try {
                if (is_callable($pipe)) {
                    return $pipe($passable, $stack);
                } elseif (! is_object($pipe)) {
                    [$name, $parameters] = $this->parsePipeString($pipe);

                    $pipe = $this->getContainer()->make($name);

                    $parameters = array_merge([$passable, $stack], $parameters);
                } else {
                    $parameters = [$passable, $stack];
                }

                $carry = method_exists($pipe, $this->method)
                                ? $pipe->{$this->method}(...$parameters)
                                : $pipe(...$parameters);

                return $this->handleCarry($carry);
            } catch (Throwable $e) {
                return $this->handleException($passable, $e);
            }
        };
    };
}

Этот метод гораздо сложнее. Давайте посмотрим на это шаг за шагом.

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

Вход в функцию try В сегменте кода первое решение таково: если pipe — это функция обратного вызова, вызовите ее напрямую и верните второе решение, если; pipe не предмет, а string слова, деконструкция pipe Информационный, сервисный контейнер make это, и параметры готовы; else То есть pipe является объектом, то passable и stack как его параметры. Наконец, если есть все объекты, метод объекта будет вызываться единообразно. handle Метод, название этого метода То есть this->method Имя метода, определенное атрибутом. внизу

В конечном итоге возвращается переменная $carry. Что это такое? Функция return next() в промежуточном программном обеспечении — это следующая функция обратного вызова в конвейере.

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

Язык кода:javascript
копировать
public function then(Closure $destination)
{
    $pipeline = array_reduce(
        array_reverse($this->pipes()), $this->carry(), $this->prepareDestination($destination)
    );

    return $pipeline($this->passable);
}

Правильно, тогда() Последний метод return Вот, теперь знай passable Где это было передано? Обратите внимание, это passable èПоследний является значением по умолчанию initial Параметры — это все наш текущий запрос. Request Объект и маршрут Route объект. То есть сказано, что повсюду Laravel В рамках этого, то, что течет в наших трубах, является нашим Request Object, и то, что в конечном итоге возвращается, происходит после завершения обработки каждого промежуточного программного обеспечения и контроллера. Response объект. Промежуточное программное обеспечение, контроллеры и даже маршрутизация на самом деле являются фильтрами в нашем конвейере. В соответствии с нашими условиями и условиями бизнеса мы можем прервать или обработать запрос в любой момент. Теперь мы понимаем, что мы можем сделать в середине. Вы также можете напрямую вернуть результаты страницы. в маршруте.

Что ж, чтобы изучить конвейер, мы фактически снова разобрались со всем процессом ответа на запрос. Будьте плодотворны!

Непосредственно напишите конвейерное приложение для тестирования.

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

первый,Нам нужно определить несколько фильтров,То есть наше промежуточное программное обеспечение, но нам не нужно его внедрять Laravel Стандартно, нужно только иметь handle() Метод хороший.

Язык кода:javascript
копировать
class AddDollar
{
    public function handle($text, $next){
        return $next("$".$text."$");
    }
}

class AddTime
{
    public function handle($text, $next){
        $t = $next($text);
        return $t . time();
    }
}

class EmailChange
{
    public function handle($text, $next){
        return $next(str_replace("@", "#", $text));
    }
}

Специальной функции нет, отфильтровываем Email в @ Символ становится # Нет. Многие веб-сайты имеют такую ​​функцию, позволяющую избежать сканирования. Email адрес. Два других предназначены для добавления символов и временных меток. существовать AddTime При обработке мы используем задний Функции промежуточного программного обеспечения, То есть Добавить контент после того, как промежуточное программное обеспечение завершит обработку. Мы уже говорили об этом на курсах, связанных с промежуточным программным обеспечением.

Далее используйте конвейеры для обработки.

Язык кода:javascript
копировать
Route::get('pipeline/test1', function(){
    $pipes = [
        \App\PipelineTest\EmailChange::class,
        \App\PipelineTest\AddTime::class,
        new \App\PipelineTest\AddDollar(),
        function($text, $next){
            return $next("【".$text."】");
        },
    ];

    return app(\Illuminate\Pipeline\Pipeline::class)
        ->send("Проверьте контент и посмотрите, заменен ли он.Email:zyblog@zyblog.ddd")
        ->through($pipes)
        ->then(function ($text) {
            return $text . "end";
        });
    // $[Проверьте содержимое и посмотрите, замените ли вы Email:zyblog#zyblog.ddd]$end1630978948

});

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

Здесь вы можете установить точки остановки и ввести проверку конвейера, как эти промежуточные программы. array_reverse() меняет порядок промежуточного программного обеспечения, поэтому заднее промежуточное программное обеспечение добавляет содержимое данных в конце. Я оставлю эту часть отладки вам!

Подвести итог

Можно сказать, что сервисные контейнеры и конвейеры (промежуточное программное обеспечение) Laravel в Самое основное содержание рамке, можно также сказать, что весь фреймворк построен на этих двух режимах. Понимание сервисного контейнера предназначено для решения проблемы зависимостей классов, а понимание конвейера — для решения проблемы потока данных запроса и ответа. Мы делаем это сами Web На самом деле разработка просто выполняет различные операции над двумя потоками данных: запроса и ответа.

После понимания двух основных частей в следующей статье мы рассмотрим, как реализовать очень часто используемую фасадную функцию в Laravel.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose