当软链接供应商目录时,Lumen 加载了错误的控制器

Lumen loaded wrong controller when vendor directory is softlinked

在我的示例设置中,我有 2 个目录(每个都是 lumen 8.x 项目,由 运行 composer create-project --prefer-dist laravel/lumen lumenNUMBER 创建)

在我的设置中,网络服务器是 apache/httpd,文档根目录设置为 ~/www/

在 lumen1 项目中:

$router->get('/route1', function () use ($router) {
    return "this is first route";
});
$router->get('/route2', function () use ($router) {
    return "this is second route";
});
$router->get("/route5", ["uses"=>"CommonController@route5"] );

<?php
namespace App\Http\Controllers;
class CommonController extends Controller
{
    public function route5() { "this is fifth route"; }
}

在 lumen2 项目中:

$router->get('/route1', function () use ($router) {
    return "this is first route";
});
$router->get('/route2', function () use ($router) {
    return "this is second route";
});
$router->get('/route3', function () use ($router) {
    return "this is third route";
});
$router->get("/route4", ["uses"=>"SomeController@route4"] );
$router->get("/route5", ["uses"=>"CommonController@route5"] );
$router->get("/route6", ["uses"=>"CommonController@route6"] );
<?php
namespace App\Http\Controllers;
class CommonController extends Controller
{
    public function route5() { "this is fifth route"; }
    public function route6() { "this is sixth route"; }
}
<?php
namespace App\Http\Controllers;
class SomeController extends Controller
{
    public function route4() { "this is fourth route"; }
}

问题

一切都运行很好,我可以提出这样的要求并得到预期的回应:

流明1:

流明2:

但现在我尝试发挥创意并删除了 lumen2/vendor 目录,然后使 lumen2/vendor 中的 symlink 指向 ../lumen1/vendor

原因是我的磁盘空间不足space(这不是唯一的 lumen 项目,我知道它只有 40-50mb,但大小乘以项目数量)

现在请求和他们的响应是(注意省略了lumen1,因为它和上面一样):

我的分析

问题是:

我发现了问题:

我创建了 4 个目录,每个目录名为 a、b、c、d,每个目录包含这样 php 个文件:

  • view.php: <?php require_once("vendor/autoload.php"); echo "view-[x]";

  • vendor/autoload.php: <?php require_once(dirname( __FILE__ )."/../controller.php");

  • controller.php: <?php echo "app-[x]"; 其中[x]替换为目录名(所以a/controller.php包含<?php echo "app-a"; ,b/controller.php包含<?php echo "app-b"; ,等等...)

  • 目录a是'master'/'main'

  • 目录b是从目录a复制过来的cp -r a b

  • 目录 c 是从目录 a cp -r a c 复制的,然后我删除了 c/vendor,然后从 a 的供应商目录软链接它:cd c; ln -s ../a/vendor vendor

  • 目录 d 是从目录 a cp -r a d 复制的,然后我删除了 d/vendor,然后从 a 的供应商目录硬链接它:cp -al a/vendor d/vendor

我发现输出来自:

  • GET http://localhost/a/view.phpapp-a view-a
  • GET http://localhost/b/view.phpapp-b view-b
  • GET http://localhost/c/view.phpapp-a view-c
  • GET http://localhost/d/view.phpapp-d view-d

解决方案:不要软链接,只需硬链接。

这解决了:

  • 与直接复制供应商目录相比,磁盘使用率更低(尽管它仍然消耗 inode,我的 laravel 项目有 80mb+ 供应商目录,通过 df -h 观察硬链接消耗大约 6mb)
  • http 请求由正确的控制器提供服务

为什么这么麻烦?

正如 NicoHaase 在对我的问题的评论中所述,两个单独的应用程序必须保留在两个单独的供应商文件夹中。

是的,我知道,我知道这一点,我非常同意。但万一它不是两个单独的应用程序。它是 git 存储库中的一个应用程序,它被制作成多个目录(通过 git 工作树)。我有一个铁定的规则,当我更新一个 branch/worktree 的 composer.lock/composer.json (依赖项)时,我必须更新其他人。所以这里的目标是节省磁盘 space.

那我为什么不直接使用 git 的结帐命令呢?那是因为我希望能够同时在多个分支上工作。隐藏 and/or 提交未完成的更改是不可能的。

为什么要为节省磁盘而烦恼space?当你有这么多空闲 space 时,你将尝试节省磁盘 space:

$ # this is the size of my vendor directory
du -sh vendor
83M     vendor
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       XXXX  XXX  413M  XXX /

$ rm -r vendor
$ # this is my free space when I deleted vendor directory
$ df -h       
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       XXXX  XXX  419M  XXX /

$ cp -r ../../myproject/vendor/ vendor
$ # this is my free space when copied vendor directory
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       XXXX  XXX  336M  XXX /

$ cp -al ../myproject/vendor/ vendor
$ # this is my free space when using hardlinked vendor directory
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       XXXX  XXX  413M  XXX /

TL;DR: 不要软链接,改用硬链接

代替ln -s [target] [link],做cp -al [target] [link]