我已经在子文件夹中安装了 Laravel,并正在尝试安装 Horizon。路由到“test.com/sub-folder/horizon”后,所有损坏的设计以及内部链接都指向主域而不是主域没有子文件夹。
经过搜索,似乎是github issue中已经报告的已知问题
当 Laravel 安装在子文件夹中时,是否有任何解决方法可以使 Horizon 工作?
我已经在子文件夹中安装了 Laravel,并正在尝试安装 Horizon。路由到“test.com/sub-folder/horizon”后,所有损坏的设计以及内部链接都指向主域而不是主域没有子文件夹。
经过搜索,似乎是github issue中已经报告的已知问题
当 Laravel 安装在子文件夹中时,是否有任何解决方法可以使 Horizon 工作?
如果你迫切需要这样做,这里有一个 hack:
public\vendor\horizon\app.js
中,搜索window.Horizon.basePath
window.Horizon.basePath="/"+window.Horizon.path;
为window.Horizon.basePath="/[you sub-directoy]/"+window.Horizon.path;
它应该可以工作......直到有一天你运行更新并且它神秘地停止工作。
我有一个只涉及 PHP 的解决方案。
正如@Isaiahiroko 所指出的,这个问题是为 HorizonbasePath
的界面定义的。该代码在Laravel\Horizon\Http\Controllers\HomeController::index()
. 想法是这样的:我们将把我们自己的控制器实现传递给 Laravel 的服务容器,该控制器将覆盖传递给 HorizonbasePath
接口的定义。
使用如下代码创建一个新控制器:
<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Str;
use Illuminate\View\View;
use Laravel\Horizon\Horizon;
use Laravel\Horizon\Http\Controllers\HomeController;
class HorizonHomeController extends HomeController
{
/**
* Overrides default horizon route to support subdirectory hosting.
*/
public function index ()
{
// We use a plain request to check for the base url.
$request = request();
// Set up our base path.
$base_path = Str::substr($request->getBasePath(), 1);
if (!empty($base_path)) {
$base_path .= '/';
}
// Patch default horizon variables with our own base path.
$variables = Horizon::scriptVariables();
$variables['path'] = $base_path . config('horizon.path');
// Render horizon's home view.
return view('horizon::layout', [
'assetsAreCurrent' => Horizon::assetsAreCurrent(),
'horizonScriptVariables' => $variables,
'cssFile' => Horizon::$useDarkTheme ? 'app-dark.css' : 'app.css',
'isDownForMaintenance' => App::isDownForMaintenance(),
]);
}
}
剩下的就是告诉 Laravel 的服务容器,当HomeController
请求 Horizon 时,它应该提供我们的HorizonHomeController
类。在你的AppServiceProvider
, 在register()
方法的最后,设置这个:
// [...]
class AppServiceProvider extends ServiceProvider
{
// [...]
/**
* Register any application services.
*
* @return void
* @throws InvalidConfiguration
*/
public function register()
{
// [...]
// Horizon's subdirectory hack
$this->app->bind(
Laravel\Horizon\Http\Controllers\HomeController::class,
App\Http\Controllers\HorizonHomeController::class
);
}
// [...]
}
之后,您应该可以http(s)://<your-host>/<your-sub-dir>/horizon
正常浏览。
注意事项:
对我来说,修补已编译的 js 感觉更干净,这也有每次更新 Horizon 时都需要重新应用的缺点(这可以通过更新后的脚本来缓解composer
)。此外,对于其他要点,此解决方案仅覆盖呈现视图的方法,而不是路由,这意味着 Horizon 的所有身份验证机制(中间件和门)完全按照文档中的描述工作。