I have a problem with addAction in my CRUD application. On the controller, the logic does not pass the check $ form-> isValid (), but the error message is not displayed on the form.
I tried with this (thanks to Sam):
foreach($form->get('product')->getElements() as $el) { echo $el->getName()." = ".$el->getValue()." > ".$el->getMessages()." <br/>"; }
This displays only the name and value of the field, but not the error message.
I tried to allow the form to be completely empty, and the error message βValue is required and cannot be emptyβ lights up, but then I fill each field one at a time until I get more error messages, but the form is still invalid.
My form has a Fieldset field as a basic set of fields and a submit button. Inside the product field set, I have an identifier field, a name field, a price field, and a Fieldset brand. Inside my Fieldset brand, I have an id field. Like this:
ProductForm:
class ProductForm extends Form { public function init() { // we want to ignore the name passed parent::__construct('product'); $this->setName('product'); $this->setAttribute('method', 'post'); $this->add(array( 'name' => 'product', 'type' => 'Administrador\Form\ProductFieldset', 'options' => array( 'use_as_base_fieldset' => true ), )); $this->add(array( 'name' => 'submit', 'type' => 'Submit', 'attributes' => array( 'value' => 'Add', 'id' => 'submitbutton', ), )); } }
ProductFieldset:
class ProductFieldset extends Fieldset implements ServiceLocatorAwareInterface { protected $serviceLocator; function __construct($name = null) { parent::__construct('product_fieldset'); $this->setHydrator(new ArraySerializableHydrator()); $this->setObject(new Product()); } public function init() { $this->add(array( 'name' => 'id', 'type' => 'Hidden', )); $this->add(array( 'name' => 'name', 'type' => 'Text', 'options' => array( 'label' => 'Name', ), )); $this->add(array( 'name' => 'price', 'type' => 'Text', 'options' => array( 'label' => 'Price', ), )); $this->add(array( 'name' => 'brand', 'type' => 'BrandFieldset', )); } public function setServiceLocator(ServiceLocatorInterface $sl) { $this->serviceLocator = $sl; } public function getServiceLocator() { return $this->serviceLocator; } }
BrandFieldset:
class BrandFieldset extends Fieldset { function __construct(BrandTable $brandTable) { parent::__construct('brand_fieldset'); //$this->setHydrator(new ClassMethodsHydrator(false))->setObject(new Brand()); $this->setHydrator(new ArraySerializableHydrator()); $this->setObject(new Brand()); $brandSelectOptionsArray = $brandTable->populateSelectBrand(); $this->add(array( 'name' => 'id', 'type' => 'Select', 'options' => array( 'label' => 'Brand', 'empty_option' => 'Please select a brand', 'value_options' => $brandSelectOptionsArray, ), )); } }
This is my new Form statement in addAction:
$formManager = $this->serviceLocator->get('FormElementManager'); $form = $formManager->get('Administrador\Form\ProductForm');
In my Product model, I have inputFilters, the required filter for the id field, the necessary filter for the name field. And for the Brand field, I created another inputFilter and added it to the main input filter:
$brandFilter->add($factory->createInput(array( 'name' => 'id', 'required' => true, 'filters' => array( array('name' => 'Int'), ), ))); $inputFilter->add($brandFilter, 'brand');
The strange behavior is that my editAction works fine and has the same logic.
Is there any form of echo of the internal error message from the form, which helps me to understand WHY the form is invalid.
EDIT 2013-06-01
Here is my complete controller:
class ProductController extends AbstractActionController { protected $productTable; protected $brandTable; public function indexAction() { return new ViewModel(array( 'products' => $this->getProductTable()->fetchAll(), )); } public function addAction() { $formManager = $this->serviceLocator->get('FormElementManager'); $form = $formManager->get('Administrador\Form\ProductForm'); $form->get('submit')->setValue('Add'); $request = $this->getRequest(); if ($request->isPost()) { $product = new Product(); $product->brand = new Brand(); $form->setInputFilter($product->getInputFilter()); $form->setData($request->getPost()); if ($form->isValid()) { $product->exchangeArray($form->getData()); $this->getProductTable()->saveProduct($product); // Redirect to list of products return $this->redirect()->toRoute('product'); } } return new ViewModel(array( 'form' => $form, )); } public function editAction() { $id = (int) $this->params()->fromRoute('id', 0); if (!$id) { return $this->redirect()->toRoute('product', array( 'action' => 'add' )); } // Get the Product with the specified id. An exception is thrown // if it cannot be found, in which case go to the index page. try { $product = $this->getProductTable()->getProduct($id); } catch (\Exception $ex) { return $this->redirect()->toRoute('product', array( 'action' => 'index' )); } $formManager = $this->serviceLocator->get('FormElementManager'); $form = $formManager->get('Administrador\Form\ProductForm'); $brand = $this->getBrandTable()->getBrand($product->brand); $product->brand = $brand; $form->bind($product); $form->get('submit')->setAttribute('value', 'Edit'); $request = $this->getRequest(); if ($request->isPost()) { $form->setInputFilter($product->getInputFilter()); $form->setData($request->getPost()); if ($form->isValid()) { $this->getProductTable()->saveProduct($form->getData()); // Redirect to list of products return $this->redirect()->toRoute('product'); } } return array( 'id' => $id, 'form' => $form, ); } public function deleteAction() { $id = (int) $this->params()->fromRoute('id', 0); if (!$id) { return $this->redirect()->toRoute('product'); } $request = $this->getRequest(); if ($request->isPost()) { $del = $request->getPost('del', 'No'); if ($del == 'Yes') { $id = (int) $request->getPost('id'); $this->getProductTable()->deleteProduct($id); } // Redirect to list of products return $this->redirect()->toRoute('product'); } return array( 'id' => $id, 'product' => $this->getProductTable()->getProduct($id) ); } public function getProductTable() { if (!$this->productTable) { $sm = $this->getServiceLocator(); $this->productTable = $sm->get('Administrador\Model\ProductTable'); } return $this->productTable; } public function getBrandTable() { if (!$this->brandTable) { $sm = $this->getServiceLocator(); $this->brandTable = $sm->get('Administrador\Model\BrandTable'); } return $this->brandTable; } }