Im' currently trying to integrate MongoDB with Doctrine in ZendFramework. I did a lot of tutorial (on StackOverflow or anywhere else) but nothing is really working.
I followed step by step a tutorial: http://www.bigwisu.com/2012/10/03/zend-framework-2-doctrine-odm and I got an error that I don't understand.
Fatal error: Class 'MongoId' not found in /home/prooxi/www/zframework/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Types/IdType.php on line 38
The IdType.php is source code for the mongoDB, so the error must be somewhere else.
Here is the files I have. (Admin is the name of the module)
config/application.config.php
<?php
return array(
'modules' => array(
'Application',
'DoctrineModule',
'DoctrineMongoODMModule',
'Udmin',
'Listing',
'Admin',
),
'module_listener_options' => array(
'module_paths' => array(
'./module',
'./vendor',
),
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php',
),
),
);
config/autoload/module.doctrine-mongo-odm.local.php
<?php
return array(
'doctrine' => array(
'connection' => array(
'odm_default' => array(
'server' => 'MYDBADRESS',
'port' => '27017',
/* 'connectionString' => null, */
/* 'user' => null, */
/* 'password' => null, */
'dbname' => 'px_boutique_test27',
'options' => array()
),
),
'configuration' => array(
'odm_default' => array(
'metadata_cache' => 'array',
'driver' => 'odm_default',
'generate_proxies' => true,
'proxy_dir' => 'data/DoctrineMongoODMModule/Proxy',
/* 'proxy_dir' => __DIR__ . '/module/Admin/src/Admin/Model/Proxy', */
/* 'proxy_dir' => __DIR__ . '/module/Udmin/src/Udmin/Model/Proxy', */
'proxy_namespace' => 'DoctrineMongoODMModule\Proxy',
/* 'proxy_namespace' => 'Udmin\Model\Proxy', */
'generate_hydrators' => true,
'hydrator_dir' => 'data/DoctrineMongoODMModule/Hydrator',
/* 'hydrator_dir' => __DIR__ . '/module/Udmin/src/Udmin/Model/Hydrator', */
'hydrator_namespace' => 'DoctrineMongoODMModule\Hydrator',
/* 'hydrator_namespace' => 'Udmin\Model\Hydrator', */
'default_db' => 'test27',
'filters' => array(), // array('filterName' => 'BSON\Filter\Class'),
/* 'logger' => null // 'DoctrineMongoODMModule\Logging\DebugStack' */
)
),
'driver' => array(
'odm_default' => array(
'drivers' => array(
'Admin\Document' => 'aplikasi'
)
),
'aplikasi' => array(
'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
'module/Admin/src/Admin/Document'
)
)
),
'documentmanager' => array(
'odm_default' => array(
'connection' => 'odm_default',
'configuration' => 'odm_default',
'eventmanager' => 'odm_default'
)
),
'eventmanager' => array(
'odm_default' => array(
'subscribers' => array()
)
),
),
);
Module/Admin/Src/Admin/Controller/AdminController.php
<?php
namespace Admin\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Mongo;
use Zend\Session\SaveHandler\MongoDB;
use Zend\Session\SaveHandler\MongoDBOptions;
use Zend\Session\SessionManager;
use Admin\Document\Boutique;
class AdminController extends AbstractActionController
{
public function indexAction()
{
$dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
$b = new Boutique();
/* $dm->getRepository('Admin\Document\Boutique')->findAll(); */
$dm->find('Admin\Document\Boutique', '52e6c677362dca7fcd40ab09');
}
}
Module/Admin/config/module.config.php
<?php
return array(
'controllers' => array(
'invokables' => array(
'Admin\Controller\Admin' => 'Admin\Controller\AdminController',
),
),
'router' => array(
'routes' => array(
'admin' => array(
'type' => 'segment',
'options' => array(
'route' => '/admin[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Admin\Controller\Admin',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'admin' => __DIR__ . '/../view',
),
),
);
The purpose of the module is to connect to an existing MongoDB databate and just make a list of all the document in it.
Thank you !
Gilles
If you are using the newer mongodb extension rather than mongo extension for PHP you will need to use MongoDB\BSON\ObjectID as detailed on the php.net page
Related
I'me developing an app in zf2. when I define routes in module.config.php and access them in my browser, php throws error :
Fatal error: Class 'BookList\src\BookList\Controller\BookController' not found in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC9\data\localweb\projects\autoclick\skeleton-application\vendor\zendframework\zendframework\library\Zend\ServiceManager\AbstractPluginManager.php on line 170
here is my module.config.php :
return array(
'controllers' => array(
'invokables' => array(
'BookList\src\BookList\Controller\Book' => 'BookList\src\BookList\Controller\BookController'
)
),
'router' => array(
'routes' => array(
'book' => array(
'type' => 'segment',
'options' => array(
'route' => '/book[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+'
),
'defaults' => array(
'controller' => 'BookList\src\BookList\Controller\Book',
'action' => 'index'
)
)
)
)
),
'view_manager' => array(
'template_path_stack' => array(
'book' => __DIR__ . '/../view'
)
)
I have my BookController namespaced BookList\src\BookList\Controller
This should be:
'controllers' => array(
'invokables' => array(
'BookList\Controller\Book' => 'BookList\Controller\BookController' // <- change key and value
)
),
'router' => array(
'routes' => array(
'book' => array(
'type' => 'segment',
'options' => array(
'route' => '/book[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+'
),
'defaults' => array(
'controller' => 'BookList\Controller\Book', // <- change
'action' => 'index'
)
)
)
)
),
You should not specify the path, but only the class name, e.g. remove \BookList\src\ part. The namespace also should not container the src folder
hi have some problems with zend framework 2 + doctrine2 and DoctrineDataFixtureModule (https://github.com/Hounddog/DoctrineDataFixtureModule)
the module is not loading my fixtures
this is my config
'doctrine' => array(
'eventmanager' => array(
'orm_default' => array(
'subscribers' => array(
'Gedmo\Tree\TreeListener',
'Gedmo\Timestampable\TimestampableListener',
'Gedmo\Sluggable\SluggableListener',
'Gedmo\Loggable\LoggableListener',
'Gedmo\Sortable\SortableListener'
),
),
),
'driver' => array(
__NAMESPACE__.'_driver' => array(
'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
__DIR__ . '/../src/'.__NAMESPACE__.'/Entity',
)
'data-fixture' => array(
__NAMESPACE__.'_fixture' => __DIR__ . '/../src/'.__NAMESPACE__.'/Fixtures',
),
),
'translatable_metadata_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
'vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity',
),
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__.'\Entity' => __NAMESPACE__.'_driver',
// 'Gedmo\Translatable\Entity' => 'translatable_metadata_driver',
)
),
)
),
the problem is i dont know how set the fixtures path or what exactly key in the array i have to set the fixtures path
in the documentation the developer says:
To register drivers with Doctrine module simply add the drivers to the
doctrine.driver key in your configuration.
return array(
'data-fixture' => array(
'ModuleName_fixture' => __DIR__ . '/../src/ModuleName/Fixture',
),
);
You actually need to add the data-fixture array to the root of the configuration array, not in the doctrine array. Like so:
return array(
...
'doctrine' => array(
'eventmanager' => array(
'orm_default' => array(
'subscribers' => array(
'Gedmo\Tree\TreeListener',
'Gedmo\Timestampable\TimestampableListener',
'Gedmo\Sluggable\SluggableListener',
'Gedmo\Loggable\LoggableListener',
'Gedmo\Sortable\SortableListener'
),
),
),
'driver' => array(
__NAMESPACE__.'_driver' => array(
'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
__DIR__ . '/../src/'.__NAMESPACE__.'/Entity',
)
),
'translatable_metadata_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
'vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity',
),
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__.'\Entity' => __NAMESPACE__.'_driver',
// 'Gedmo\Translatable\Entity' => 'translatable_metadata_driver',
)
),
)
),
'data-fixture' => array(
__NAMESPACE__.'_fixture' => __DIR__ . '/../src/'.__NAMESPACE__.'/Fixtures',
),
...
);
I'll admit the wording in the documentation is a bit confusing.
I was following this tutorial
http://www.bigwisu.com/2012/10/03/zend-framework-2-doctrine-odm
when a get this error:
The class 'Application\Document\User' was not found in the chain configured namespaces
This is my module.doctrine-mongo-odm.local.php after a little bit of testing:
<?php
return array(
'doctrine' => array(
'connection' => array(
'odm_default' => array(
'server' => 'localhost',
'port' => '27017',
'user' => '',
'password' => '',
'dbname' => 'test',
'options' => array()
),
),
'configuration' => array(
'odm_default' => array(
'metadata_cache' => 'array',
'driver' => 'odm_default',
'generate_proxies' => true,
'proxy_dir' => 'data/DoctrineMongoODMModule/Proxy',
'proxy_namespace' => 'DoctrineMongoODMModule\Proxy',
'generate_hydrators' => true,
'hydrator_dir' => 'data/DoctrineMongoODMModule/Hydrator',
'hydrator_namespace' => 'DoctrineMongoODMModule\Hydrator',
'default_db' => 'test',
'filters' => array(), // array('filterName' => 'BSON\Filter\Class'),
'logger' => null // 'DoctrineMongoODMModule\Logging\DebugStack'
)
),
'odm_default' => array(
'drivers' => array(
'Application\Document' => 'odm_driver'
)
),
'odm_driver' => array(
'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
'module/Application/src/Application/Document'
),
),
'documentmanager' => array(
'odm_default' => array(
'connection' => 'odm_default',
'configuration' => 'odm_default',
'eventmanager' => 'odm_default'
)
),
'eventmanager' => array(
'odm_default' => array(
'subscribers' => array()
)
),
),
);
I could fix the error by adding this information to the the Application/config/module.config.php and remove it from the global conf:
<?php
namespace Application;
return array(
// routes, etc
'doctrine' => array(
'driver' => array(
'odm_driver' => array(
'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Document')
),
'odm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Document' => 'odm_driver'
)
)
)
)
Can you explain me, why this is working? And what is the best way to go, since i need the odm in different modules? Define it in every module.config.php where its needed?
Played a little with the configs I managed to setup Global configruation.
'odm_driver' => array(
'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Document')
),
'odm_default' => array(
'drivers' => array(
Change is here --> 'Admin\Document' => 'odm_driver'
)
)
As you can see, I've changed NAMESPACE to strict value, this made the trick. Really don't understand till the end new Namespaces in the ZF2.
I am having problem while implementing Multiple routes as defined Below in my snippet
EDIT: i am getting this exception too
Additional information:
Zend\Mvc\Exception\InvalidControllerException
with Message
Controller of type Account\Controller\VoucherController is invalid; must implement Zend\Stdlib\DispatchableInterface
<?php
namespace Account;
return array(
'controllers' => array(
'invokables' => array(
'Account\Controller\Account' => 'Account\Controller\AccountController',
'Account\Controller\Voucher' => 'Account\Controller\VoucherController',
),
// --------- Doctrine Settings For the Module
'doctrine' => array(
'driver' => array(
'account_entities' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/Account/Entity')
),
'orm_default' => array(
'drivers' => array(
'Account\Entity' => 'account_entities'
)
)
)
),
// The following section is new and should be added to your file
'router' => array(
'routes' => array(
'account' => array(
'type' => 'segment',
'options' => array(
'route' => '/account[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Account\Controller\Account',
'action' => 'index',
),
),
),
'voucher' => array(
'type' => 'segment',
'options' => array(
'route' => '/account/voucher[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Account\Controller\Voucher',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'account' => __DIR__ . '/../view',
),
),
),
);
Now the issue is i am getting a 404, when i try to access MyHost/account/Voucher
P.S: I already have A Controller under Account/Controller/Voucher and a view under Account/View/Voucher named as index.phtml now i dont know what am i missing here.
As Adnrew and Timdev comments above that there is something not right in your controller, you can check few basic things in your controller, that you have following code correct. specially the typos.
namespace Account\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class VoucherController extends AbstractActionController {
// you acctions
}
I'm having an odd problem. If I have 1 module my routes are correctly matched and the pages returned. Add another module to the application config and BANG - it stops working and ends up in the Module.php of my second module (which has boostrapping and triggers loads of events).
application.config.php
<?php
return array(
'modules' => array(
'CMS',
'AOCS',
),
'module_listener_options' => array(
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php',
),
'module_paths' => array(
'./module',
'./vendor',
),
),
);
CMS module config
<?php
return array(
'router' => array(
'routes' => array(
'Admin' => array(
'type' => 'Literal',
'options' => array(
'route' => '/admin',
'defaults' => array(
'__NAMESPACE__' => 'CMS\Controller',
'controller' => 'Index',
'action' => 'Login',
),
),
'may_terminate' => true,
),
'Logout' => array(
'type' => 'Literal',
'options' => array(
'route' => '/logout',
'defaults' => array(
'__NAMESPACE__' => 'CMS\Controller',
'controller' => 'Index',
'action' => 'Logout',
),
),
),
'CMS/Welcome' => array(
'type' => 'Literal',
'options' => array(
'route' => '/aocs/welcome',
'defaults' => array(
'__NAMESPACE__' => 'AOCS\Controller',
'controller' => 'Welcome',
'action' => 'Welcome',
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'CMS\Controller\Index' => 'CMS\Controller\IndexController',
),
),
'translator' => array(
'locale' => 'en_GB',
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../templates/admin.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
);
AOCS module config
<?php
return array(
'router' => array(
'routes' => array(
'Welcome' => array(
'type' => 'Literal',
'options' => array(
'route' => '/welcome',
'defaults' => array(
'__NAMESPACE__' => 'AOCS\Controller',
'controller' => 'Welcome',
'action' => 'Welcome',
),
),
),
'Mains' => array(
'type' => 'segment',
'options' => array(
'route' => '/aocs[/:controller][/:action][/:id]',
'defaults' => array(
'__NAMESPACE__' => 'AOCS\Controller',
'controller' => 'Welcome',
'action' => 'Welcome',
),
),
'may_terminate' => true,
'child_routes' => array(
'query' => array(
'type' => 'Query',
),
),
),
),
),
'navigation' => array(
'menu' => array(
'page-1' => array(
'label' => 'Logout',
'route' => 'Logout',
'resource' => 'aocs_index_logout'
),
'page-2' => array(
'label' => 'Login',
'route' => 'Admin' ,
'resource' => 'cms_index_login'
),
),
),
'service_manager' => array(
'factories' => array(
'menu' => 'AOCS\Navigation\MenuNavigationFactory'
),
),
'controllers' => array(
'invokables' => array(
'AOCS\Controller\Welcome' => 'AOCS\Controller\WelcomeController'
),
),
'translator' => array(
'locale' => 'en_GB',
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../templates/admin.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
/*'strategies' => array(
'ViewJsonStrategy',
),*/
),
);
Module.php from CMS
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
* #copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace CMS;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\View\Renderer\JsonRenderer;
use Zend\Di\Di;
use Zend\Config\Reader\Ini;
use Zend\Navigation\Navigation;
// AH core code
use Core\Classes\setDB;
use Core\Classes\setCache;
use Core\Models\SecurityModel;
use Core\Models\AclModel;
class Module
{
public function onBootstrap(MvcEvent $e)
{
$sm = $e->getApplication()->getServiceManager();
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
// Set config - required throughout
$reader = new Ini;
$sm->setService('configIni',$reader->fromFile('./config/application.ini'));
// Setup a Database connection
$sm->setService('setDB',new setDB($sm,'database'));
// Setup Caching
$sm->setService('setCache',new setCache($sm));
/*$eventManager->attach('dispatch', function ($sm) use ($controllers) {
print'<pre>[CMS]';print_r($sm->getRouteMatch());print'</pre>';
exit;
}, 100); // execute before executing action logic*/
// Assign system names to view models so we can set across templates
$view = $e->getViewModel();
$config = $sm->get('configIni');
$view->setVariable('systemname',$config['system']['name']);
$view->setVariable('systemshort',$config['system']['shortname']);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
}
Am I missing something obvious? Its really annoying!
Thanks
Antony
Fixed it!
The BANG was that I have a dispatch in the 2x Modules.php which for some reason were triggering automatically. As the 2nd checked if the user is logged in and they weren't it redirected causing problems.
The issue wasn't to do with my config it appears (unless I'm missing the obvious) that this is a bug in ZF2 where the dispatch events are not tied to the module they're called from but all get run automatically.
So if my page is in CMS module the AOCS modules > bootstrap is still run. Why??
Thanks for the point about type = Query - will update.