How to integrate ZF2 with Doctrine Mongo ODM? [closed] - zend-framework

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am trying to integrate zf2 beta3 with doctrine mongo odm (https://github.com/doctrine/DoctrineMongoODMModule) but no sucess.
How can I install and configure it?

I'm doing just the same thing. Something like this should work:
Download the module, and place in your vendor folder.
Add the module in application.config.php
Copy module.doctrine_mongodb.config.php.dist to /config/autoload
Edit that config file with your own settings
Change the name of that config file to module.doctrine_mongodb.local.config.php
Create a 'setDocumentManager' method in your controller like this:
protected $documentManager;
public function setDocumentManager(DocumentManager $documentManager)
{
$this->documentManager = $documentManager;
return $this;
}
Place the following in your module's DI config:
'Application\Controller\[YourControllerClass]' => array(
'parameters' => array(
'documentManager' => 'mongo_dm'
)
),
Create Document classes according to the Doctrine 2 documentation, and the clarification in this question and answer: Annotations Namespace not loaded DoctrineMongoODMModule for Zend Framework 2
Finally, use the dm like this:
public function indexAction()
{
$dm = $this->documentManager;
$user = new User();
$user->set('name', 'testname');
$user->set('firstname', 'testfirstname');
$dm->persist($user);
$dm->flush();
return new ViewModel();
}

I will give the steps I have done to integrate zf2 with mongodb doctrine odm
1.Download the mongodb doctrine odm module and place in vendor directory or clone it from github
cd /path/to/project/vendor
git clone --recursive https://github.com/doctrine/DoctrineMongoODMModule.git
2.Copy the file from /path/to/project/vendor/DoctrineMongoODMModule/config/module.doctrine_mongodb.config.php.dist, place in your path/to/your/project/config/autoload/ and rename to module.doctrine_mongodb.local.config.php
3.Edit your module.doctrine_mongodb.local.config.php.
Change the default db
'config' => array(
// set the default database to use (or not)
'default_db' => 'myDbName'
),
Change your connection params
'connection' => array(
//'server' => 'mongodb://<user>:<password>#<server>:<port>',
'server' => 'mongodb://localhost:27017',
'options' => array()
),
Change the driver options
'driver' => array(
'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
'namespace' => 'Application\Document',
'paths' => array('module/Application/src/Application/Document'),
),
Add proxy and hydratros config
'mongo_config' => array(
'parameters' => array(
'opts' => array(
'auto_generate_proxies' => true,
'proxy_dir' => __DIR__ . '/../../module/Application/src/Application/Document/Proxy',
'proxy_namespace' => 'Application\Model\Proxy',
'auto_generate_hydrators' => true,
'hydrator_dir' => __DIR__ . '/../../module/Application/src/Application/Document/Hydrators',
'hydrator_namespace' => 'Application\Document\Hydrators',
'default_db' => $settings['config']['default_db'],
),
'metadataCache' => $settings['cache'],
)
),
4.Create a directory named "Document" in /path/to/project/module/Application/src/Application/ where goes your documents mapping and inside "Document" directory, create "Proxy" and "Hydrators" directories.
5.Edit your /path/to/project/config/application.config.php and add 'DoctrineMongoODMModule' to modules array
6.Be sure you have mongo php extension installed otherwise download at http://www.php.net/manual/en/mongo.installation.php#mongo.installation.windows and copy it to your extension php directory, usually /php/ext. Add the extension line acording the name file extension you have downloaded "extension=php_mongo-x.x.x-5.x-vc9.dll" in your php.ini.
7.Create a document mapping User.php in your document directory application module.
<?php
namespace Application\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/** #ODM\Document */
class User
{
/** #ODM\Id */
private $id;
/** #ODM\Field(type="string") */
private $name;
/**
* #return the $id
*/
public function getId() {
return $this->id;
}
/**
* #return the $name
*/
public function getName() {
return $this->name;
}
/**
* #param field_type $id
*/
public function setId($id) {
$this->id = $id;
}
/**
* #param field_type $name
*/
public function setName($name) {
$this->name = $name;
}
}
8.Persist it, for example in your controller
<?php
namespace Application\Controller;
use Zend\Mvc\Controller\ActionController,
Zend\View\Model\ViewModel,
Application\Document\User;
class IndexController extends ActionController
{
public function indexAction()
{
$dm = $this->getLocator()->get('mongo_dm');
$user = new User();
$user->setName('Bulat S.');
$dm->persist($user);
$dm->flush();
return new ViewModel();
}
}

Now the default config has changed, could you show an updated method to get this working in ZF2?
<?php
return array(
'doctrine' => array(
'connection' => array(
'odm_default' => array(
'server' => 'localhost',
'port' => '27017',
'user' => null,
'password' => null,
'dbname' => 'user',
'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' => null,
'filters' => array() // array('filterName' => 'BSON\Filter\Class')
)
),
'driver' => array(
'odm_default' => array(
'drivers' => array()
)
),
'documentmanager' => array(
'odm_default' => array(
'connection' => 'odm_default',
'configuration' => 'odm_default',
'eventmanager' => 'odm_default'
)
),
'eventmanager' => array(
'odm_default' => array(
'subscribers' => array()
)
),
),
);
Currently receiving the error: The class 'Application\Document\User' was not found in the chain configured namespaces

Related

Zend framework 2 form element normalization

I am migrating an application from Zend 1 to Zend 2 and starting to desperate with one issue. The application works with different locales and therefore, I need to store the data in a normalized way in the database. In Zend 1 I used this code:
public function normalizeNumber( $value )
{
// get the locale to change the date format
$this->_locale = Zend_Registry::get('Zend_Locale' );
return Zend_Locale_Format::getNumber($value, array('precision' => 2, 'locale' => $this->_locale));
}
Unfortunately Zend 2 does not has this Zend_Locale_Format::getNumber any more and I was not able to figure out what function did replace it. I have tried with NumberFormat, but I get only localized data not normalized. I need this function to normalize data I receive from a form via POST. Can someone give some advice?
thanks
Just to complete my question. The Form element definition I am using is the following:
namespace Profile\Form;
use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;
class Profile Extends Form implements InputFilterProviderInterface
{
protected $model;
public function __construct( $model, $name = 'assignmentprofile')
{
parent::__construct( $name );
$this->setAttribute( 'method', 'post');
$this->model = $model;
...
$this->add( array(
'name' =>'CommutingRate',
'type' =>'Zend\Form\Element\Text',
'options' => array( // list of options to add to the element
'label' => 'Commuting rate to be charged:',
'pattern' => '/[0-9.,]/',
),
'attributes' => array( // Attributes to be passed to the HTML lement
'type' =>'text',
'required' => 'required',
'placeholder' => '',
),
));
}
public function getInputFilterSpecification()
{
return array(
...
'CommutingRate' => array(
'required' => true,
'filters' => array(
array( 'name' => 'StripTags', ),
array( 'name' => 'StringTrim'),
array( 'name' => 'NumberFormat', 'options' => array('locale' => 'en_US', 'style' => 'NumberFormatter::DECIMAL', 'type' => 'NumberFormatter::TYPE_DOUBLE',
))
),
'validators' => array(
array( 'name' => 'Float',
'options' => array( 'messages' => array('notFloat' => 'A valid numeric entry is required')),
),
),),
...
);
}
}
As mentioned before, I am able to localized the data and validate it in the localized manner, but i am failing to convert it back to a normalized manner...

Transform forms from Symfony2 to Symfony3

I want to transform a form like this to comply with Symfony3 code :
$form = $this->createForm(new AjoutQC(array('idcolle' => $idColle,'idqc' => $question->getId())),
$question,
array('action' => $this->generateUrl('paces_colle_qc_update',
array(
'id' => $question->getId(),
'idColle' => $idColle,
'idTuteur' => $idTuteur)
),
'method' => 'PUT',
));
$form->add('submit', SubmitType::class, array('label' => 'Sauvegarder'));
Symfony3 asks for something like :
AjoutQC::class
instead of :
new AjoutQC...
I didn't find anything about it after some research.
Check these upgrade notes for forms.
It says:
Passing type instances to Form::add(), FormBuilder::add() and the FormFactory::create*() methods is not supported anymore. Pass the fully-qualified class name of the type instead.
Before:
$form = $this->createForm(new MyType());
After:
$form = $this->createForm(MyType::class);
You can use OptionsResolver and pass your data array('idcolle' => $idColle,'idqc' => $question->getId()) that you are currently passing to your form type as a third argument to createForm method:
$form = $this->createForm(AjoutQC::class, $question, array(
'action' => $this->generateUrl('paces_colle_qc_update', array(
'id' => $question->getId(),
'idColle' => $idColle,
'idTuteur' => $idTuteur,
)),
'method' => 'PUT',
'idcolle' => $idColle,
'idqc' => $question->getId(),
));
Then in your AjoutQC type you need to do something like:
use Symfony\Component\OptionsResolver\OptionsResolver;
// ..
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->idcolle = $options['idcolle'];
$this->idqc = $options['idqc'];
$builder
->add(...)
// ..
;
}
// ..
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array('idcolle', 'idqc'));
}
This will set idcolle, idqc options as required, that must be passed to your form type (AjoutQC).
In Symfony 3 you need to use FQCN (fully-qualified class name) instead of an instance of the form (or a string reference to a service).
$form = $this->createForm(
AjoutQC::class,
$question,
array(
'action' => $this->generateUrl(
'paces_colle_qc_update',
array(
'id' => $question->getId(),
'idColle' => $idColle,
'idTuteur' => $idTuteur
)
),
'method' => 'PUT',
'idColle' => $idColle,
'idQc' => $question->getId()
)
)
In your AjoutQC class you need to go to your configureOptions method and add the idcolle and idqc options:
class AjoutQC extends AbstractType {
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array('idColle','idQc'));
$resolver->setDefaults(
array(
'data_class' => 'Your\Entity\Path',
'idColle' => null,
'idQc' => null
)
);
}
}
If you are just wondering about the ::class notation, you can find information about that here: http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class.class
::class requires php >= 5.5
If you are using <5.5 you can just simply use the FQCN e.g. MyLong\Namespace\Fully\Qualified\ClassNameType

Symfony2 form refresh same page after submit

I have a form whose content is created from a DB.
in my controller i have:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
//here I get all the data from DB and create the form
if ($form->isValid())
{
//here I do all the relevant changes in the DB
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
It updates the info on the DB properly, but it does not build again the form with updated data. Instead of the return inside the "isValid()" I simply need a refresh on the current page.
I assume it's possible and easy to accomplish, but I failed to find how to do it :/
EDIT - here comes more relevant code:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
$user = $this->container->get('security.context')->getToken()->getUser(); //get current user
$em = $this->getDoctrine()->getManager(); //connect to DB
$prj = $this->getDoctrine()->getRepository('AppBundle:Project')->findOneById($projectID);
[...]
// here comes some code to generate the list of $HRsInThisProject and the list of roles ($rolesListForForm)
[...]
foreach ($HRsInThisProject as $key => $HR)
{
$form->add('roleOf_'.$key, 'choice', array('choices' => $rolesListForForm, 'required' => true, 'data' => $HR['role'], 'label' => false, ));
$form->add('isActive_'.$key, 'choice', array('choices' => [0 => 'Inactive', 1 => 'Active'] , 'required' => true, 'data' => $HR['is_active'], 'label' => false, ));
}
[...]
// here there is some code to get the $HRsInMyDomainForForm
[...]
$form->add('HRid', 'choice', array('choices' => $HRsInMyDomainForForm,'required' => false, 'placeholder' => 'Choose a resource', 'label' => false, ));
$form->add('role', 'choice', array('choices' => $rolesListForForm,'required' => false, 'placeholder' => 'Choose a role', 'label' => false, ));
$form->add('save', 'submit', array('label' => 'Save'));
$form->handleRequest($request);
if ($form->isValid())
{
{
[...] here there is a huge portion of code that determines if I need to generate a new "event" to be stored, or even multiple events as I can change several form fields at once
// If I needed to create the event I persist it (this is inside a foreach)
$em->persist($newHREvent);
}
$em->flush();
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
I also include a screenshot of the form:
If a user selects to add a new resouce, I need to persist it to DB (and that is done properly) but then I need to see it in the list of available HRs, without the need for the user to reload the page.
More dynamic way would be:
$request = $this->getRequest();
return $this->redirectToRoute($request->get('_route'), $request->query->all());
or simply
return $this->redirect($request->getUri());
I managed to solve it in a simple (and I hope correct) way.
I simply substituted the "render" inside the isValid() with the following:
return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $prj->getId())));
I works, but does anybody foresee problems with this solution?
You have to link the form to the request.
$entity = new Entity();
$form = $this->createFormBuilder($entity)
->add('field1', 'text')
->add('field2', 'date')
->add('save', 'submit', array('label' => 'Submit'))
->getForm();
$form->handleRequest($request); // <= this links the form to the request.
only after that you test $form->isValid() and pass this form when rendering the template. If you already did this and haven't included in the code above please show more code for better help.
Here is the right way to do it. Event though you have $projectId slug, in Action you can pass whole Object, in this case Project. Symfony will take care for the rest (fetching right Project entity for you.
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, Project $project)
{
$form = $this->createForm(new ProjectType(), $project);
$form->handleRequest($request);
// ... your business logic or what ever
//here I get all the data from DB and create the form
if ($form->isValid() && $form->isSubmitted()) {
$em->persist($project);
// no need to flush since entity already exists
// no need to redirect
}
// here $form->createView() will populate fields with data since you have passed Poroject $project to form
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
Update
According to your edit, you need to use javascript for client-side dom manipulation. Check this link from Symfony official document embedded forms. Here you'll find an example of what you're trying to accomplish.

Zend Framework 2 - Gobal Variable that are accessible to controller/model that are initialize in local.php or global.php

Hello everyone please someone help me how to create a global variable in zend framework 2 to be use in table prefix that are accessible in controller and model.
Thanks and regards to all.
In your config/database.local.php you can define which you want globally
<?
return array(
'service_manager' => array(
'factories' => array(
//'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
'Zend\Db\Adapter\Adapter' => function ($serviceManager) {
$adapterFactory = new Zend\Db\Adapter\AdapterServiceFactory();
$adapter = $adapterFactory->createService($serviceManager);
\Zend\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($adapter);
return $adapter;
}
),
),
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=testdb;host=localhost',
'username' => 'root',
'password' => '',
),
'msg' => array(
'add' => 'Data Inserted Successfully',
'edit' => 'Data Updated Successfully',
'delete' => 'Data Deleted Successfully',
),
);
?>
Controller File:
DemoController.php
<?php
namespace Demo\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class DemoController extends AbstractActionController
{
public function indexAction($cms_page_name='whyus')
{
/*Call config file to fetch current cms page id-- fetch config file from database.local.php*/
$config = $this->getServiceLocator()->get('Config');
$all_msg = $config['msg'];
}
}
?>

Including settings in to module class

Im my module.config.php file got following excerpt:
return array(
'service_manager' => array(
'aliases' => array(
'Util\Dao\Factory' => 'modelFactory',
),
'factories' => array(
'modelFactory' => function($sm) {
$dbAdapter = $sm->get('Doctrine\ORM\EntityManager');
return new \Util\Dao\Factory($dbAdapter);
},
)
),
'doctrine' => array(
'driver' => array(
'application_entities' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
__DIR__ . '/../src/Application/Model'
),
),
'orm_default' => array(
'drivers' => array(
'Application\Model' => 'application_entities'
)
),
),
),
How do i put the block "doctrine" in module class?
Well, this is actually fairly simple. Probably your Module class has the method getConfig(). That method usually loads moduleName/config/module.config.php.
So in whatever function you are, simply call the getConfig()-method. This is pure and basic php ;)
//Module class
public function doSomethingAwesome() {
$moduleConfig = $this->getConfig();
$doctrineConfig = isset($moduleConfig['doctrine'])
? $moduleConfig['doctrine']
: array('doctrine-config-not-initialized');
}
However you need to notice that this only includes your Modules config. If you need to gain access to the merged configuration, you'll need to do that in the onBootstrap()-method. Which would be done like this:
//Module class
public function onBootstrap(MvcEvent $mvcEvent)
{
$application = $mvcEvent->getApplication();
$serviceLocator = $application->getServiceLocator();
$mergedConfig = $serviceLocator->get('config');
$doctrineConfig = isset($mergedConfig['doctrine'])
? $mergedConfig['doctrine']
: array('doctrine-config-not-initialized');
}
This works similar if you're attaching to some events...