Skip to content

Instantly share code, notes, and snippets.

@dwgebler
Created April 5, 2018 22:17
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dwgebler/4be59b84a5a4dd5bd6b90ad0efb22a35 to your computer and use it in GitHub Desktop.
Save dwgebler/4be59b84a5a4dd5bd6b90ad0efb22a35 to your computer and use it in GitHub Desktop.
Generate Symfony 4 entities + repositories from existing database
<?php
include './vendor/autoload.php';
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();
class RepoGen extends Doctrine\ORM\Tools\EntityRepositoryGenerator {
protected static $_template =
'<?php
namespace App\Repository;
use App\Entity\__ENTITY__;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
/**
* @method __ENTITY__|null find($id, $lockMode = null, $lockVersion = null)
* @method __ENTITY__|null findOneBy(array $criteria, array $orderBy = null)
* @method __ENTITY__[] findAll()
* @method __ENTITY__[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class __ENTITY__Repository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, __ENTITY__::class);
}
/*
public function findBySomething($value)
{
return $this->createQueryBuilder(\'g\')
->where(\'g.something = :value\')->setParameter(\'value\', $value)
->orderBy(\'g.id\', \'ASC\')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
}
';
protected $entity = '__Entity';
public function generateEntityRepositoryClass($fullClassName) {
$val = str_replace('__ENTITY__', $this->entity, self::$_template);
return $val;
}
public function setEntityName($name) {
$this->entity = $name;
}
}
// config
$config = new \Doctrine\ORM\Configuration();
$config->setMetadataDriverImpl($config->newDefaultAnnotationDriver(__DIR__ . '/Entities'));
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$connectionParams = array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'port' => '3306',
'user' => 'root',
'password' => 'root',
'dbname' => 'dbname',
'charset' => 'utf8',
);
$em = \Doctrine\ORM\EntityManager::create($connectionParams, $config);
// custom datatypes (not mapped for reverse engineering)
$em->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('set', 'string');
$em->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
// fetch metadata
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$em->getConnection()->getSchemaManager()
);
$driver->setNamespace('App\Entity\\');
$em->getConfiguration()->setMetadataDriverImpl($driver);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory($em);
$cmf->setEntityManager($em);
$classes = $driver->getAllClassNames();
$metadata = $cmf->getAllMetadata();
foreach ($metadata as $md) {
$md->setCustomRepositoryClass(str_replace('App\Entity\\', 'App\Repository\\', $md->getName().'Repository'));
}
$generator = new Doctrine\ORM\Tools\EntityGenerator();
$generator->setUpdateEntityIfExists(true);
$generator->setGenerateStubMethods(true);
$generator->setGenerateAnnotations(true);
$generator->generate($metadata, __DIR__ . '/Entities');
$repGenerator = new RepoGen();
foreach ($classes as $className) {
$className = str_replace('App\Entity\\', '', $className);
$repGenerator->setEntityName($className);
$repGenerator->writeEntityRepositoryClass($className.'Repository',__DIR__ . '/Repositories');
}
print 'Done!';
@dwgebler
Copy link
Author

dwgebler commented Apr 5, 2018

Full credit to https://gist.github.com/tawfekov/4079388 @tawfekov
this is just a modification of their gist to include repos for Symfony 4 projects

@MaximeC64
Copy link

Hello dwgebler,
I search a system to import a existing database for a while so thanks for your job.
But i'm a beginner and i don't know where i have to put this .php file ?
Somebody can help me please ?

Thanks.
Sorry for my english, i'm french.

@dwgebler
Copy link
Author

Hi @MaximeC64 just put the file in the root of your Symfony 4 project where .env, composer.json etc. sit and run from the command line.

@dwgebler
Copy link
Author

Please bear in mind this is just a helper as a starting point when you're by necessity working with an existing database; generating entities from an existing database is not actually a very good idea, since you are importing design flaws from the start rather than starting by building your entities correctly from the ground up. The generated entities will get about 90% of your basic field types and mappings correct, but you'll need to work on them manually to get the right Doctrine ORM structure for your project.

@Neurozone
Copy link

Please bear in mind this is just a helper as a starting point when you're by necessity working with an existing database; generating entities from an existing database is not actually a very good idea, since you are importing design flaws from the start rather than starting by building your entities correctly from the ground up. The generated entities will get about 90% of your basic field types and mappings correct, but you'll need to work on them manually to get the right Doctrine ORM structure for your project.

I just found your work (very good) and as a former dba, I can assure you that the design flow you're feared of came only from developpement team.
I've designed many databases in the past and every flaws came from dev too fierce to ask help from dbas ^^

But thank you for the code ;)

@Yassinebmns
Copy link

Thank you so much , this script saved me a ton of effort

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment