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

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

Related

Zend Framework autoloader in Doctrine 2 repositories

I use Zend Framework and Doctrine 2 in my project. Everything works fine except, that autoloader doesn't load Zend classes from Doctrine repositories.
Here is my bootstrap part for Zend autoloader:
/**
* Register namespace Default_
* #return Zend_Application_Module_Autoloader
*/
protected function _initAutoload() {
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Default_',
'basePath' => dirname(__FILE__),
));
return $autoloader;
}
Here is my bootstrap part for Doctrine initialization:
/**
* Initialize Doctrine
* #return Doctrine_Manager
*/
public function _initDoctrine() {
// include and register Doctrine's class loader
require_once('Doctrine/Common/ClassLoader.php');
$classLoader = new \Doctrine\Common\ClassLoader(
'Doctrine',
APPLICATION_PATH . '/../library/'
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Repositories',
APPLICATION_PATH . '/../library/Model'
);
$classLoader->register();
// create the Doctrine configuration
$config = new \Doctrine\ORM\Configuration();
// setting the cache ( to ArrayCache. Take a look at
// the Doctrine manual for different options ! )
$cache = new \Doctrine\Common\Cache\ApcCache;
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
// choosing the driver for our database schema
// we'll use annotations
$driver = $config->newDefaultAnnotationDriver(
APPLICATION_PATH . '/../library/Model'
);
$config->setMetadataDriverImpl($driver);
// set the proxy dir and set some options
$config->setProxyDir(APPLICATION_PATH . '/../library/Model/Proxies');
$config->setAutoGenerateProxyClasses(true);
$config->setProxyNamespace('Model\Proxies');
// now create the entity manager and use the connection
// settings we defined in our application.ini
$connectionSettings = $this->getOption('doctrine');
$conn = array(
'driver' => $connectionSettings['conn']['driv'],
'user' => $connectionSettings['conn']['user'],
'password' => $connectionSettings['conn']['pass'],
'dbname' => $connectionSettings['conn']['dbname'],
'host' => $connectionSettings['conn']['host']
);
$entityManager = \Doctrine\ORM\EntityManager::create($conn, $config);
// push the entity manager into our registry for later use
$registry = Zend_Registry::getInstance();
$registry->entitymanager = $entityManager;
return $entityManager;
}
How could i fix this?
Your _initAutoload is completely unnecessary.
Just add
autoloadernamespaces[] = Default
autoloadernamespaces[] = Doctrine
to your application.ini
I agree that _initAutoload() shouldn't be necessary, but i suspect you'll need this in application.ini:
autoloaderNamespaces[] = "Doctrine"
autoloaderNamespaces[] = "Model"
If you just starting you project I will advice to use zf2 (beta5 last beta folowing: http://framework.zend.com/zf2/blog/entry/Zend-Framework-2-0-0beta5-Released)
This is tutorial which I was using for my project zf2 + doctrine 2 http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/

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

Unable to load \Doctrine\ORM\Configuration() class with Doctrine 2 classloader in cli-config.php file when using the doctrine CLI

I followed the steps in the following article in order to integrate Zend Framework 1.11 and Doctrine 2:
http://jeboy25.blogspot.com/2010/08/doctrine-2-and-zend-framework-110.html
And I have 3 questions about the article:
1-In the "SchemaToolClass" section i don't understand why the author includes schema_tool.php at the bottom of ZendProject/public/index.php file after :
$application->bootstrap()
->run();
2-when i execute the command "php doctrine orm:schema-tool:create" i have the following error message in the command line:
HP Stack trace:
PHP 1. {main}() /Library/WebServer/Documents/carlending/application/tools/doctrine:0
PHP 2. include() /Library/WebServer/Documents/carlending/application/tools/doctrine:7
PHP 3. require() /Library/WebServer/Documents/carlending/application/tools/doctrine.php:41
PHP 4. Doctrine\Common\ClassLoader->loadClass($className = uninitialized)
the error occurs in the cli-config.php file at the line '$config = new \Doctrine\ORM\Configuration();'
3-Can you explain why the author puts the doctrine generated proxies and models inside the domain folder. Isn't it better that they reside in the models folder like any other model class.
Sometimes i also see some programmers using a 'generated' folder inside models.
If you managed to make a working integration of Zend 1.x and Doctrine i would be very happy if you could also send me a working project that would very helpful.
Thanks for your help.
After reading "Obtaining the EntityManager" section in http://www.doctrine-project.org/docs/orm/2.1/en/tutorials/getting-started-xml-edition.html
I think you need the following three lines to bootstrap:
use Doctrine\ORM\Tools\Setup;
require_once 'Doctrine/ORM/Tools/Setup.php';
Setup::registerAutoloadPEAR();
I've got it to work a few weeks ago, here's my code. Doctrine 2 is really nice :)
In my bootstrap
/**
* Initialize auto loader of Doctrine
*
* #return Doctrine_Manager
*/
protected function _initDoctrine() {
$this->bootstrap('autoload');
require_once('Doctrine/Common/ClassLoader.php');
// Create the doctrine autoloader and remove it from the spl autoload stack (it adds itself)
require_once 'Doctrine/Common/ClassLoader.php';
$doctrineAutoloader = array(new \Doctrine\Common\ClassLoader(), 'loadClass');
//$doctrineAutoloader->register();
spl_autoload_unregister($doctrineAutoloader);
$autoloader = Zend_Loader_Autoloader::getInstance();
// Push the doctrine autoloader to load for the Doctrine\ namespace
$autoloader->pushAutoloader($doctrineAutoloader, 'Doctrine');
$classLoader = new \Doctrine\Common\ClassLoader('Entities', realpath(__DIR__ . '/models/'), 'loadClass');
$autoloader->pushAutoloader(array($classLoader, 'loadClass'), 'Entities');
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', realpath(__DIR__ . '/../library/Doctrine/'), 'loadClass');
$autoloader->pushAutoloader(array($classLoader, 'loadClass'), 'Symfony');
$doctrineConfig = $this->getOption('doctrine');
$config = new \Doctrine\ORM\Configuration();
$cache = new \Doctrine\Common\Cache\ArrayCache;
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
$driverImpl = new Doctrine\ORM\Mapping\Driver\YamlDriver(APPLICATION_PATH . '/../configs/mappings/yaml');
//$driverImpl = $config->newDefaultAnnotationDriver($doctrineConfig['path']['entities']);
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir(APPLICATION_PATH . '/../proxies');
$config->setProxyNamespace('App\Proxies');
$connectionOptions = array(
'driver' => $doctrineConfig['conn']['driv'],
'user' => $doctrineConfig['conn']['user'],
'password' => $doctrineConfig['conn']['pass'],
'dbname' => $doctrineConfig['conn']['dbname'],
'host' => $doctrineConfig['conn']['host']
);
$registry = Zend_Registry::getInstance();
$registry->entitymanager = $em;
return $em;
}
Schema etc
I use yaml as you seen above, I haven't looked through the tutorial but I've used the command line tool that works like a charm, my doctrine.php (located in APPLICATION/bin):
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/..'));
// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'development'));
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path()
)));
/** Zend_Application */
require_once 'Zend/Application.php';
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/../configs/application.ini'
);
$application->getBootstrap()->bootstrap('doctrine');
require_once __DIR__ . '/../Bootstrap.php';
$em = $application->getBootstrap()->getResource('doctrine');
$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em, APPLICATION_PATH . "/configs/mappings")
));
\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);
You first have to generate your entities:
Generate all the models without deleting, creates also annotations -
./doctrine orm:generate-entities ~/Public/my_app/application/models/ --regenerate-entities 0 --generate-annotations 1
then generate your schema
./doctrine orm:schema-tool:create --dump-sql
or
./doctrine orm:schema-tool:update --dump-sql
the proxies are not really a part of your models, it's just used by Doctrine internally so I've put it as a separate entity from the models folder but I guess it doesn't really matter:
./doctrine orm:generate-proxies ~/Public/my_app/proxies/
Remember to add write permissions to the proxies for apache group.
Hmm... guess I didn't quite explain Jeboy's solution but perhaps my code helps you get started, it took me a while but once it's up and running it works like a charm :)
PS Don't forget the "namespace Entities;" in each of your models (it should be generated automatically)

generate annotated doctrine2 entites from db schema

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

loading doctrine models in zend framework scripts

i use zend framework 1.10 and i have a script under scripts library.
i run this script from command line.
how can i load all the models of doctrine and use them in my script.
in the begining of the script i write
/**
* Doctrine CLI script
*/
define('APPLICATION_ENV', 'production');
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
realpath(APPLICATION_PATH . '/../library/lib'),
realpath(APPLICATION_PATH . '/models/generated'),
realpath(APPLICATION_PATH .'/models'),
get_include_path()
)));
require_once 'Zend/Application.php';
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
then i connect to doctrine
require_once 'Doctrine.php';
$doctrineConfig = $application->getOption('doctrine');
$manager = Doctrine_Manager::getInstance();
$manager->openConnection($doctrineConfig['connection_string']);
then when i try to run a query like :
$q = Doctrine_Query::create()
->select('c.CampaignId')
->from('ModelCampaigns c');
he write an error :
Fatal error: Uncaught exception
'Doctrine_Exception' with message
'Couldn't find class ModelCampaigns'
its ok now i add this to script :
require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
$loader->setFallbackAutoloader(true);
$moduleLoader = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH));