使用Composer 2自动加载器的Laravel基类没有找到Trait



截至本文撰写之时,我正在进行一个使用PHP、Laravel和Composer 2的新ish版本的Laravel项目。我在几个现有的特征文件旁边添加了一个新的app/Traits/MyTrait.php文件,但不幸的是Composer绝对不会检测到新文件。我得到这个错误:

Trait 'AppTraitsMyTrait' not found

类似于:

未找到Laravel自定义属性

以下是代码的总体布局:

# app/Traits/MyTrait.php:
<?php
namespace AppTraits;
trait MyTrait {
// ...
}
# app/Notifications/MyBaseClass.php:
<?php
namespace AppNotifications;
use AppTraitsMyTrait;
class MyBaseClass
{
use MyTrait;
// ...
}
# app/Notifications/MyChildClass.php
<?php
namespace AppNotifications;
class MyChildClass extends MyBaseClass
{
// ...
}

奇怪的是,这段代码在我的本地开发中运行得很好,但无论我尝试什么,当它在Docker容器中运行时部署到服务器时都不会工作。我已经尝试了我能想到的一切,比如将"optimize-autoloader": true保存在composer.json中,并在部署期间运行composer dump-autoload -o,但没有任何修复方法:

https://getcomposer.org/doc/articles/autoloader-optimization.md

我担心Composer或Laravel可能没有正确测试这种继承排列,所以这可能是工具中的一个错误。如果情况越来越糟,我会尝试以下(潜在的破坏性)解决方案:

  • 调用composer dump-autoload -o(大大降低了部署速度,因为这是一个大型项目,到目前为止似乎还没有解决它)
  • 在每次部署之前通过vendor文件夹中的rm vendor/composer/autoload_classmap.phprm vendor/composer/autoload_psr4.php和/或rm vendor/composer/autoload_namespaces.php(或类似)进行删除,以强制Composer重新生成
  • 通过rm -rf vendor删除

这件事的险恶之处在于,我们必须对我们的部署过程充满信心。我们不能在服务器开发环境中手动删除vendor之类的东西,然后在生产部署中失败,因为Composer在其vendor文件夹中被过时的数据绊倒了。我的直觉是,这正是发生的事情,可能是由于最近几个月从Composer 1升级到Composer 2,或者版本更改或缓存文件过时。

即使是像";这个部署到Docker的最小样本项目为我们工作";将有助于缩小范围,谢谢。

编辑:这是一个关于Composer自动加载器如何工作的有用资源:https://jinoantony.com/blog/how-composer-autoloads-php-files

问题是由AWS上的容器/文件系统区分大小写引起的,但我在macOS上的本地开发环境不区分大小写

我最初的特征(保密)以名称中的URL结尾,但我将其路径包含为,并在基类中使用为Url

所以这个问题与特性、基类或Composer无关。它也不需要对composer.json进行任何修改,也不需要我们在部署过程中对其进行任何调用。但我认为在composer.json中使用它仍然是最好的做法,我目前也在本地开发中使用它(好/坏?):

"config": {
"optimize-autoloader": true
},

这里(整个行业)的真正问题是:

  • 含糊的错误消息
  • 代码缺乏深入研究和查找实际原因的能力(例如,尝试以不区分大小写的方式加载并在发现时返回警告)
  • 缺少用户的操作项(你检查过案例吗?检查过文件是否存在?检查过的文件权限?等等,写在错误消息中,可能还有一个支持页面/论坛的链接)

将ssh插入服务器(按设计)并不方便。因此,为了解决故障,我暂时将其提交到我的分支:

# app/Http/Controllers/TestController.php
class TestController extends Controller
{
public function test()
{
return response('<pre>' . 
'# /var/www/html/vendor/composer/autoload_classmap.php' . "n" . file_get_contents('/var/www/html/vendor/composer/autoload_classmap.php') . "n" .
'# /var/www/html/vendor/composer/autoload_files.php' . "n" . file_get_contents('/var/www/html/vendor/composer/autoload_files.php') . "n" .
'# /var/www/html/vendor/composer/autoload_namespaces.php' . "n" . file_get_contents('/var/www/html/vendor/composer/autoload_namespaces.php') . "n" .
'# /var/www/html/vendor/composer/autoload_psr4.php' . "n" . file_get_contents('/var/www/html/vendor/composer/autoload_psr4.php') . "n" .
'# /var/www/html/vendor/composer/autoload_real.php' . "n" . file_get_contents('/var/www/html/vendor/composer/autoload_real.php') . "n" .
'# /var/www/html/vendor/composer/autoload_static.php' . "n" . file_get_contents('/var/www/html/vendor/composer/autoload_static.php') . "n"
);
}
}
# routes/api.php
Route::get('/test', 'TestController@test');

然后在没有合并的情况下在GitLab中部署,并将响应与AWS Cloudwatch中的错误进行比较,也就是拼写错误跳出来的时候。

然后我删除了临时提交:

git reset --soft HEAD^

武力推动了我的分支:

git push --force-with-lease

因此,我们能够在不影响CI/CD设置或将代码永久提交给开发或主分支的情况下解决此问题。

我已经做了很多年了,甚至怀疑这里有一个病例敏感性问题,但有时我们离这个问题太近了。如果你深陷代码,即将患上焦虑症,那么让另一双眼睛从第一原则开始与你一起回顾你的思维过程会有所帮助。

我还需要弄清楚如何以区分大小写的方式运行本地Docker容器,以匹配服务器(因为这就是使用Docker容器的全部意义所在)。

我遇到了同样的问题,它与我的文件名有关。我一开始就把它放在小写,也就是:apiResponser.php。我添加了一些更改,并将文件重命名为ApiResponser.php,并将其发送到生产中,但是哦,哦

我也有同样的问题。

它对我唯一有效的方法是,进行git名称替换:

📦 git mv app/Traits/apiResponser.php app/Traits/ApiResponser.php

这样我就能解决问题。我知道你已经解决了然而,另一种方式可能会帮助另一个开发人员。🙂

最新更新