使用 Composer 2 自动加载器的 Laravel 基类找不到特征?

Posted

技术标签:

【中文标题】使用 Composer 2 自动加载器的 Laravel 基类找不到特征?【英文标题】:Trait not found by Laravel base class using Composer 2 autoloader? 【发布时间】:2022-01-22 14:06:26 【问题描述】:

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

Trait 'App\Traits\MyTrait' not found

类似于:

Laravel Custom Trait Not Found

下面是代码的总体布局:

# app/Traits/MyTrait.php:
<?php

namespace App\Traits;

trait MyTrait 
    // ...

# app/Notifications/MyBaseClass.php:
<?php

namespace App\Notifications;

use App\Traits\MyTrait;

class MyBaseClass

    use MyTrait;

    // ...

# app/Notifications/MyChildClass.php
<?php

namespace App\Notifications;

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

【问题讨论】:

以上应该可以。正如你所说,它适用于你的开发。所以它有效。我们不知道为什么它在您部署后不起作用,但其中有很多细节我们不知道我们会猜测。 几点:composer dump-outoload -o 在部署时是正常的。在部署应用程序的新版本时,您始终应该这样做。其他选项不太合理,但由于在我的部署中(以及在我能想到的大多数 good 部署策略中),您将在部署时完全重建 vendor...。有点多余。同样,由于我们不知道您的部署策略,所以只是猜测 特别是如果您使用 docker 容器:那么您的 vendor 目录绝不应该是“陈旧的”,因为在每次部署时,您都在构建一个新映像,其中应该包括通过 composer install。跨度> 为了您的方便,是的,“这个部署到 Docker 的最小示例项目完全为我们工作”。甚至有点奇怪。 “我担心这种继承排列可能没有被 Composer 或 Laravel 正确测试,所以这可能是工具中的一个错误。”这绝不是一个不寻常的“继承排列”,我可以向你保证,它在 Laravel 基础代码中被使用了数百次。 “其供应商文件夹中的陈旧数据”您的部署目标中根本不应该有预先存在的vendor 目录。您的 composer.lock 应该是您的 VCS 的一部分,composer install 在部署期间运行。你的开发环境和你的生活是什么? 【参考方案1】:

问题原来是由 AWS 上的容器/文件系统区分大小写引起的,但我在 ma​​cOS 上的本地开发环境不区分大小写。。 p>

我的原始特征(保密)在其名称中以 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 中 deployed without merging 并将响应与 AWS Cloudwatch 中的错误进行比较,这是错误跳出的时候。

然后我删除了临时提交:

git reset --soft HEAD^

然后强行推动我的分支:

git push --force-with-lease

所以能够在不影响我们的 CI/CD 设置或将代码永久提交到开发或主分支的情况下解决这个问题。

我已经这样做了很多年,甚至怀疑这里存在区分大小写的问题,但有时我们离问题太近了。如果您对代码深有了解并且即将出现焦虑症,那么让另一双眼睛从第一原则与您一起回顾您的思维过程会有所帮助。

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

【讨论】:

【参考方案2】:

我遇到了同样的问题,这与我的文件名有关。我一开始是用小写的,即:apiResponser.php。我添加了一些更改并将我的文件重命名为 ApiResponser.php 并将其发送到生产环境,但是...... 哦,哦!

我遇到了同样的问题。

对我有用的唯一方法是替换 git 名称:

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

这样我就可以解决了。我知道你已经解决了 另一种方式,但这可能有助于其他开发人员。 ?

【讨论】:

以上是关于使用 Composer 2 自动加载器的 Laravel 基类找不到特征?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Composer 的自动加载

Git克隆的laravel 5.2项目不会迁移

使用 Composer 自动加载 PSR-4

使用composer 实现自动加载

Composer 自动加载自定义类

composer+psr-4实现自动加载