Обходной путь для генератора доктрин в кодовой базе PSR-4
С помощью Symfony 2 и доктрины на компьютере с Windows я пытаюсь
-
Создание сущностей из существующей схемы:
php app/console doctrine:mapping:import --force CoreBundle annotation
-
Создайте на них геттеры/сеттеры:
php app/console doctrine:generate:entities --path=/path/to/codebase/src/MyProject/CoreBundle/Entities CoreBundle
-
Создайте на них контроллеры REST CRUD, используя Voryx:
php app/console voryx:generate:rest --entity="CoreBundle:User"
Первые шаги работают нормально, и я могу найти сущности в своей папке CoreBundle/Entity с правильным пространство имен:
MyVendor\MyProject\CoreBundle\Entity
Пока все хорошо. Однако выполнение других 2 команд завершится ошибкой:
[RuntimeException]
Can't find base path for "CoreBundle" (path:
"\path\to\codebase\src\MyProject\CoreBundle", destination:
"/path/to/codebase/src/MyProject/CoreBundle").
Загрузка в моем файле composer.json выглядит так:
"autoload": {
"psr-4": {
"MyVendor\\": "src/"
}
},
Я обнаружил, что Доктрина не может иметь дело с пространствами имен PSR-4, вероятно, это и приводит к ее сбою.
Мне бы очень хотелось, чтобы сущности жили в ядре PSR-4, хотя - есть ли обходной путь для этого?
Я пробовал это, но это тоже не работает:
"autoload": {
"psr-0": {
"MyVendor\\MyProject\\CoreBundle\\Entity": "src/MyProject/CoreBundle/Entity/"
},
"psr-4": {
"MyVendor\\": "src/"
}
},
Спасибо.
2 answers
Пользователь janvennemann на GitHub исправил доктрину для PSR-4. Вы можете найти патч на Gist или ссылку здесь ниже
Шаг, чтобы исправить это
-
mkdir -p app/VendorOverride
; -
cp vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php app/VendorOverride/DisconnectedMetadataFactory.php
; - примените патч DisconnectedMetadataFactory;
- добавить
app/VendorOverride
в разделclassmap
вcomposer.json
; - выполнить
composer dump-autoload
.
Тогда почти все команды строительных лесов работают.
Отключенный патч PSR-4 metadatafactory
/**
* Get a base path for a class
*
* @param string $name class name
* @param string $namespace class namespace
* @param string $path class path
*
* @return string
* @throws \RuntimeException When base path not found
*/
private function getBasePathForClass($name, $namespace, $path)
{
$composerClassLoader = $this->getComposerClassLoader();
if ($composerClassLoader !== NULL) {
$psr4Paths = $this->findPathsByPsr4Prefix($namespace, $composerClassLoader);
if ($psr4Paths !== array()) {
// We just use the first path for now
return $psr4Paths[0];
}
}
$namespace = str_replace('\\', '/', $namespace);
$search = str_replace('\\', '/', $path);
$destination = str_replace('/'.$namespace, '', $search, $c);
if ($c != 1) {
throw new \RuntimeException(sprintf('Can\'t find base path for "%s" (path: "%s", destination: "%s").', $name, $path, $destination));
}
return $destination;
}
/**
* Gets the composer class loader from the list of registered autoloaders
*
* @return \Composer\Autoload\ClassLoader
*/
private function getComposerClassLoader() {
$activeAutloaders = spl_autoload_functions();
foreach($activeAutloaders as $autoloaderFunction) {
if (!is_array($autoloaderFunction)) {
continue;
}
$classLoader = $autoloaderFunction[0];
if ($classLoader instanceof \Symfony\Component\Debug\DebugClassLoader) {
$classLoader = $classLoader->getClassLoader()[0];
}
if (!is_object($classLoader)) {
continue;
}
if ($classLoader instanceof \Composer\Autoload\ClassLoader) {
return $classLoader;
}
}
return NULL;
}
/**
* Matches the namespace against all registered psr4 prefixes and
* returns their mapped paths if found
*
* @param string $namespace The full namespace to search for
* @param \Composer\Autoload\ClassLoader $composerClassLoader A composer class loader instance to get the list of psr4 preixes from
* @return array The found paths for the namespace or an empty array if none matched
*/
private function findPathsByPsr4Prefix($namespace, $composerClassLoader) {
foreach ($composerClassLoader->getPrefixesPsr4() as $prefix => $paths) {
if (strpos($namespace, $prefix) === 0) {
return $paths;
}
}
return array();
}
Если кто-нибудь столкнется с этой проблемой.. У меня наконец-то получилось. Я не совсем уверен, что именно это исправило, поэтому вот все шаги, которые я сделал:
- Когда я запускал Symfony 2.3, сначала я обновил версию до 2.7
- Я заново сгенерировал пакет с нуля... Я изменил расположение пакета на
MyProject\CoreBundle
и переименовал класс пакета в MyProjectCoreBundle.
Теперь я могу успешно выполнить все эти команды:
php app/console doctrine:mapping:import --force MyProjectCoreBundle annotation
php app/console doctrine:generate:entities MyProjectCoreBundle
php app/console doctrine:generate:form MyProjectCoreBundle:User
php app/console voryx:generate:rest --entity=MyProjectCoreBundle:User
(Обратите внимание, что вызов doctrine:generate:form
не было в ОП.)
Мое лучшее предположение заключается в том, что одним из этапов обновления было изменение автоматической загрузки композитора - это, или загрузчик 2.7, похоже, исправил это:
"autoload": {
"psr-4": { "": "src/", "SymfonyStandard\\": "app/" }
},