Workaround for doctrine generator in PSR-4 codebase

感情迁移 提交于 2019-12-04 14:09:38

User janvennemann on GitHub fixed Doctrine for PSR-4. You can find the patch on Gist, or linked here below

Step to fix it

  1. mkdir -p app/VendorOverride;
  2. cp vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php app/VendorOverride/DisconnectedMetadataFactory.php;
  3. apply the DisconnectedMetadataFactory patch;
  4. add app/VendorOverride to the classmap section in composer.json;
  5. run composer dump-autoload.

Then almost all scaffolding command works.

DisconnectedMetadataFactory PSR-4 patch

/**
 * 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();
}
phpPhil

If somebody comes across this issue.. I got it finally working. I'm not quite sure what exactly fixed it, so here are all the steps I did:

  1. As I was running Symfony 2.3, first I upgraded to 2.7
  2. I re-generated the bundle from scratch... I changed the location of the bundle to MyProject\CoreBundle and renamed the bundle class to MyProjectCoreBundle.

I can now run all of these commands successfully:

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       

(Note that the call of doctrine:generate:form was not in the OP.)

My best guess is that one step of the upgrade was to change the composer autoload - this, or the 2.7 autoloader, seems to have fixed it:

"autoload": {
    "psr-4": { "": "src/", "SymfonyStandard\\": "app/" }
},
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!