Php 存在的文件的编写器更新时引发ReflectionException
为了让这更有趣,如果我运行Php 存在的文件的编写器更新时引发ReflectionException,php,laravel,laravel-5,composer-php,Php,Laravel,Laravel 5,Composer Php,为了让这更有趣,如果我运行composer dump autoload-o,事情会很顺利,但我很好奇,为什么在运行composer update时会出现错误?我需要弄清这件事的真相。快速修复并不能让我内心快乐 aligajani at Alis-MBP in ~/Projects/saveeo on master ✗ [faaba4
composer dump autoload-o
,事情会很顺利,但我很好奇,为什么在运行composer update
时会出现错误?我需要弄清这件事的真相。快速修复并不能让我内心快乐
aligajani at Alis-MBP in ~/Projects/saveeo on master ✗ [faaba41c] 4:53
> composer update
> php artisan clear-compiled
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Package guzzle/guzzle is abandoned, you should avoid using it. Use guzzlehttp/guzzle instead.
Generating autoload files
> php artisan optimize
[ReflectionException]
Class Saveeo\Board\Observers\BoardEventListener does not exist
BoardEventListener.php(位于Saveeo/Board/observer中)
我相信如果您将名称空间更改为:
App\Saveeo\Board\observators
而不是Saveeo\Board\observators
你所有的问题都应该解决。请告诉我您是否有创建此新名称空间的原因,而不仅仅是从基本应用程序名称空间分支。这似乎与Composer PSR自动加载有关。默认情况下,Laravel将包括
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
这意味着“App
命名空间的根在App
文件夹中,并从那里匹配命名空间到文件夹结构”
您的Saveeo
命名空间尚未注册(它不在App
层次结构中),因此Composer不知道它的位置
如果在composer.json中添加另一行(然后dump autoload
),则应该可以正常工作
或者,正如另一个答案所指出的,您可以将整个
Saveeo
名称空间放在App
中(例如,它是App\Saveeo\Board\observators\Events\Board\hasEncreated
)。然而,您的Saveeo
名称空间似乎是一个自包含的模块,将其作为一个单独的名称空间可能更合理,而不是在其所有文件中重命名名称空间。看起来我们更改了自动加载名称空间(手动或使用artisan app:name
)对于从composer.json中的app
(默认)到Saveeo
的app/目录中的类:
当我们理解其含义时,这是完全可以做到的。当我们查看导致异常的文件的项目文件夹结构时,可以看到问题中描述的问题(名称空间在括号中):
app(Saveeo)
├── Saveeo(Saveeo\Saveeo)
│ ├── 线路板(Saveeo\Saveeo\Board)
│ │ ├── 观察员(Saveeo\Saveeo\Board\Observators)
│ │ │ ├── BoardEventListener
└── ...
为了与PSR-4兼容,BoardEventListener
的名称空间应为Saveeo\Saveeo\Board\observer
,因为它存在于app/下嵌套的saveo/目录中。实现基于文件名和路径解析类文件,而不是基于文件中声明的名称空间。[只要顶级命名空间匹配,Composer就会从类文件中读取命名空间以创建优化的类映射。请参阅更新。]
如果我们不想更改应用程序的目录结构,也不想在命名空间中使用两个Saveeo
s,我们可以将Composer配置为在自动加载类时将两个目录合并到同一命名空间中:
"autoload": {
"psr-4": {
"Saveeo\\": [ "app/", "app/Saveeo/" ]
}
},
…并记住composer dump autoload
这是可行的,但我不建议在实践中使用。它偏离了PSR-4标准,使应用程序容易受到名称空间冲突的影响,并且可能会使从事项目工作的其他人感到困惑。我建议您将Saveeo
名称空间和目录展平,或者为嵌套目录中的类选择不同的名称空间
…如果我运行composer dump autoload-o,一切正常,但我很好奇,当我运行composer update
时,为什么会出现错误
生成自动加载缓存文件时,Composer实际上不会执行您的代码。但是,在大多数Laravel应用程序(直到5.5版)中,artisan optimize
命令在composer update之后运行,确实会引导应用程序执行其操作,因此问题代码会执行,我们看到异常
更新:
如果使用Saveeo\Board\etc
与使用Saveeo\Saveeo\Board\etc
相比是错误的,那么整个应用程序中的其他文件将不起作用,但它们确实起作用
我们可以在技术上使用与项目目录结构不匹配的非PSR-4名称空间来生成优化的自动加载程序,就像我们准备生产应用程序一样:
composer dump-autoload --optimize
这是因为Composer将扫描每个类文件中的名称空间以创建静态类映射。当我们不指定--optimize
时,Composer依赖于动态自动加载,它将文件路径匹配到名称空间,因此非标准名称空间或目录结构无法解析
所讨论项目的名称空间在大部分情况下都有效,即使它不遵循PSR-4,因为我们正在使用-o
选项来手动转储优化的自动加载程序。但是,我们看到了错误消息,因为composer update
在运行更新之前删除了缓存的类映射,因此,当artisan optimize
命令运行时,类映射不再包含我们转储的类
我们可以通过在Composer.json中设置optimize autoloader
configuration指令将Composer配置为:
…这将修复此项目的
安装
和更新
命令。要解决非标准名称空间问题有点麻烦。使用这种方法,请记住,每当我们在开发中添加一个不符合PSR-4的新文件时,我们都需要转储自动加载程序。我为什么要使用App
名称空间Saveoo
就是这样。您的Saveeo目录位于您的应用程序目录下。那么,为什么要在现有名称空间根中创建第二个名称空间根呢?你认为这样做有好处吗?生孩子
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
"autoload": {
"psr-4": {
"App\\": "app/",
"Saveeo\\": "app/Saveeo"
}
}
"autoload": {
"psr-4": {
"Saveeo\\": "app/"
}
},
"autoload": {
"psr-4": {
"Saveeo\\": [ "app/", "app/Saveeo/" ]
}
},
composer dump-autoload --optimize
"config": {
"optimize-autoloader": true
}