0x00 Предисловие
Промежуточное программное обеспечение — это функция, предоставляемая многими фреймворками PHP, и я был удивлен и взволнован, когда впервые узнал об этом. Поскольку его роль слишком сильна, до того, как не будет промежуточного программного обеспечения, мы должны написать проверку разрешений и некоторые публичные операции в методе контроллера, тогда контроллер станет очень раздутым, что снизит читабельность и ремонтопригодность. Но с промежуточным программным обеспечением мы можем написать эти операции в промежуточном программном обеспечении, а затем, используя различные комбинации промежуточного программного обеспечения, мы можем не только выполнить требования, но и уменьшить связанность кода. Поскольку промежуточное ПО хорошо во всех отношениях, как оно реализовано? чтениеLaravel
иSlim
В процессе работы с исходным кодом (мазохистский процесс, который заставляет людей чувствовать себя очень трудоемкими, измученными и чувствовать себя тарелками /(ㄒoㄒ)/~~) я обнаружил, что ключевым моментом является закрытие нескольких промежуточных программ (некоторые фреймворки промежуточных программ не поддерживаются). реализуется через замыкания, но принадлежитcallable
Категория , совместно именуемая замыканиями для удобства написания) черезarray_reduce
Или оберните его в процесс закрытия в цикле.
0x01 разминка
Когда дело доходит до промежуточного программного обеспечения, люди часто представляют себе эту картину.
Выглядит удивительно и пугающе, но если присмотреться, этот процесс на самом деле выглядит как вложенный вызов функции.Middleware2(Middleware1(App()))
Шерстяная ткань? Но этот вложенный вызов явно неверен, потому что сначала выполняется PHP.App()
вместоMiddleware2
Но как насчет вложенных замыканий? Пример кода приведен ниже:
$allMiddleware = function () {
echo 'start middleware2' . PHP_EOL;
(function () {
echo 'start middleware1' . PHP_EOL;
// app
(function () {
echo 'app' . PHP_EOL;
})();
// end app
echo 'end middleware1' . PHP_EOL;
})();
echo 'end middleware2' . PHP_EOL;
};
$allMiddleware();
// 输出
// start middleware2
// start middleware1
// app
// end middleware1
// end middleware2
0x02 мышление
Эй, приведенный выше код работает так, как и ожидалось, но этот код кажется немного руо (чжи). Но на самом деле приведенный выше код$allMiddleware
Это результат комбинации промежуточного программного обеспечения, поэтому мы коснулись порога Теперь, пожалуйста, подумайте, как автоматически комбинировать следующие замыкания промежуточного программного обеспечения?
// 数据库中间件
$db = function (Closure $next) {
echo '成功建立数据库连接' . PHP_EOL;
$next();
echo '成功关闭数据库连接' . PHP_EOL;
};
// 点赞中间件
$like = function (Closure $next) {
echo '点赞+1' . PHP_EOL;
$next();
echo '点赞+2' . PHP_EOL;
};
// 内容闭包
$app = function () {
echo '文章内容' . PHP_EOL;
};
больше параметров$next
какого черта?$next
Это следует понимать как «закрытие, упакованное всеми функциями закрытия промежуточного программного обеспечения после этого промежуточного программного обеспечения», просто используйтеMiddleware2
С точки зрения его$next
этоMiddleware1
иAPP
Упакованная крышка (см. два самых внутренних слоя на рисунке выше).
0x03 ответы
Код ответа следующий:
// array_reduce 实现
$allMiddleware = [$like, $db];
$go = array_reduce($allMiddleware, function ($next, $middleware) {
return function () use ($next, $middleware) {
$middleware($next);
};
}, $app);
$go();
// foreach 实现
$allMiddleware = [$like, $db];
$next = $app;
foreach ($allMiddleware as $middleware) {
$next = function () use ($next, $middleware) {
return $middleware($next);
};
}
$next();
Две реализации, но тот же принцип, так что только объяснитеforeach
реализация версии. Первый — сформировать массив всего промежуточного ПО и поместить$next
Установить как$app
, а затем запустить цикл$next
иmiddleware
сформировать новое замыкание и присвоить$next
,так$next
Он будет продолжать объединять предыдущие замыкания и, наконец, станет одним из них. Затем, выполнив окончательный$next
чтобы получить результат. Конечно, мне может быть нелегко понять то, что я сказал пустыми словами. Лучший способ - запустить этот код в моем мозгу. ㄒ)/~~) и тогда вы сможете понять. Тоже не ясноarray_reduce
функция можеткликните сюда.
0x04 лучшая версия
Чтобы лучше понять предыдущее промежуточное ПО, достаточно$next
параметры, но промежуточное ПО фактического фреймворка будет иметь аналогичные$request
параметры и поддерживает возвращаемые значения$response
(например, Laravel), ниже приведен код реализации промежуточного программного обеспечения, похожего на Laravel (просто имитация, как у тигров и кошек). Одна уловка, все уловки, это блюдо не объяснит этого (если это затронет мои слепые пятна знаний, это будет ГГ, О(∩_∩)О, ха-ха~).
$db = function ($request, Closure $next) {
echo '成功建立数据库连接' . PHP_EOL;
$response = $next($request);
echo '成功关闭数据库连接' . PHP_EOL;
return $response;
};
$like = function ($request, Closure $next) {
echo '点赞+1' . PHP_EOL;
$response = $next($request);
echo '点赞+2' . PHP_EOL;
return $response;
};
$app = function ($request) {
echo $request . PHP_EOL;
return '一个无聊的返回值';
};
$allMiddleware = [$like, $db];
$next = $app;
foreach ($allMiddleware as $middleware) {
$next = function ($request) use ($middleware, $next) {
return $middleware($request, $next);
};
}
$response = $next('O(∩_∩)O');
echo $response;
0x05 Сводка
(⊙v⊙) Что ж, совсем немного контента достаточно, чтобы я почувствовал удовлетворение O(∩_∩)О, ха-ха~. Кроме того, если в статье есть ошибка, надеюсь, все смогут указать на нее, а если возникнут вопросы, то можно обсудить друг с другом :-D.