0

我已经在子文件夹中安装了 Laravel,并正在尝试安装 Horizo​​n。路由到“test.com/sub-folder/horizo​​n”后,所有损坏的设计以及内部链接都指向主域而不是主域没有子文件夹。

经过搜索,似乎是github issue中已经报告的已知问题

当 Laravel 安装在子文件夹中时,是否有任何解决方法可以使 Horizo​​n 工作?

4

2 回答 2

2

如果你迫切需要这样做,这里有一个 hack:

  1. public\vendor\horizon\app.js中,搜索window.Horizon.basePath
  2. 替换window.Horizon.basePath="/"+window.Horizon.path;window.Horizon.basePath="/[you sub-directoy]/"+window.Horizon.path;

它应该可以工作......直到有一天你运行更新并且它神秘地停止工作。

于 2020-11-09T15:37:41.467 回答
1

我有一个只涉及 PHP 的解决方案。

正如@Isaiahiroko 所指出的,这个问题是为 Horizo​​nbasePath的界面定义的。该代码在Laravel\Horizon\Http\Controllers\HomeController::index(). 想法是这样的:我们将把我们自己的控制器实现传递给 Laravel 的服务容器,该控制器将覆盖传递给 Horizo​​nbasePath接口的定义。

使用如下代码创建一个新控制器:

<?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请求 Horizo​​n 时,它应该提供我们的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 感觉更干净,这也有每次更新 Horizo​​n 时都需要重新应用的缺点(这可以通过更新后的脚本来缓解composer)。此外,对于其他要点,此解决方案仅覆盖呈现视图的方法,而不是路由,这意味着 Horizo​​n 的所有身份验证机制(中间件和门)完全按照文档中的描述工作。

于 2022-02-14T16:08:09.790 回答