I am using doctrine 2 in my project, but I separate all my modules into different folders so the doctrine 2 entities are located in different directories depending on which module they belong to.
I am wondering if it is possible to change the Doctrine2 entity and proxy directory setting while using the existing connecting to the database. I have looked into the EntityManager class but can not see a function to update the configuration.
If there is no built in solution, does anyone know if this function would work in the EntityManager class:
public function updateConfiguration(Configuration $config)
{
$this->config = $config;
$metadataFactoryClassName = $config->getClassMetadataFactoryName();
$this->metadataFactory = new $metadataFactoryClassName;
$this->metadataFactory->setEntityManager($this);
$this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
$this->proxyFactory = new ProxyFactory($this,
$config->getProxyDir(),
$config->getProxyNamespace(),
$config->getAutoGenerateProxyClasses());
}
I's not clear what you exactly mean, but I will give it a try.
The databaseconnection is part of the EntityManager but they are not the same. Making changes to a databaseconnection is, as far as I know, not possible if the connection is already established.
You must be sure you have setup all configurations before you create an instance of the EntityManger. You can define your configuration as flexible as you want, but once the entitymanager is created you can't change it (correct me if I'm wrong). If you do so it can cause problems with other entities it already loaded and, for example, your flush calls could fail.
If you want to load entities from different location you can work with the Doctrine classloader. Assign all entities of a module to a namespace and load that namespace from any location on your filesystem.
Small code example
// Doctrine module
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', "/var/www/library/Doctrine/");
$classLoader->register();
// User modules
$classLoader = new \Doctrine\Common\ClassLoader('User', "/var/www/modules/models/User/");
$classLoader->register();
// Page module
$classLoader = new \Doctrine\Common\ClassLoader('Page', "/some/path/to/different/modules/models/Page/");
$classLoader->register();
I don't see the use of changing the settings of your EntityManager during a request. If you have to do that, you're trying to fix your problem at the wrong place. I've never even tried it and don't want to anyway :).
Maybe I didn't understand your question. If so, please let me know :).
One can retrieve $config from Entity manager like this:
$config = $em->getConfiguration();
To dynamically update entities paths try this (i've not tried it myself):
$driverImpl = new Doctrine\ORM\Mapping\Driver\AnnotationDriver(array(
APP_PATH . DIRECTORY_SEPARATOR . 'entities'
));
$config->setMetadataDriverImpl($driverImpl);
P.S> I think this should work but I've not tried this so plz correct me if this wrong.
Related
As i'm trying to install the Neo4jPHP library in codeigniter (v2.2.x), i'm having annoying issues regarding namespaces. I've been searching for 4 hours without success.
In short, there is a libraries directory in which Neo4jPHP must be copied. So in 'libraries/', there is a directory 'Everyman/Neo4j/', which contains all the Neo4j php classes.
Also, in the same 'libraries' directory, there is a class with an autoloader function, which aims at loading the Neo4j classes (which are in 'Everyman/Neo4j/').
Inside of 'libraries'
- libraries/
|-- Everyman/
|-- Neo4j/
|-- Client.php
|-- some_other_classes.php
|-- Neo4j.php
Then, somewhere in my code, in the global namespace, i try to instantiate the class client :
$client = new Client();
But i get the error Class 'Client' not found.
In the class client, the following namespace is specified : Everyman\Neo4j.
I'm must admit that i found 2 workarounds for this issue :
From the calling code, use the fully qualified name :
new Everyman\Neo4j\Client();
Or, in Client.php, remove the namespace.
In these 2 cases, it works. However, i would like to call the Client class with these 2 condition :
1. I don't want to modify anything from the Neo4jPhp library.
2. I really don't want to have to use the fully qualified name (Everyman\Neo4j\Client). I want to use "new Client()".
Do you guys have an idea how i could achieve this (yes, i don't have a very deep understanding of namespaces, and loaders).
In Neo4j.php (file with loader)
<?php
class Everyman{
public function __construct()
{
spl_autoload_register(array($this,'autoload'));
}
public function autoload($sClass){
$sLibPath = __DIR__.DIRECTORY_SEPARATOR;
//Below, i modified the instruction so that the class file
//can be found. However, the class is not found.
$sClassFile = 'Everyman'.DIRECTORY_SEPARATOR.'Neo4j'.str_replace('\\',DIRECTORY_SEPARATOR,$sClass).'.php';
$sClassPath = $sLibPath.$sClassFile;
if (file_exists($sClassPath)) {
require($sClassPath);
}
}
}
So that's it. I think i've given you all the information i have. If no one can help me, i'll have to use 'new Everyman\Ne4j\Client();' (which works).
It may seem stupid to ask for help, as i already have found 2 workarounds, but i really want to learn how to properly handle this issue (if possible).
Thanks.
It seems code like $client = new Everyman\Neo4j\Client('localhost', 7474); is the offical usage: https://github.com/jadell/neo4jphp#connection-test
So it is not work around.
I really don't want to have to use the fully qualified name (Everyman\Neo4j\Client). I want to use "new Client()".
I don't know what you really want. But then how about putting the code below in your code which you use Everyman\Neo4j\Client:
use Everyman\Neo4j\Client;
and
$client = new Client();
See http://php.net/manual/en/language.namespaces.importing.php
The supported way of installing neo4jphp is using Composer (https://getcomposer.org/). It is a good idea to learn how to use Composer, since a large number of PHP libraries can be installed using it. It also sets up the autoloading for you, so you don't have to worry about paths and namespaces yourself.
If you don't want to write new Everyman\Neo4j\Client() every time, you can put a use statement at the top of your script: use Everyman\Neo4j\Client; and then new Client();
Thank you for your answers.
For some reason, the 'use Everyman\Neo4j\Client' command didn't work, and i decided not to perform further inquiry into this issue.
So i decided to stick with the call to '$client = new Everyman\Neo4J\Client();', instead of trying to achieve '$client = new Client();'.
Thank you for your propositions.
Loïc.
I'm using the default Zend_Application design pattern which loads a zend config ini file automatically in the application bootstrap and I need to ini file's variables across many models and controllers.
Right now, I'm solving it by settings the config object as a key into Zend_Registry:
protected function _initConfig()
{
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
}
Generally, I don't like using Zend_Registry, as it doesn't offer code auto complete in my IDE, and it's hard to keep track on what I have in the registry namespace.
Is there another way to access the Zend_Application's config ini?
In a controller you should be able to do:
$this->getInvokeArg('bootstrap')->getOptions();
to access the config. For models you really should be passing in the options you need. Otherwise your only choice is really the registry.
You could always initialise it as needed yourself with
$options = new Zend_Config_Ini('/path/to/config.ini',
'config');
Wich is pretty much what the bootstrap does for you. Then you would have autocomplete on $options. But you would have to initialise it everytime you need it.
I think modifying your code to suit autocomplete is not the greatest idea ever. But this is personnal.
If I am not mistaken with Zend Studio 8/9 (maybe 7) you DO have autocomplete even for objects returned by Zend_Registry::get().
we`re currently developing our own Feedmanager for ShopProducts based on Zend Framework.
In this feedmanager you can manage several feeds, to be created and sent to different locations.
Each feed has n-fields which are in the current version only in one level.
Now we want to change it to a multilevel version, we we have parentfields and childfields.
We dont want to reinvent the wheel, so we would like to use a developed class or helper.
I found the class of F. Pietka.
https://github.com/fpietka/Zend-Nested-Set
I tried to use this helper in our system, but had no success.
I wrote the following line, to use the class:
$oNested = new NestedSet_Model();
I got the following error message:
Fatal error: Call to undefined method NestedSet_Model::getDbTable() in
D:\xampp\htdocs\feedmanager_alpha\application\classes\NestedSet.class.php
on line 75
In the readme of Peitka`s NestedSet helper it says that the ZendLibrary needs to be in the include path.
I think I did this with the following lines:
define("ROOTPATH", realpath("../"));
define("LIBPATH", ROOTPATH . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR);
// Ensure library/ is on include_path
set_include_path(
implode(PATH_SEPARATOR,
array(
realpath(LIBPATH)
)
)
);
Did I set the include path correctly?
What could be the problem in my case?
Is a nested-set the best way to create the parent-child-model?
I would strongly advise you not to use this class, because it's clearly a WIP. However, if you want to circumvent this error, you can just delete the __construct() method and call the setDb() and setTableName() by hand.
Example:
$model = new NestedSet_Model();
$model->setDb(Zend_Db_Table::getDefaultAdapter());
$model->setTableName('table_name');
class NestedSet extends Zend_Db_Table
{
protected $_name = 't_nested_set_mkb_10';
public function set(){
$model = new NestedSet_Model();
$model->setDb(Zend_Db_Table::getDefaultAdapter());
$model->setTableName('t_nested_set_mkb_10');
}
}
It was long overdue, but I updated https://github.com/fpietka/Zend-Nested-Set (even with unit tests).
Feel free to create issues!
I'm interested in using Doctrine as an ORM for a new Zend Framework app I'm writing. I'm trying to figure out the best way to integrate it as straightforward as possible. Every example I find is different, and a lot of them pre-date the new autoloading features in ZF 1.8. None of them have worked for me yet.
Does anyone have a good way to do this? I'm inclined to want to place it in my bootstrap file, but some people suggest making a Zend_Application_Resource plugin. The hard part seems to be getting the load paths working correctly for both the Doctrine namespace and the model classes which by default don't follow the Zend auto-loading convention.
Any thoughts? Thanks.
I wrote a Resource Bootstrapper for Doctrine and Zend Framework a few weeks ago and turned it all into a small wrapper framework, cause I think ZF and Doctrine are a great team.
You can read the article here:
http://coffeecoders.de/2009/06/using-the-zend-framework-18-bootstrapper-and-doctrine-110/
It is fully configurable via the Bootstrap resource configurations (example included, too). Unfortunately Doctrine searches for Models in the model folder with the same classname as the filename (which doesn't match the ZF naming scheme) so it was actually not possible to get rid of registering the Doctrine Autoloader.
The resource Loader looks like this:
<?php
/**
* Doctrine model loading bootstrap resource. Options must provide a connection string.
* directory option for model directory is optional (default is ./models).
* Further options will be set for the Doctrine manager via setAttribute (e.g. model_loading).
* #author daff
*/
class Cuckoo_Application_Resource_Model extends Zend_Application_Resource_ResourceAbstract
{
public function init()
{
$manager = Doctrine_Manager::getInstance();
$options = $this->getOptions();
foreach($options as $key => $value)
{
if($key != 'connection' && $key != 'directory')
$manager->setAttribute($key, $value);
}
if(empty($options['connection']))
throw new Exception("No database connection string provided!");
Doctrine_Manager::connection($options['connection']);
if(empty($options['directory']))
$dir = './models';
else
$dir = $options['directory'];
Doctrine::loadModels(realpath($dir));
return $manager;
}
}
http://weierophinney.net/matthew/archives/220-Autoloading-Doctrine-and-Doctrine-entities-from-Zend-Framework.html
take a look at this post. It gives a detailed explanation, directory structure and how to use autaloading features.
As far as auto-loading is concerned, you can actually use the Doctrine loader with the new Zend_Loader_Autoloader stack quite easily. Take a look at this page, especially where it mentions the pushAutoloader() method.
Here's the basic run down, though:
$autoloader = Zend_Loader_Autoloader->getInstance();
$autoloader->pushAutoloader(array('Doctrine', 'autoload'), 'Doctrine');
This will use Doctrine's own autoloader for only classes that begin with Doctrine, if they are not already found by other autoloaders in the stack.
Hope this helps a bit.
Is there a helper method/object/methodology for getting a reference to a Zend_Application's config resource?
I know I can do something like
$config = new Zend_Config_Ini($file, $environment);
but that's going to reload/parse the config file. I'm looking for a way to peek at the given configuration value for a running Zend_Application.
The larger issue I'm trying to solve is I want a Zend_Queue to use the same database settings as my default database resource. If there's a more "Zend Like" way of achieving this other than "get reference to config, read resource values" please feel free to share that as well!
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
public function run()
{
// make the config available to everyone
$config = $this->getOptions();
Zend_Registry::set('config', new Zend_Config($config));
parent::run();
}
}
Zend_Queue
there is code in Zend_Queue_Adapter_Db __construct if (isset($this->_options['dbAdapter'])) so u can do thomething like this
new Zend_Queue_Adapter_Db(array('dbAdapter' => Zend_Db_Table::getDefaultAdapter()));
because standart Zend_Application_Resource_Db can use config option resources.db.isDefaultTableAdapter = true
or u can put db adapter in registry and get it from there at any place
Zend_Controller_Front::getInstance()->getParam('bootstrap')->getOptions()