对存在的文件的composer更新引发ReflectionException



为了让这件事更有趣,如果我运行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 SaveeoBoardObserversBoardEventListener does not exist  

BoardEventListener.php(放置在Saveeo/Board/Obstators中)

<?php
namespace SaveeoBoardObservers;
use SaveeoServicesHashIdsContractsHashIds as HashIdService;
class BoardEventListener {
private $hashIdService;
public function __construct(HashIdService $hashIdService) {
$this->hashIdService = $hashIdService;
}
public function whenBoardIsCreated($event) {
$this->hashIdService->syncHashIdValueOnModelChanges($event, 'board');
}
public function whenBoardIsUpdated($event) {
$this->hashIdService->syncHashIdValueOnModelChanges($event, 'board');
}
public function subscribe($events) {
$events->listen(
'SaveeoBoardObserversEventsBoardHasBeenCreated',
'SaveeoBoardObserversBoardEventListener@whenBoardIsCreated'
);
$events->listen(
'SaveeoBoardObserversEventsBoardHasBeenUpdated',
'SaveeoBoardObserversBoardEventListener@whenBoardIsUpdated'
);
}
}

EventServiceProvider.php(位于Saveeo/Providers中)

<?php
namespace SaveeoProviders;
use IlluminateContractsEventsDispatcher as DispatcherContract;
use IlluminateFoundationSupportProvidersEventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
//
];
/**
* The subscriber classes to register.
*
* @var array
*/
protected $subscribe = [
'SaveeoBoardObserversBoardEventListener',
];
/**
* Register any other events for your application.
*
* @param  IlluminateContractsEventsDispatcher  $events
* @return void
*/
public function boot(DispatcherContract $events) {
parent::boot($events);
//
}
}

这是文件夹结构。这里看不出有什么问题吗?

https://i.stack.imgur.com/JQ2l1.jpg

Composer.json

{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"type": "project",
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.2.*",
"firebase/php-jwt": "~2.0",
"guzzlehttp/guzzle": "5.*",
"guzzlehttp/oauth-subscriber": "0.2.0",
"laravel/socialite": "2.*",
"league/flysystem-aws-s3-v3": "~1.0",
"aws/aws-sdk-php": "3.*",
"bugsnag/bugsnag-laravel": "1.*",
"vinkla/hashids": "^2.3"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~4.0",
"phpspec/phpspec": "~2.1",
"tymon/jwt-auth": "0.5.*",
"symfony/dom-crawler": "~3.0",
"symfony/css-selector": "~3.0"
},
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"Saveeo\": "app/"
}
},
"autoload-dev": {
"classmap": [
"tests/TestCase.php"
]
},
"scripts": {
"post-install-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"pre-update-cmd": [
"php artisan clear-compiled"
],
"post-update-cmd": [
"php artisan optimize"
],
"post-root-package-install": [
"php -r "copy('.env.example', '.env');""
],
"post-create-project-cmd": [
"php artisan key:generate"
]
},
"config": {
"preferred-install": "dist"
}
}

看起来我们将app/目录中类的自动加载命名空间(手动或使用artisan app:name)从composer中的App(默认值)更改为Saveeo。json:

"autoload": {
"psr-4": {
"Saveeo\": "app/"
}
},

当我们理解其含义时,这是完美的。当我们查看导致异常的文件(括号中的名称空间)的项目文件夹结构时,我们可以看到问题中描述的问题:

app                    (Saveeo)
├── Saveeo             (SaveeoSaveeo)
│   ├── Board          (SaveeoSaveeoBoard)
│   │   ├── Observers  (SaveeoSaveeoBoardObservers)
│   │   │   ├── BoardEventListener
└── ...

为了与PSR-4兼容,BoardEventListener的命名空间应该是SaveeoSaveeoBoardObservers,因为它存在于嵌套在app/下的Saveeo/件名和路径而不是文件中声明的命名空间来解析类文件[Composer从类文件中读取命名空间以创建优化的类映射,只要顶级命名空间匹配即可。请参阅更新。]

如果我们不想更改应用程序的目录结构,并且不想在命名空间中使用两个Saveeo,我们可以配置Composer在自动加载类时将两个目录合并到同一命名空间中:

"autoload": {
"psr-4": {
"Saveeo\": [ "app/", "app/Saveeo/" ]
}
},

并记住CCD_ 9。

它有效,但我不建议在实践中这样做。它偏离了PSR-4标准,使应用程序容易受到名称空间冲突的影响,并且可能会使项目的其他工作人员感到困惑。我建议您展平Saveeo命名空间和目录,或者为嵌套目录中的类选择不同的命名空间。

。。。如果我运行composer dump-autoload -o,事情会很好,但我很好奇为什么当我运行composer update时会出现错误。。。?

生成自动加载缓存文件时,Composer实际上不会执行您的代码。然而,在大多数Laravel应用程序(直到5.5)中,artisan optimize命令在composer update之后运行,确实启动应用程序以执行其操作,因此执行问题代码,我们看到异常。

更新:

如果使用SaveeoBoardetc与使用SaveeoSaveeoBoardetc相比是错误的,那么整个应用程序中的其他文件将不起作用,但它们起作用。

当我们生成优化的自动加载器时,我们可以从技术上使用与项目目录结构不匹配的非PSR-4命名空间,就像我们准备生产应用程序一样:

composer dump-autoload --optimize 

这是因为Composer将扫描每个类文件的名称空间,以创建静态类映射。当我们不指定--optimize时,Composer依赖于动态自动加载,它将文件路径与命名空间匹配,因此无法解决非标准的命名空间或目录结构。

有问题的项目的名称空间在很大程度上是有效的,尽管它没有遵循PSR-4,因为我们使用dump-autoload-o选项手动转储优化的自动加载器。但是,我们看到了错误消息,因为composer update在运行更新之前删除了缓存的类映射,因此,当artisan optimize命令运行时,类映射不再包含我们转储的类。

我们可以通过在Composer.json:中设置optimize-autoloader配置指令,将Composer配置为始终优化自动加载器

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

其应当为该项目修复CCD_ 23和CCD_。要解决非标准的名称空间问题有点麻烦。使用这种方法,请记住,每当我们在开发中添加一个不遵循PSR-4的新文件时,我们都需要转储自动加载器。

这似乎与Composer PSR自动加载有关。默认情况下,Laravel将包括

"autoload": {
"psr-4": {
"App\": "app/"
}
}

这意味着"App命名空间的根在app文件夹中,并且从那里匹配命名空间到文件夹结构"。

您的Saveeo命名空间尚未注册(它不在App层次结构中),因此Composer不知道它的位置。

如果您在composer.json(然后是dump-autoload)中添加另一行,它应该会起作用

"autoload": {
"psr-4": {
"App\": "app/",
"Saveeo\": "app/Saveeo"
}
}

或者,正如另一个答案所指出的,您可以将整个Saveeo命名空间放置在App中(例如,它就是AppSaveeoBoardObserversEventsBoardHasBeenCreated)。然而,Saveeo命名空间似乎是一个自包含的模块,将其作为一个单独的命名空间可能更合理,而不是在其所有文件中重命名命名空间。

我相信如果您只是将名称空间更改为:

AppSaveeoBoardObservers代替SaveeoBoardObservers

你所有的问题都应该解决。如果您有创建这个新名称空间的原因,而不是从基本的App名称空间分支出来,请告诉我。

相关内容

  • 没有找到相关文章

最新更新