zf2 doctrine2 editAction - php

I am facing an error to edit the values of my Entity Category. Here is my code
Bearbeiten
In my IndexController is the Action:
public function editAction()
{
$id = (int) $this->params()->fromRoute('id');
$em = $this->getEntityManager();
$category = $em->getRepository('Application\Entity\Category')->find($id);
$form = new CategoryForm();
$form->setHydrator(new CategoryHydrator());
$form->bind($category);
$request = $this->getRequest();
if($request->isPost())
{
$form->setData($this->getRequest()->getPost());
if($form->isValid())
{
$object = $form->getData();
$category->setName($object->getName());
$category->setDescription($object->getDescription());
$category->setParent($object->getParent());
$em->flush();
return $this->redirect()->toRoute('home');
}
}
return array(
'form' => $form
);
}
Here is my CategoryForm.php:
namespace Application\Form;
use Zend\Form\Form;
class CategoryForm extends Form
{
public function __construct()
{
parent::__construct('categoryForm');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'name',
'attributes' => array(
'type' => 'text',
'id' => 'name',
),
'options' => array(
'label' => 'Ihr Name:',
),
));
$this->add(array(
'name' => 'description',
'attributes' => array(
'type' => 'text',
'id' => 'description',
),
'options' => array(
'label' => 'Ihre Beschreibung:',
),
));
$this->add(array(
'name' => 'parent',
'attributes' => array(
'id' => 'parent',
'name' => 'parent',
'type' => 'hidden',
),
));
$this->add(array(
'name'=>'submit',
'attributes'=>array(
'type' => 'submit',
'value' => 'OK',
),
));
}
}
And the following is my edit.phtml:
<?php
$form = $this->form;
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formRow($form->get('name'));
echo $this->formRow($form->get('description'));
echo $this->formRow($form->get('parent'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag();
?>
By calling the action 'edit', the browser shows a error with the message:
Object provided to Escape helper, but flags do not allow recursion
Does someone knows my mistake and can help me?

First, from your question it can only be quessed what the $child->getId() is. I assume the $child is an instance of the Category class, and getId() returns an integer, being the category's id. So instead, i just put this, for testing, in my index.phtml:
Bearbeiten
To be on the safe side, I have also passed an instance of Category to index.phtml as $child variable, used your code for the link, and the link worked, (so it's not something wrong with url view helper). Anyway, I could just write the url into the browser and click enter, but since I don't know where your error showed up, (perhaps after clicking the link), I had to make sure :)
Next, I copied your code exactly, except for this line:
$form->setHydrator(new CategoryHydrator());
You did not provide the code for your hydrator. I assume you've created it, but without it being shown to me, I can only assume there is an error somewhere in the hydrator code. Instead of that line, try:
$form->setHydrator ( new \DoctrineModule\Stdlib\Hydrator\DoctrineObject ( $em, 'Application\Entity\Category' ) );
I hope I can safely assume that DoctrineModule was installed with composer and is added to your 'modules' array in application.config.php.
With this line, otherwise the code being exactly as yours, after a click on the link, or entering the URI /application/edit/1 ( 1 being the id of my category to edit), the form was displayed and the input fields were populated correctly, without any errors.
If there's still something wrong, perhaps there is some error in your Category entity.

Related

Save cakephp 2.0 associations

I am trying to save associated data in Cakephp 2.0, in the database I have two tables, table entities (id, main_name) and adresses(id, entity_id, city)
In the Entities model I made the association:
public $hasMany = array(
'Address' => array(
'className' => 'Address',
'foreignKey' => 'entity_id'
)
);
In the AdressesController I saved with the following data:
public function add() {
if ($this->request->is('post')) {
if($this->Entity->save($this->request->data)) {
$this->Flash->success('Entity successfully registered!');
$this->redirect(array('action' => 'add'));
} else {
$this->Flash->error(Oops, we could not register this entity!
Make sure it already exists.');
}
}
}
And in the view, my form looks like this:
<?php
echo $this->Form->input(
'Entity.main_name',
array(
'type' => 'text',
'class' => 'form-control',
'label' => false
)
);
?>
<?php
echo $this->Form->input(
'Address.city',
array(
'type' => 'text',
'class' => 'form-control',
'label' => false
)
);
?>
The data of the entity normally saved in the database, but does not relate the entity_id and does not save the city in the adresses table, do I have to do anything else in the controller?
There are several ways of solving your problem. Like described in CakeBook: Saving your data you can use saveAssociated() or Save each Model step by step.
Saving using saveAssociated()
In your Controller/EntitiesController.php:
public function add() {
if ($this->request->is('post')) {
$this->Entity->create();
// Use saveAssociated() instead of save() here
if ($this->Entity->saveAssociated($this->request->data)) {
$this->Flash->success(__('The entity has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Flash->error(__('The entity could not be saved. Please, try again.'));
}
}
$addresses = $this->Entity->Address->find('all');
$this->set($addresses);
}
In your View/Entities/add.ctp:
<?php
echo $this->Form->input('main_name', array(
'type' => 'text',
'class' => 'form-control',
'label' => false
));
// Make sure you use Address.0.city
echo $this->Form->input('Address.0.city', array(
'type' => 'text',
'class' => 'form-control',
'label' => false
));
?>
Since you use a hasMany Association a Entity can have several Addresses. For this reason you have to set the 0 in Address.0.city. This will result in a data array like this:
array(
'Entity' => array(
'main_name' => 'Fancy Name'
),
'Address' => array(
(int) 0 => array(
'city' => 'Cool City'
)
)
)
Saving Models step by step
Another approach would be to save the Entity and then save the Address with the entity_id like described in CakeBook:
In your Controller/EntitiesController.php:
public function add() {
if (!empty($this->request->data)) {
// save Entity
$entity = $this->Entity->save($this->request->data);
if (!empty($entity)) {
// Set the EntityId to the data array and save the Address with the EntityId
$this->request->data['Address']['entity_id'] = $this->Entity->id;
$this->Entity->Address->save($this->request->data);
}
}
}
In this case your View/Entities/add.ctp Address form would look like:
echo $this->Form->input('Address.city', array(
'type' => 'text',
'class' => 'form-control',
'label' => false
));
Best, variables

zf2 Date element not required

I have a problem with Zend Framework 2 and Date element. The attribute I'm trying to store is a DateOfBirth, but this attribute maybe empty. For example the date is unknown. The column in the database allows NULL. The Doctrine class attached to it has a attribute that let's it know it allows null. But Zend Framework 2 still gives me this error:
"Value is required and can't be empty".
Even though I set the required attribute=false, also the allow_empty=true, but nothing works.
The attirbute it a member of a nested fieldset within a form. The nesting looks as follows:
UserManagementForm
User (fieldset)
Person (fieldset)
DateOfBirth (element)
Couple examples i tried:
Form not validating correctly zend framework 2
https://github.com/zendframework/zf2/issues/4302
Here is the code I am using at the moment. Hopefully you see something that I'm missing. I don't know if it due to the fact that it is nested, but the rest works perfect, only the date element is causing me trouble.
UserManagementForm
<?php
namespace Application\Form;
use Zend\Form\Form;
class UserManagementForm extends Form
{
public function __construct()
{
parent::__construct('usermanagementform');
$this->setAttribute('method', 'post');
$fieldset = new \Application\Form\Fieldset\User();
$fieldset
->setHydrator(new \Zend\Stdlib\Hydrator\ObjectProperty(false))
->setObject(new \Application\Entity\User())
->setOptions(array('use_as_base_fieldset' => true))
;
$this->add($fieldset);
$this->add(array(
'name' => 'btnSubmit',
'type' => 'submit',
'attributes' => array(
'class' => 'btn-primary',
),
'options' => array(
'column-size' => 'sm-9 col-sm-offset-3',
'label' => 'Save changes',
),
));
}
}
?>
User (Fieldset)
<?php
namespace Application\Form\Fieldset;
use Zend\Form\Fieldset;
class User extends Fieldset
{
public function __construct()
{
parent::__construct('User');
$fieldset = new \Application\Form\Fieldset\EmailAddress();
$fieldset
->setHydrator(new \Zend\Stdlib\Hydrator\ObjectProperty(false))
->setObject(new \Application\Entity\EmailAddress());
$this->add($fieldset);
$fieldset = new \Application\Form\Fieldset\Person();
$fieldset
->setHydrator(new \Zend\Stdlib\Hydrator\ObjectProperty(false))
->setObject(new \Application\Entity\Person());
$this->add($fieldset);
}
}
?>
Person (fieldset)
<?php
namespace Application\Form\Fieldset;
use Zend\Form\Fieldset;
class Person extends Fieldset
{
public function __construct()
{
parent::__construct('Person');
$this->add(array(
'type' => 'date',
'name' => 'DateOfBirth',
'required' => false,
'allowEmpty' => true,
'options' => array(
'label' => 'Date of birth',
'column-size' => 'sm-9',
'label_attributes' => array(
'class' => 'col-sm-3',
),
'format' => 'd-m-Y',
),
));
}
}
?>
'required' isn't an attribute of element but an validator attribute.
The solution consist to implement Zend\InputFilter\InputFilterProviderInterface
use Zend\InputFilter\InputFilterProviderInterface;
class UserManagementForm extends AbstractSbmForm implements InputFilterProviderInterface {
public function __construct()
{
... without change
}
public function getInputFilterSpecification()
{
return array(
'DateOfBirth' => array(
'name' => 'DateOfBirth',
'required' => false,
);
);
}
}

Zend Framework 2 - I can't manage to validate form when using fieldsets

I have a Registration form.
namespace User\Form;
use Zend\Form\Form;
class Register extends Form {
public function __construct() {
parent::__construct('register');
$this->setAttribute('action', 'new-account');
$this->setAttribute('method', 'post');
//$this->setInputFilter(new \User\Form\RegisterFilter); - used this prior to learning Fieldset
$this->add(new \User\Form\RegisterFieldsetUser);
// Submit
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Register',
'class' => 'btn btn-primary',
),
));
}
}
and the User fieldset:
(to make this short I've only left on field)
namespace User\Form;
use Zend\Form\Fieldset;
class RegisterFieldsetUser extends Fieldset {
public function __construct() {
parent::__construct('user');
// User Identifier
$identifier = new \Zend\Form\Element\Email();
$identifier->setName('identifier');
$identifier->setAttributes(array(
'id' => 'user-email',
'placeholder' => 'Email'
));
$identifier->setLabel('Your email:');
$this->add($identifier);
}
public function getInputFilterSpecification() {
return array(
'identifier' => array(
'filters' => array(
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'break_chain_on_failure' => true,
'options' => array(
'messages' => array(
\Zend\Validator\NotEmpty::IS_EMPTY => 'You really have to enter something!',
),
),
),
array(
'name' => 'EmailAddress',
'options' => array(
'messages' => array(
\Zend\Validator\EmailAddress::INVALID_FORMAT => 'Hmm... this does not look valid!',
),
),
),
),
),
);
}
}
this is my action:
public function registerAction() {
$registerForm = new \User\Form\Register;
if ($this->getRequest()->isPost()) {
// Form processing
$formData = $this->getRequest()->getPost();
if ($registerForm->isValid()) {
// Yeeeeei
} else {
$registerForm->setData($formData);
return new ViewModel(array(
'form' => $registerForm,
));
}
} else {
return new ViewModel(array(
'form' => $registerForm,
));
}
}
Now, if I submit the form without entering anything, I get the message : "Value is required and can't be empty" (which is NOT the message I have set). But it's not an issue with the messages I set, because if I submit the form with an invalid email address ("asd/") then it doesn't say anything, no validation error. So, I assume no validation happens here.
Any clue why?
Before learning to use filedset, I had an InputFilter which worked perfectly fine, but following the book's learning curve, I got to using Fieldset.
I'm just a zf newb, learning from this book I've bought from leanpub (Michael Romer's "Web development with zf2"). I don't know the version used in the book (it was last updated in august 2013), but I use the latest (2.2.5).
If you want to add filter specification by getInputFilterSpecification method your form class (or fieldset class) MUST implement InputFilterProviderInterface. So:
<?php
use Zend\InputFilter\InputFilterProviderInterface;
class RegisterFieldsetUser extends Fieldset
implements InputFilterProviderInterface
{
...
}

Create a drop down list in Zend Framework 2

I know this sounds much more basic, still I want to post my question as it is related to Zend Framework 2. I know this form from the Zend example module
namespace Album\Form;
use Zend\Form\Form;
class AlbumForm extends Form
{
public function __construct($name = null)
{
// we want to ignore the name passed
parent::__construct('album');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
$this->add(array(
'name' => 'artist',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Artist',
),
));
$this->add(array(
'name' => 'title',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Title',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
And this is called in this fashion
<?php
$form = $this->form;
$form->setAttribute('action', $this->url('album', array('action' => 'add')));
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formHidden($form->get('id'));
echo $this->formRow($form->get('title'));
echo $this->formRow($form->get('artist'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag();
How can I add a drop down list for the artist field where the list is stored in an associative array. Since Im getting into Zend Framework 2, I wanted the suggestions from the experts. I have followed this previous post but it was somewhat unclear to me.
This is one way to do it for static options.
....
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'number'
'options' array(
'options' => array( '1' => 'one', '2', 'two' )
)
));
Be warned....
Because you are creating the form within a constructor you will not have access the ServiceManger. This could cause a problem if you want to populate from a database.
Lets try something like...
class AlbumForm extends Form implements ServiceManagerAwareInterface
{
public function __construct()
{
....
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'number'
));
....
}
....
public function initFormOptions()
{
$this->get('number')->setAttribute('options', $this->getNumberOptions());
}
protected function getNumberOptions()
{
// or however you want to load the data in
$mapper = $this->getServiceManager()->get('NumberMapper');
return $mapper->getList();
}
public function getServiceManager()
{
if ( is_null($this->serviceManager) ) {
throw new Exception('The ServiceManager has not been set.');
}
return $this->serviceManager;
}
public function setServiceManager(ServiceManager $serviceManager)
{
$this->serviceManager = $serviceManager;
}
But that's not great, rethink...
Extending the Form so that you can create a form isn't quite right. We are not creating a new type of form, we are just setting up a form. This calls for a factory. Also, the advantages of using a factory here are that we can set it up in a way in which we can use the service manager to serve it up, that way the service manager can inject itself instead of us doing in manually from the controller. Another advantage is that we can invoke this form whenever we have the service manager.
Another point worth making is that where it makes sense, I think it's better to take code out of the controller. The controller is not a script dump so it's nice to have objects look after themselves. What I'm trying to say is that it's good to inject an object with objects it needs, but it's not okay to just hand it the data from the controller because it creates too much of a dependency. Don't spoon feed objects from the controller, inject the spoon.
Anyway, too much rant more code...
class MySpankingFormService implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceManager )
{
$mySpankingNewForm = new Form;
// build that form baby,
// you have a service manager,
// inject it if you need to,
// otherwise just use it.
return $mySpankingNewForm;
}
}
controller
<?php
class FooController
{
...
protected function getForm()
{
if ( is_null($this->form) ) {
$this->form =
$this->getServiceManager()->get('MySpankingFormService');
}
return $this->form;
}
...
}
module.config.php
...
'service_manager' => array (
'factories' => array (
...
'MySpankingFormService'
=> 'MyNameSpacing\Foo\MySpankingFormService',
...

Zend Framework 2 RC3 Zend\Form#getData()

I wonder if I'm doing something wrong or if this is a bug in ZF2: When i'm trying to set some data on a form, validate it and retrieve the data it's just an empty array.
I extracted this code from some classes to simplify the problem
$form = new \Zend\Form\Form;
$form->setInputFilter(new \Zend\InputFilter\InputFilter);
$form->add(array(
'name' => 'username',
'attributes' => array(
'type' => 'text',
'label' => 'Username',
),
));
$form->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Register',
),
));
if ($this->getRequest()->isPost()) {
$form->setData($this->getRequest()->getPost()->toArray());
if ($form->isValid()) {
echo '<pre>';
print_r($form->getData());
print_r($form->getMessages());
echo '</pre>';
}
}
both print_r()s show empty arrays. I don't get any Data out of the form as well as no messages. Is it my fault or ZF2's?
Thanks to #SamuelHerzog and #Sam,
the form needs inputFilters for all elements. In the case of the form described in the question this short code is enough to get it work at all.
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'username'
)));
$form->setInputFilter($inputFilter);
It's not required to have any rules for the element, it just needs to be added to the inpoutFilter to work basically. By default any element has the required flag and must not be a blank value.

Categories