php - 如何正确扩展 Laravel 5.7 路由器?
问题描述
这个问题已经在这里、这里或这里讨论过很多次,但没有提到优雅的解决方案。
一个特殊的用例是允许使用 Laravel 加载和路由旧的 PHP 文件。例如,我正在将一个非常古老(> 20 年)的代码库迁移到 Laravel 中,并且大多数页面都是常规的 PHP 文件,我想将它们呈现到特定的 Blade 模板中。
要做到这一点,这样做会很优雅:
Router::php('/some/route/{id}', base_path('legacy/some/page.php'));
在幕后,我需要的只是将捕获的变量传递给 PHP 页面,评估并获取它的内容并最终返回一个视图实例。
由于 Laravel 声称自己是一个 SOLID 框架,我认为扩展路由器是微不足道的,所以我写了这个:
命名空间应用\服务;
class Router extends \Illuminate\Routing\Router
{
public function php($uri, $filename, $template='default') {
...
return view(...
}
}
然后我尝试用这个扩展我的 Http Kernel:
namespace App\Http;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use App\Services\Router;
class Kernel extends HttpKernel
{
public function __construct(Application $app, Router $router) {
return parent::__construct($app, $router);
}
}
但它不起作用,似乎应用程序正在构建具有错误依赖关系的内核。在Application@registerCoreContainerAliases
我看到核心别名router
是硬编码的,因为这个方法是在应用程序的构造函数中调用的,我注定要失败。
剩下的唯一解决方案是在加载内核之前覆盖路由器,如下所示:
$app = new Application($_ENV['APP_BASE_PATH'] ?? dirname(__DIR__));
$app->singleton('router', \App\Services\Router::class);
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
但这看起来有点难看。有没有更好的方法来实现这一目标?
解决方案
Router::macro('php', function ($uri, $filepath) {
return $this->addRoute(['GET', 'POST', etc...], $uri, function () use ($filepath) {
// here you might use the blade compiler to render the raw php along with any variables.
//
// See: https://laravel.com/api/5.7/Illuminate/View/Compilers/Concerns/CompilesRawPhp.html
//
$contents = file_get_contents($filepath);
// return compiled $contents...
});
});
推荐阅读
- python - 如何删除 Django 中的操作错误?
- python - 修补程序滚动条不适用于画布小部件
- javascript - vue.js 道具没有在组件中呈现
- java - 我还能在 macOS 上使用 JDK 7 吗?
- python - “未找到版本‘GLIBCXX_3.4.26’”在 anaconda env 中运行 gdal 时出错
- react-native - flatlist 用阿拉伯语口吃
- c - 从C中的单链表中删除特定节点
- mysql - Sequelize Raw 查询不返回数组有很多
- python - 尝试绑定到套接字时出现“OSError: [Errno 22] Invalid argument”错误
- r - 通过识别日期列替换 R 中的数据时出错