通过Composer 2自动加载器,Laravel基类找不到Trait。

7 浏览
0 Comments

通过Composer 2自动加载器,Laravel基类找不到Trait。

我正在使用较新版本的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:

# app/Notifications/MyBaseClass.php:

# app/Notifications/MyChildClass.php

奇怪的是,这段代码在我的本地开发环境中运行得很好,但无论我尝试什么,它在部署到运行在Docker容器中的服务器时都无法工作。我尝试了我能想到的一切,比如在composer.json中保存"optimize-autoloader": true,并在部署过程中运行composer dump-autoload -o,但没有任何修复的效果:https://getcomposer.org/doc/articles/autoloader-optimization.md。我担心Composer或Laravel可能没有正确地测试这种继承组合,所以这可能是工具中的一个bug。如果情况变得越来越糟,我将尝试以下(可能具有破坏性的)解决方法:

  • 调用composer dump-autoload -o(在部署过程中速度非常慢,因为这是一个大型项目,而且到目前为止似乎也没有修复它的效果)
  • 在每次部署之前通过rm vendor/composer/autoload_classmap.phprm vendor/composer/autoload_psr4.php和/或rm vendor/composer/autoload_namespaces.php(或类似的方法)删除vendor文件夹中的文件,以强制Composer重新构建。
  • 通过rm -rf vendor删除

这个可怕的部分是我们必须对我们的部署过程完全有信心。我们不能在服务器开发环境中通过手动删除vendor等内容来解决问题,然后在生产部署中失败,因为Composer在其vendor文件夹中遇到陈旧数据而绊倒。我的直觉是,这正是正在发生的事情,可能是由于从Composer 1升级到Composer 2或版本更改,或者是最近几个月工作中的陈旧缓存文件。即使有一个验证,比如"这个最小的示例项目在Docker上部署对我们来说是可行的",也将有助于缩小问题范围。编辑:这是一个关于Composer自动加载器工作原理的有用资源:https://jinoantony.com/blog/how-composer-autoloads-php-files

0
0 Comments

Laravel基类无法通过Composer 2自动加载器找到的Trait是什么原因?以及如何解决?

问题的出现原因是文件名的大小写问题。最初,文件名以小写字母开头,如apiResponser.php。后来,我对文件进行了一些更改,并将文件名改为ApiResponser.php,然后将其部署到生产环境,但是... 哎呀,出现了问题。

我遇到了同样的问题。唯一解决方法是进行git名称替换:

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

通过这种方式,我成功解决了问题。我知道你可能采用了其他方法来解决这个问题,但这种解决方法可能会帮助到其他开发者。

0
0 Comments

问题出现的原因是AWS上的容器/文件系统区分大小写,而我的本地开发环境(macOS)是不区分大小写的。

我原本的Trait(保密)在其名称结尾处是以URL结尾的,但是我在基类中引用它时,路径和使用的名称是Url

所以这个问题与Trait、基类或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');

然后在GitLab中部署未合并的代码,并将响应与AWS Cloudwatch中的错误进行比较,这时候错误的拼写错误就会显现出来。

然后我使用以下命令移除了临时提交:

git reset --soft HEAD^

并使用以下命令强制推送了我的分支:

git push --force-with-lease

因此,我能够解决这个问题,而不影响我们的CI/CD设置或永久地将代码提交到develop或master分支。

我已经做了很多年开发,甚至怀疑这里存在大小写敏感的问题,但有时我们对问题太过于熟悉。如果您陷入代码中并即将发作焦虑,那么有另一双眼睛从头原理上审查您的思考过程会有所帮助。

我还需要找出如何将本地的Docker容器也设置为区分大小写,以与服务器匹配(因为这是使用Docker容器的初衷)。

0