I'm trying to set up Doctrine 2 to play with ZF 1.11 for a while. I have managed to resolve all errors except one:
PHP Fatal error: Class 'Doctrine\ORM\Configuration' not found in C:\development\porjects\application\Bootstrap.php on line 258
Below is the _iniDoctrine() function in the Bootstrap.php file up to the line 258 referred to by the error message:
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');
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();
Apparently, the application fails to 'see' the Configuration class (and file). If I manually require the class before the class is instantiated. Another Class/file appears 'unseen'. A 'manual' fix definitely would not do.
The Doctrine folder which contains these files is on my include path. I have scoured the web for ideas. What please would you suggest? Thanks
I achieve to make ZF 1.x & Doctrine 2 working great together using this application resource it is available on github and well documented.
Hope that helps
If you are looking to integrate Doctrine 2 + Zend Framework you might want to use the 'glue' provided by one of the Doctrine developers (Guilherme Blanco)
https://github.com/guilhermeblanco/ZendFramework1-Doctrine2
If you haven't seen the presentation by Ralph Schindler and Guilherme Blanco, there is one on Slideshare.
http://www.slideshare.net/ralphschindler/zend-framework-1-doctrine-2-6177485
Also, Ralph has a nice example application on Github.
https://github.com/ralphschindler/NOLASnowball/tree/doctrine2-managed-crud#
There's also a great screencast at ZendCasts on how to implement Guilerme's adapter. Look for Unit Testing Doctrine 2 Entities.
Related
I'm just getting started with Zend Framework. I decided to try it for my website translations.
I set the include path as follow:
set_include_path('.:/usr/share/php:/usr/share/php/Zend/library');
And then straight from the docs this doesn't work:
use Zend\I18n\Translator\Translator;
$translator = new Translator();
Of course, I haven't loaded the Zend\I18n\Translator\Translator class anywhere, so I get:
Fatal error: Class 'Zend\I18n\Translator\Translator' not found in /path/file.php on line X
I see there are several things in the Zend/Loader directory, but I can't figure out how to use them and I don't even know if this is what I should be looking at. How do I load the Zend\I18n\Translator\Translator class?
Using the auto loader, you can do:
require_once 'Zend/Loader/StandardAutoloader.php';
$loader = new Zend\Loader\StandardAutoloader(array(
'fallback_autoloader' => true,
));
$loader->register();
use Zend\I18n\Translator\Translator;
I want to try Yii, but I don't want use it as my main framework. In other words, I want to use my own framework while also using some of Yii's features. I figured that in order to be able to instantiate Yii's classes from my application, I'd just need to register Yii's autoloader from my application, probably in a way similar to this:
spl_autoload_register
(
function ($classname)
{
YiiBase::autoload($className);
}
);
Of course, I'm gonna need to require or include the YiiBase class, so before I call the previous function, I do this:
$yiiBase = $_SERVER['DOCUMENT_ROOT'].'/yii/framework/YiiBase.php';
require_once($yiiBase);
But I get a "Cannot redeclare class YiiBase" error. What am I missing?
1) Do not include YiiBase.php direcly, include yii.php. Because yii.php contains a class Yii which is used in all over framework code (even in YiiBase methods).
$yii = $_SERVER['DOCUMENT_ROOT'].'/yii/framework/yii.php';
require_once($yii);
( and YiiBase.php is included in yii.php by default)
2) register your autoload handler in this way.
(Yii has built-in functionality to add custom autoload handlers ).
$my_autoload = function($class) { ... };
// OR
// $my_autoload = array('MyClass', 'my_autoload')
YiiBase::registerAutoloader($my_autoload, true);
The second parameter true tells whether to append/prepend the new autoloader after/before the default Yii autoloader
if the YiiBase.php included, then Yii's default autoloader will also gets included. No need to call YiiBase::autoload() explicitly in you code. Ref: check the last line in YiiBase.php file
You can take a look at some approaches of people integrating Yii with wordpress, you may not need to do ->run() the application, unless you need the controllers/routing, it also depends on what parts of the framework you pretend to use.
To do it for Yii2, this article explains it under the heading "Using Yii in Third-Party Systems" in the middle of the page.
Here is the relevant part to include on startup of your external application:
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$yiiConfig = require(__DIR__ . '/../config/yii/web.php');
new yii\web\Application($yiiConfig); // Do NOT call run() here
Obviously, __DIR__ . '/../ may need to be adjusted to fit your directory layout.
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 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.
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.