这个问题已被here,here或here多次讨论,但没有提及优雅的解决方案。
一个特殊的用例是允许使用Laravel加载和路由旧的PHP文件。例如,我正在将一个非常老的代码(> 20年)迁移到Laravel中,并且大多数页面都是常规的PHP文件,我希望将它们渲染到特定的Blade模板中。
要做到这一点,做起来很优雅:
Router::php('/some/route/{id}', base_path('legacy/some/page.php'));
在幕后,我只需要将捕获的变量传递到PHP页面,评估并获取其中的内容,最后返回一个视图实例。
由于Laravel声称自己是SOLID框架,所以我认为扩展Router很简单,所以我这样写:
命名空间App \ Services;
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
);
但这看起来有点丑陋。有没有更好的方法可以做到这一点?
答案 0 :(得分:1)
由于Router类是macroable,因此您可以执行以下操作:
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...
});
});