当软链接供应商目录时,Lumen 加载了错误的控制器
Lumen loaded wrong controller when vendor directory is softlinked
在我的示例设置中,我有 2 个目录(每个都是 lumen 8.x 项目,由 运行 composer create-project --prefer-dist laravel/lumen lumenNUMBER
创建)
- ~/www/lumen1/
- ~/www/lumen2/
在我的设置中,网络服务器是 apache/httpd,文档根目录设置为 ~/www/
在 lumen1 项目中:
- 已编辑文件:routes/web.php
$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"] );
- 已添加文件:app/Http/Controllers/CommonController.php
<?php
namespace App\Http\Controllers;
class CommonController extends Controller
{
public function route5() { "this is fifth route"; }
}
在 lumen2 项目中:
- 已编辑文件:routes/web.php
$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"] );
- 已添加文件:app/Http/Controllers/CommonController.php
<?php
namespace App\Http\Controllers;
class CommonController extends Controller
{
public function route5() { "this is fifth route"; }
public function route6() { "this is sixth route"; }
}
- 已添加文件:app/Http/Controllers/SomeController.php
<?php
namespace App\Http\Controllers;
class SomeController extends Controller
{
public function route4() { "this is fourth route"; }
}
问题
一切都运行很好,我可以提出这样的要求并得到预期的回应:
流明1:
- 请求
GET http://localhost/lumen1/public/route1
响应this is first route
- 请求
GET http://localhost/lumen1/public/route2
响应this is second route
- 请求
GET http://localhost/lumen1/public/route3
响应错误(预期):404
- 请求
GET http://localhost/lumen1/public/route4
响应错误(预期):404
- 请求
GET http://localhost/lumen1/public/route5
响应this is fifth route
- 请求
GET http://localhost/lumen1/public/route6
响应错误(预期):404
流明2:
- 请求
GET http://localhost/lumen2/public/route1
响应this is first route
- 请求
GET http://localhost/lumen2/public/route2
响应this is second route
- 请求
GET http://localhost/lumen2/public/route3
响应this is third route
- 请求
GET http://localhost/lumen2/public/route4
响应this is fourth route
- 请求
GET http://localhost/lumen2/public/route5
响应this is fifth route
- 请求
GET http://localhost/lumen2/public/route6
响应this is sixth route
但现在我尝试发挥创意并删除了 lumen2/vendor 目录,然后使 lumen2/vendor 中的 symlink 指向 ../lumen1/vendor
ln -s ../lumen1/vendor vendor
- ls -al 在 ~/www/lumen2 上的输出:
lrwxrwxrwx 1 kristian kristian 16 Apr 21 08:49 vendor -> ../lumen1/vendor
原因是我的磁盘空间不足space(这不是唯一的 lumen 项目,我知道它只有 40-50mb,但大小乘以项目数量)
现在请求和他们的响应是(注意省略了lumen1,因为它和上面一样):
- 请求
GET http://localhost/lumen2/public/route1
响应this is first route
- 请求
GET http://localhost/lumen2/public/route2
响应this is second route
- 请求
GET http://localhost/lumen2/public/route3
响应this is third route
- 请求
GET http://localhost/lumen2/public/route4
响应错误(预计不会):500 目标 class [App\Http\Controllers\SomeController] 不存在。
- 请求
GET http://localhost/lumen2/public/route5
响应this is fifth route
- 请求
GET http://localhost/lumen2/public/route6
响应错误(预计不会):404
我的分析
- 关闭路由不受软linked 供应商目录
的影响
- 使用软link供应商目录的路由将从link目标的控制器而不是它自己的控制器读取它的控制器
问题是:
- 为什么 softlinked vendor 目录让 lumen 从 'lumen1' 目录读取它的控制器?
- 如果这种方法不可行,那么如何减少 lumen and/or laravel 供应商目录上的磁盘 space 使用率?
我发现了问题:
我创建了 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.php
是 app-a view-a
GET http://localhost/b/view.php
是 app-b view-b
GET http://localhost/c/view.php
是 app-a view-c
GET http://localhost/d/view.php
是 app-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]
在我的示例设置中,我有 2 个目录(每个都是 lumen 8.x 项目,由 运行 composer create-project --prefer-dist laravel/lumen lumenNUMBER
创建)
- ~/www/lumen1/
- ~/www/lumen2/
在我的设置中,网络服务器是 apache/httpd,文档根目录设置为 ~/www/
在 lumen1 项目中:
- 已编辑文件:routes/web.php
$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"] );
- 已添加文件:app/Http/Controllers/CommonController.php
<?php
namespace App\Http\Controllers;
class CommonController extends Controller
{
public function route5() { "this is fifth route"; }
}
在 lumen2 项目中:
- 已编辑文件:routes/web.php
$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"] );
- 已添加文件:app/Http/Controllers/CommonController.php
<?php
namespace App\Http\Controllers;
class CommonController extends Controller
{
public function route5() { "this is fifth route"; }
public function route6() { "this is sixth route"; }
}
- 已添加文件:app/Http/Controllers/SomeController.php
<?php
namespace App\Http\Controllers;
class SomeController extends Controller
{
public function route4() { "this is fourth route"; }
}
问题
一切都运行很好,我可以提出这样的要求并得到预期的回应:
流明1:
- 请求
GET http://localhost/lumen1/public/route1
响应this is first route
- 请求
GET http://localhost/lumen1/public/route2
响应this is second route
- 请求
GET http://localhost/lumen1/public/route3
响应错误(预期):404 - 请求
GET http://localhost/lumen1/public/route4
响应错误(预期):404 - 请求
GET http://localhost/lumen1/public/route5
响应this is fifth route
- 请求
GET http://localhost/lumen1/public/route6
响应错误(预期):404
流明2:
- 请求
GET http://localhost/lumen2/public/route1
响应this is first route
- 请求
GET http://localhost/lumen2/public/route2
响应this is second route
- 请求
GET http://localhost/lumen2/public/route3
响应this is third route
- 请求
GET http://localhost/lumen2/public/route4
响应this is fourth route
- 请求
GET http://localhost/lumen2/public/route5
响应this is fifth route
- 请求
GET http://localhost/lumen2/public/route6
响应this is sixth route
但现在我尝试发挥创意并删除了 lumen2/vendor 目录,然后使 lumen2/vendor 中的 symlink 指向 ../lumen1/vendor
ln -s ../lumen1/vendor vendor
- ls -al 在 ~/www/lumen2 上的输出:
lrwxrwxrwx 1 kristian kristian 16 Apr 21 08:49 vendor -> ../lumen1/vendor
原因是我的磁盘空间不足space(这不是唯一的 lumen 项目,我知道它只有 40-50mb,但大小乘以项目数量)
现在请求和他们的响应是(注意省略了lumen1,因为它和上面一样):
- 请求
GET http://localhost/lumen2/public/route1
响应this is first route
- 请求
GET http://localhost/lumen2/public/route2
响应this is second route
- 请求
GET http://localhost/lumen2/public/route3
响应this is third route
- 请求
GET http://localhost/lumen2/public/route4
响应错误(预计不会):500 目标 class [App\Http\Controllers\SomeController] 不存在。 - 请求
GET http://localhost/lumen2/public/route5
响应this is fifth route
- 请求
GET http://localhost/lumen2/public/route6
响应错误(预计不会):404
我的分析
- 关闭路由不受软linked 供应商目录 的影响
- 使用软link供应商目录的路由将从link目标的控制器而不是它自己的控制器读取它的控制器
问题是:
- 为什么 softlinked vendor 目录让 lumen 从 'lumen1' 目录读取它的控制器?
- 如果这种方法不可行,那么如何减少 lumen and/or laravel 供应商目录上的磁盘 space 使用率?
我发现了问题:
我创建了 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.php
是app-a view-a
GET http://localhost/b/view.php
是app-b view-b
GET http://localhost/c/view.php
是app-a view-c
GET http://localhost/d/view.php
是app-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]