PSR-4 代码库中条令生成器的解决方法
Workaround for doctrine generator in PSR-4 codebase
在 Windows 机器上使用 Symfony 2 和 Doctrine 我正在尝试
从现有模式生成实体:
php app/console doctrine:mapping:import --force CoreBundle annotation
对它们生成 getters/setters:
php app/console doctrine:generate:entities --path=/path/to/codebase/src/MyProject/CoreBundle/Entities CoreBundle
使用 Voryx:
在它们上生成 REST CRUD 控制器
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/"
}
},
我发现 Doctrine can't deal with PSR-4 namespaces,这可能是它失败的原因。
不过,我真的希望这些实体存在于 PSR-4 CoreBundle 中 - 有解决方法吗?
我试过了,但也不管用:
"autoload": {
"psr-0": {
"MyVendor\MyProject\CoreBundle\Entity": "src/MyProject/CoreBundle/Entity/"
},
"psr-4": {
"MyVendor\": "src/"
}
},
谢谢。
如果有人遇到这个问题..我终于让它工作了。我不太确定究竟是什么修复了它,所以这里是我执行的所有步骤:
- 因为我是 运行宁 Symfony 2.3,首先
- 我从头开始重新生成包...我将包的位置更改为
MyProject\CoreBundle
并将包 class 重命名为 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
的调用不在 OP 中。)
我最好的猜测是升级的一个步骤是更改作曲家自动加载 - 这个或 2.7 自动加载器似乎已修复它:
"autoload": {
"psr-4": { "": "src/", "SymfonyStandard\": "app/" }
},
GitHub 上的用户 janvennemann 修复了 PSR-4 的 Doctrine。您可以找到 patch on Gist,或在下方链接
解决问题的步骤
mkdir -p app/VendorOverride
;
cp vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php app/VendorOverride/DisconnectedMetadataFactory.php
;
- 应用 DisconnectedMetadataFactory 补丁;
- 将
app/VendorOverride
添加到 composer.json
中的 classmap
部分;
- 运行
composer dump-autoload
.
那么几乎所有脚手架命令都可以工作。
DisconnectedMetadataFactory PSR-4 补丁
/**
* 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();
}
在 Windows 机器上使用 Symfony 2 和 Doctrine 我正在尝试
从现有模式生成实体:
php app/console doctrine:mapping:import --force CoreBundle annotation
对它们生成 getters/setters:
php app/console doctrine:generate:entities --path=/path/to/codebase/src/MyProject/CoreBundle/Entities CoreBundle
使用 Voryx:
在它们上生成 REST CRUD 控制器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/"
}
},
我发现 Doctrine can't deal with PSR-4 namespaces,这可能是它失败的原因。
不过,我真的希望这些实体存在于 PSR-4 CoreBundle 中 - 有解决方法吗?
我试过了,但也不管用:
"autoload": {
"psr-0": {
"MyVendor\MyProject\CoreBundle\Entity": "src/MyProject/CoreBundle/Entity/"
},
"psr-4": {
"MyVendor\": "src/"
}
},
谢谢。
如果有人遇到这个问题..我终于让它工作了。我不太确定究竟是什么修复了它,所以这里是我执行的所有步骤:
- 因为我是 运行宁 Symfony 2.3,首先
- 我从头开始重新生成包...我将包的位置更改为
MyProject\CoreBundle
并将包 class 重命名为 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
的调用不在 OP 中。)
我最好的猜测是升级的一个步骤是更改作曲家自动加载 - 这个或 2.7 自动加载器似乎已修复它:
"autoload": {
"psr-4": { "": "src/", "SymfonyStandard\": "app/" }
},
GitHub 上的用户 janvennemann 修复了 PSR-4 的 Doctrine。您可以找到 patch on Gist,或在下方链接
解决问题的步骤
mkdir -p app/VendorOverride
;cp vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php app/VendorOverride/DisconnectedMetadataFactory.php
;- 应用 DisconnectedMetadataFactory 补丁;
- 将
app/VendorOverride
添加到composer.json
中的classmap
部分; - 运行
composer dump-autoload
.
那么几乎所有脚手架命令都可以工作。
DisconnectedMetadataFactory PSR-4 补丁
/**
* 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();
}