generate annotated doctrine2 entites from db schema - annotations

Is it possible to generate Doctrine 2 entities, with the relevant docblock annotations, from an existing database schema?

I had to made these changes for the above code to work..
<?php
use Doctrine\ORM\Tools\EntityGenerator;
ini_set("display_errors", "On");
$libPath = __DIR__; // Set this to where you have doctrine2 installed
// autoloaders
require_once $libPath . '/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', $libPath);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();
// 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(
'path' => 'test.sqlite3',
'driver' => 'pdo_sqlite',
);
$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()
);
$em->getConfiguration()->setMetadataDriverImpl($driver);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory($em);
$cmf->setEntityManager($em);
$classes = $driver->getAllClassNames();
$metadata = $cmf->getAllMetadata();
$generator = new EntityGenerator();
$generator->setUpdateEntityIfExists(true);
$generator->setGenerateStubMethods(true);
$generator->setGenerateAnnotations(true);
$generator->generate($metadata, __DIR__ . '/Entities');
print 'Done!';
?>
and mysql connection configuration like :
$connectionParams = array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'port' => '3306',
'user' => 'root',
'password' => 'root',
'dbname' => 'database',
'charset' => 'utf8',
);

Yes it possible though RDBMS data types are not fully supported, so you might have to play with your code a bit before using it in your project. It's not straight forward as Doctrine 1.x used to be but still rather easy. Here some sample code I used myself (create folders properly before using it)
use Doctrine\ORM\Tools\EntityGenerator;
ini_set("display_errors", "On");
$libPath = __DIR__ . '/../lib/doctrine2';
// autoloaders
require_once $libPath . '/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', $libPath);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();
// 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(
'dbname' => 'xx',
'user' => 'root',
'password' => '',
'host' => 'localhost',
'driver' => 'pdo_mysql',
);
$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()
);
$classes = $driver->getAllClassNames();
foreach ($classes as $class) {
//any unsupported table/schema could be handled here to exclude some classes
if (true) {
$metadata[] = $cmf->getMetadataFor($class);
}
}
$em->getConfiguration()->setMetadataDriverImpl($driver);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory($em);
$generator = new EntityGenerator();
$generator->setUpdateEntityIfExists(true);
$generator->setGenerateStubMethods(true);
$generator->setGenerateAnnotations(true);
$generator->generate($metadata, __DIR__ . '/Entities');
print 'Done!';

I have implemented new command to achieve that https://github.com/umpirsky/doctrine2/blob/master/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesDbCommand.php
Just add it like this:
$cli->addCommands(array(
// DBAL Commands
new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(),
new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(),
// ORM Commands
new \Doctrine\ORM\Tools\Console\Command\ClearCache\MetadataCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\ResultCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryCommand(),
new \Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand(),
new \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand(),
new \Doctrine\ORM\Tools\Console\Command\SchemaTool\DropCommand(),
new \Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand(),
new \Doctrine\ORM\Tools\Console\Command\ConvertDoctrine1SchemaCommand(),
new \Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand(),
new \Doctrine\ORM\Tools\Console\Command\GenerateEntitiesCommand(),
new \Doctrine\ORM\Tools\Console\Command\GenerateEntitiesDbCommand(),
new \Doctrine\ORM\Tools\Console\Command\GenerateProxiesCommand(),
new \Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand(),
new \Doctrine\ORM\Tools\Console\Command\RunDqlCommand(),
new \Doctrine\ORM\Tools\Console\Command\ValidateSchemaCommand(),
));
$cli->run();

As of https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php , generating entities is already supported by Doctrine's default CLI

Related

Use Doctrine with REST APIs

Is it possible to use a REST API as Doctrine database?
Regarding the configuration on http://doctrine-orm.readthedocs.org/projects/doctrine-dbal/en/latest/reference/configuration.html I can change the "driver" property.
But in the list of allowed drivers there is no one to use a REST API.
What I would like to do is:
<?php
$config = new \Doctrine\DBAL\Configuration();
//..
$connectionParams = array(
'dbname' => 'my_rest_api',
'user' => 'user',
'password' => 'secret',
'host' => 'localhost:3000',
'driver' => 'rest',
);
$conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);
$entityManager = EntityManager::create($conn, $config);
// Sends a GET request to localhost:3000/myentity/1 and maps it properly to my configured entity
$entity = $entityManager->find("MyNamespace\Entity\MyEntity", 1);
// Sends a POST request to localhost:3000/myentity
$entity = new MyEntity();
$entityManager->persist($entity);
$entityManager->flush();
// and so on
Thank you for your answers!!
DoctrineRestDriver is exactly doing what you are looking for!
https://github.com/CircleOfNice/DoctrineRestDriver
Have fun!

"em is not defined error" when trying to run doctrine command

I've just setup a ZF2 project and configured it all for Doctrine2 without issue. It works and simply gives me an error now as it cannot find the database table I am trying to query.
Entity is also setup correctly, all as per http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/
So wanted to use the CLI to create the tables etc but when running any CLI command I get
[InvalidArgumentException]
The helper "em" is not defined.
Command I am using
php doctrine.php orm:schema-tool:update --dump-sql
Am running the doctrine.php from folder
/Library/WebServer/Documents/zf2-Skel-NewProj1/vendor/bin
Now if I use the CLI for one of my ZF1.11 projects it works fine.
To get this working do I have to edit the cli-config.php file located under
/Library/WebServer/Documents/zf2-Skel-NewProj1/vendor/doctrine/orm/tools
Contents of this file is:
<?php
require_once '../../lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\ORM', realpath(__DIR__ . '/../../lib'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\DBAL', realpath(__DIR__ . '/../../lib/vendor/doctrine-dbal/lib'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\Common', realpath(__DIR__ . '/../../lib/vendor/doctrine-common/lib'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', realpath(__DIR__ . '/../../lib/vendor'));
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();
$config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities"));
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$connectionOptions = array(
'driver' => 'pdo_sqlite',
'path' => 'database.sqlite'
);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
$helpers = new Symfony\Component\Console\Helper\HelperSet(array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));
try:
vendor\bin\doctrine-module orm:schema-tool:update --dump-sql

what is the benifit of using Zend_Config class?

i am new to zend framework i wana know why we are using this code for connection to database although we can use the below code also which is simple and not including class what is the advantages of including Zend_config( )
require_once 'Zend/Config.php';
$arrConfig = array(
'webhost'=>'localhost',
'appName'=>'My First Zend',
'database'=>array(
'dbhost'=>'localhost',
'dbname'=>'zend',
'dbuser'=>'root',
'dbpass'=>'admin'
)
);
$config = new Zend_Config($arrConfig);
$params = array('host' =>$config->database->dbhost,
'username' =>$config->database->dbuser,
'password' =>$config->database->dbpass,
'dbname' =>$config->database->dbname
);
$DB = new Zend_Db_Adapter_Pdo_Mysql($params);
$DB->setFetchMode(Zend_Db::FETCH_OBJ);
if i can do like this
include_once 'Zend/Db/Adapter/Pdo/Mysql.php';
$params = array('host' => 'localhost',
'username' => 'root',
'password' => '',
'dbname' => 'zend'
);
$DB = new Zend_Db_Adapter_Pdo_Mysql($params);
$DB->setFetchMode(Zend_Db::FETCH_OBJ);
in the way you're using Zend_Config it's in fact doesn't help you a lot to have the settings in a config object.
Usually, in ZF applications, there's a separate application.ini file which contains all the settings:
$config = new Zend_Config_Ini('/path/to/config.ini',
'production');
Then it's convenient to separate environments (production & development for example) into different sections:
; Production site configuration data
[production]
database.adapter = pdo_mysql
database.params.host = db.example.com
database.params.username = dbuser
database.params.password = secret
database.params.dbname = dbname
; Development site configuration data inherits from production and
; overrides values as necessary
[development : production]
database.params.host = dev.example.com
database.params.username = devuser
database.params.password = devsecret
meaning loading the config with:
$config = new Zend_Config_Ini('/path/to/config.ini',
'development');
wil return the development config.
http://framework.zend.com/manual/en/zend.config.adapters.ini.html

How to define the use of utf-8 in Doctrine 2 in Zend Framework application.ini, when using Bisna

The following ZendCasts cast, shows a way to use doctrine 2 in a zend framework environment.
Using this configuration, how can I make the connection use a utf-8 charset so the magic of "SET NAMES 'utf8'" will happen ?
What I'm really searching for is a way to configure it using the application.ini file.
If that's not possible using this configuration, how can this be done by code ? an _initDoctrine method in the Bootstratp file ?
Thank you.
UPDATE
It appears there's a post connect event which handles this, but I don't see how can I set it up via application.ini (if possible at all).
If not, can I set it up via a bootstrap method ? Will the bootstrap method run before any other doctrine connection code run, when relying on the Bisna library ?
If you are not using Bisna, you could simply do something like the following:
Pass the config stuff directly to EntityManager's connection options
(although driverOptions is not documented)
// $options is a simple array to hold your data
$connectionOptions = array(
'driver' => $options['conn']['driv'],
'user' => $options['conn']['user'],
'password' => $options['conn']['pass'],
'dbname' => $options['conn']['dbname'],
'host' => $options['conn']['host'],
'charset' => 'utf8',
'driverOptions' => array(
1002 => 'SET NAMES utf8'
)
);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
I'm using the following custom bootstrap resource to initialize doctrine therefore $options is in application.ini and is accessible there by $this->getOptions();
// \library\My\Application\Resource\Doctrine.php
class My_Application_Resource_Doctrine extends Zend_Application_Resource_ResourceAbstract
{
public function init()
{
$options = $this->getOptions();
$config = new \Doctrine\ORM\Configuration();
//doctrine autoloader, config and other initializations
...
$connectionOptions = array(
.... //see above
);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
$registry = Zend_Registry::getInstance();
$registry->em = $em;
return $em;
}
}
It will bootstrap automatically if you put in application.ini
resources.doctrine.conn.host = '127.0.0.1'
resources.doctrine.conn.user = '...'
resources.doctrine.conn.pass = '...'
....
works fine for me
resources.doctrine.dbal.connections.default.parameters.driverOptions.1002 = "SET NAMES 'UTF8'"
1002 is the integer value of PDO::MYSQL_ATTR_INIT_COMMAND:
Command to execute when connecting to the MySQL server. Will
automatically be re-executed when reconnecting.
Note, this constant can only be used in the driver_options array when constructing a new
database handle.
this worked for me. config/autoload/doctrine.local.php
<?php
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '3306',
'user' => '...',
'password' => '...',
'dbname' => '...',
'driverOptions' => array(
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
)
),
)
)
)
);
It is possible to add it via application.ini, provided you use ZendX_Doctrine2 (at https://github.com/mridgway/ZendX_Doctrine2) with MySQL.
Then here's the line you need in application.ini:
resources.entitymanagerfactory.connectionOptions.driverOptions.1002 = "SET NAMES utf8"
(1002 == PDO::MYSQL_ATTR_INIT_COMMAND)
Don't forget to correctly set
default-character-set=utf8
in your my.cnf
Since this is for Doctrine 2, and ZendCasts is using Bisna, I believe you can just add this to your configuration.ini file
resources.doctrine.dbal.connections.default.parameters.driverOptions.charset = "utf8"
I'm not exactly sure how to test if it is sticking or not but let us know.
You could set the default table charset like that to utf8:
// Create new Doctrine Manager instance
$doctrineManager = Doctrine_Manager::getInstance();
// Set charset to UTF8
$doctrineManager->setAttribute(
Doctrine_Core::ATTR_DEFAULT_TABLE_CHARSET,
'utf8'
);
Quote:
an _initDoctrine method in the Bootstratp file ?
Yes.
For LoSo library and Doctrine 2 and MySQL add
resources.doctrine2.connection.driverOptions.1002 = "SET NAMES 'UTF8'"
to your application.ini
I have this in my bootstrap:
protected function _initDoctrineLibrary()
{
require_once('Doctrine/Doctrine.php');
$this->getApplication()->getAutoloader()->pushAutoloader(array('Doctrine', 'autoload'),'Doctrine');
$manager = Doctrine_Manager::getInstance();
$manager->setAttribute(
Doctrine::ATTR_MODEL_LOADING,
Doctrine::MODEL_LOADING_CONSERVATIVE
);
$config = $this->getOption('doctrine');
$conn = Doctrine_Manager::connection($config['dsn'],'doctrine');
$conn->setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM, true);
return $conn;
}
where in the application.ini you see
doctrine.dsn = "mysql://user:password#host/databasename"
I think you can do something similar

zend translate join multiple file languages

i am trying to add to my language file, the zend form errors language file, which can be found in
ZendFramework-1.11.2.zip\ZendFramework-1.11.2\resources\languages
in order to have localized form validators erorrs. This blog http://www.thomasweidner.com/flatpress/2010/03/25/working-with-multiple-translation-sources/comments/ explains what i try to do, but it fails :( it only translates from my .ini file, the .php is not included
Here is what i did:
this is my application.ini
resources.translate.adapter = "ini"
resources.translate.default.locale = "it_IT"
resources.translate.default.locale = "en_US"
resources.translate.default.file = APPLICATION_PATH "/lang/source-it.ini"
resources.translate.translation.en = APPLICATION_PATH "/lang/source-en.ini"
;resources.translate.data.directory = APPLICATION_PATH "/lang"
resources.translate.data = APPLICATION_PATH "/lang"
and then i have this
<?php
class Gestionale_Application_Resource_Translate extends Zend_Application_Resource_ResourceAbstract
{
public function init ()
{
$options = $this->getOptions();
$adapter = $options['adapter'];
$defaultTranslation = $options['default']['file'];
$defaultLocale = $options['default']['locale'];
$translate = new Zend_Translate($adapter, $defaultTranslation, $defaultLocale);
$translation_addme = new Zend_Translate(
'array',
APPLICATION_PATH."/resources/languages/it/Zend_Validate.php"
'it',
array('scan' => Zend_Translate::LOCALE_DIRECTORY)
);
$translate->addTranslation($translation_addme);
foreach ($options['translation'] as $locale => $translation) {
$translate->addTranslation($translation, $locale);
}
Zend_Registry::set('Zend_Translate', $translate);
return $translate;
}
}
and this is my dir
c:\www\www\gestionale\application>dir /w /aD
Il volume nell'unità C è OS
Numero di serie del volume: 6A5E-FD9B
Directory di c:\www\www\gestionale\application
[.] [..] [.svn] [configs] [controllers]
[forms] [lang] [layouts] [models] [resources]
[views]
0 File 0 byte
11 Directory 447.780.282.368 byte disponibili
Just by looking at your code I cannot tell you much. I suspect that your problems might be because you create your own resource plugin, which is unnessesry for this purpose, somethings are not being bootstrap properly, or there are some conflicts with your application.ini. Any way, I will post my translation setup and maybe it will give you some clues.
application.ini
Nothing here about translation or locale since I setup them in Bootstrap.php.
Bootstrap.php
protected function _initLocale() {
// define locale
$locale = new Zend_Locale('en');
// register it so that it can be used all over the website
Zend_Registry::set('Zend_Locale', $locale);
}
protected function _initTranslate() {
// Get Locale
$locale = Zend_Registry::get('Zend_Locale');
// Set up and load the translations (there are my custom translations for my app)
$translate = new Zend_Translate(
array(
'adapter' => 'array',
'content' => APPLICATION_PATH . '/languages/' . $locale . '.php',
'locale' => $locale)
);
// Set up ZF's translations for validation messages.
$translate_msg = new Zend_Translate(
array(
'adapter' => 'array',
'content' => APPLICATION_PATH .
'/resources/languages/' . $locale . '/Zend_Validate.php',
'locale' => $locale)
);
// Add translation of validation messages
$translate->addTranslation($translate_msg);
Zend_Form::setDefaultTranslator($translate);
// Save it for later
Zend_Registry::set('Zend_Translate', $translate);
}