Dynamic added fieldset/ collection not added to database Zend 2 Doctrin 2 - doctrine-orm

After browsing several tutorials reagrding Zend2 /Doctrine 2 and Fieldsets i finally figured out the filedset/collction.
But new "fields" wont be added to the database table. Any changes in the existing elements are stored. Major Class Organization callsthe fieldset ActBusinessCountry:
Major Class Organization
class Organization {
protected $inputFilter;
/**
* #ORM\Id
* #ORM\Column(type="integer");
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $organizational;
/**
* #ORM\Column(type="string")
*/
protected $structure;
/**
* #param \Doctrine\Common\Collections\ArrayCollection
* #ORM\OneToMany(targetEntity="People\Entity\ActBusinessCountry",mappedBy="company",cascade={"persist", "merge", "refresh", "remove"})
*/
protected $organizaton_opcountry;
public function __construct()
{
$this->organizaton_opcountry = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #param \Doctrine\Common\Collections\ArrayCollection $organizaton_opcountry
*/
public function addOrganizaton_opcountry(Collection $organizaton_opcountry)
{
foreach ($organizaton_opcountry as $opcountry) {
$this->organizaton_opcountry->add($opcountry);
}
return $this->organizaton_opcountry;
}
public function removeOrganizaton_opcountry(Collection $organizaton_opcountry)
{
foreach ($organizaton_opcountry as $opcountry) {
$tag->setCompany(null);
$this->organizaton_opcountry->removeElement($opcountry);
}
}
/**
* #return Collection
*/
public function getOrganizaton_opcountry()
{
return $this->organizaton_opcountry;
}
Sub class/fieldset is ActBusinessCountry
class ActBusinessCountry {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* #ORM\ManyToOne(targetEntity="People\Entity\Organization",inversedBy="organizaton_opcountry")
* #ORM\JoinColumn(name="company_id", referencedColumnName="id")
*/
public $company;
/**
* #ORM\Column(type="string")
*/
public $country;
/**
* #ORM\Column(type="string")
*/
public $company_id;
/**
* Allow null to remove association
*/
public function setId($id = null)
{
$this->id = $id;
}
public function getId()
{
return $this->id;
}
public function getCompany()
{
return $this->company;
}
public function setCompany(Company $company = null)
{
$this->company = $company;
}
public function getCountry()
{
return $this->country;
}
public function setCountry($country)
{
$this->country = $country;
}
}
Organization Form:
$countrySelect = new ActBusinessCountryFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'organizaton_opcountry',
'options' => array(
'should_create_template' => true,
'use_as_base_fieldet' => true,
'count' => 1,
'allow_add' => true,
'target_element' => $countrySelect,
),
));
Fielset Elements:
class ActBusinessCountryFieldset extends Fieldset implements ObjectManagerAwareInterface
{
protected $objectManager;
public function __construct(ObjectManager $objectManager)
{
$this->setObjectManager($objectManager);
parent::__construct('fieldset');
$this ->setHydrator(new DoctrineHydrator($objectManager, 'People\Entity\ActBusinessCountry'))
->setObject(new \People\Entity\ActBusinessCountry());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'country',
'attributes' => array(
'class' => 'form-control input-small',
),
'options' => array(
'object_manager' => $this->getObjectManager(),
'target_class' => 'People\Entity\Country',
'value' => 'country',
'property' => 'country_name',
'class'=>'form-control',
'label_attributes' => array(
'class'=> 'col-sm-3 control-label',
),
),
));
}
public function getInputFilterSpecification()
{
return array(
'id' => array(
'required' => false
)
);
return array(
'country' => array(
'required' => true
)
);
}
Controller Flushing Part:
if ($this->request->isPost()) {
// Cancel button
if(isset($_POST['cancel'])) {
echo "<script>window.close();</script>";
}
$form->setData($this->request->getPost());
var_dump($this->request->getPost('organizaton_opcountry'));
var_dump($queryresult->getOrganizaton_opcountry());
//$queryresult->addOrganizaton_opcountry();
if ($form->isValid()) {
// Security request
if ($this->isAllowed('admin_res','admin_priv')) {
$form->bindValues();
$this->getEntityManager()->persist($queryresult);
$this->getEntityManager()->flush();
}
//echo "<script>window.close();</script>";
}
}
I am afraid, that i just missed a point. Though the post var_dump($this->request->getPost('organizaton_opcountry')); in the controller does output the following, after adding a third element and submitting:
array
0 =>
array
'id' => string '1' (length=1)
'country' => string 'Chad' (length=4)
1 =>
array
'id' => string '2' (length=1)
'country' => string 'Bermuda' (length=7)
2 =>
array
'id' => string '' (length=0)
'country' => string '(Not Specified)' (length=15)
Maybe you guys have an idea, or you have had the same problem before.
Thank you very much for any hint.
Kind regards,
David

Maybe u take a look at:
Saving a Doctine 2 Entity that contains an ObjectSelect element using Zend Form
Check the inputFilter in the Fieldset and add an inputfilter for the fieldset in the form e.g.:
$this->setValidationGroup(array(
'User' => array(
'name',
'role' // <- Fieldset
)
));

Related

Inserting data to database using zf3 and doctrine

i'm trying to insert data to database but submitted forms does nothing.
this is my service manager:
class AutosManager
{
/**
* Entity manager.
* #var Doctrine\ORM\EntityManager;
*/
private $entityManager;
/**
* Constructor.
*/
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
public function addNewAutos($data)
{
$autos = new Autos();
$autos->setTitle($data['title']);
$autos->setDescription($data['description']);
$currentDate = date('Y-m-d H:i:s');
$autos->setDateCreated($currentDate);
$this->entityManager->persist($autos);
$this->entityManager->flush();
}
this is my controller addAction
public function addAction()
{
// Create the form.
$form = new PostForm();
if ($this->getRequest()->isPost()) {
// Get POST data.
$data = $this->params()->fromPost();
// Fill form with data.
$form->setData($data);
if ($form->isValid()) {
// Get validated form data.
$data = $form->getData();
$this->AutosManager->addNewAutos($data);
return $this->redirect()->toRoute('retrieve');
}
}
return new ViewModel([
'form' => $form
]);
}
i can retrieve data from database to the index page but i cannot add. hope to find the solution.
this is my Autos Entity
namespace Retrieve\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="\Retrieve\Repository\AutosRepository")
* #ORM\Table(name="auto")
*/
class Autos
{
/**
* #ORM\Id
* #ORM\Column(name="id")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\Column(name="title")
*/
protected $title;
/**
* #ORM\Column(name="description")
*/
protected $description;
/**
* #ORM\Column(name="featured")
*/
protected $featured;
/**
* #ORM\Column(name="date_created")
*/
protected $dateCreated;
/**
* Returns ID of this post.
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Sets ID of this post.
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Returns title.
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Sets title.
* #param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Returns featured.
* #return integer
*/
public function getFeatured()
{
return $this->featured;
}
/**
* Sets featured.
* #param integer $featured
*/
public function setFeatured($featured)
{
$this->featured = $featured;
}
/**
* Returns post description.
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets post description.
* #param type $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* Returns the date when this post was created.
* #return string
*/
public function getDateCreated()
{
return $this->dateCreated;
}
/**
* Sets the date when this post was created.
* #param string $dateCreated
*/
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
}
}
hope this helps to find solution.
I found the problem: it was an inputfilter element I wasn't using that was authenticating in forms. But the solution only brings me to a different problem:
Notice: Undefined index: title in C:\xampp\htdocs\ameyaw\module\BusinessGhana\src\Service\AutosManager.php on line 38
Notice: Undefined index: description in C:\xampp\htdocs\ameyaw\module\BusinessGhana\src\Service\AutosManager.php on line 39
Notice: Undefined index: featured in C:\xampp\htdocs\ameyaw\module\BusinessGhana\src\Service\AutosManager.php on line 58
Message:
An exception occurred while executing 'INSERT INTO auto (title, description, featured, date_created) VALUES (?, ?, ?, ?)' with params [null, null, null, "2017-06-15 05:04:44"]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'title' cannot be null
this is my form and fieldset
use Zend\Form\Fieldset;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use BusinessGhana\Entity\Autos;
class AddFieldset extends Fieldset
{
protected $objectManager;
public function init()
{
$this->add([
'type' => 'text',
'name' => 'title',
'attributes' => [
'id' => 'autoTitle'
],
'options' => [
'label' => 'Title',
'display_empty_item' => true,
'empty_item_label' => 'Maximum of 60 characters',
],
]);
$this->add([
'type' => 'textarea',
'name' => 'description',
'attributes' => [
'id' => 'autoDescription'
],
'options' => [
'label' => 'Description',
'display_empty_item' => true,
'empty_item_label' => 'description',
],
]);
$this->add([
'type' => 'radio',
'name' => 'featured',
'attributes' => [
'id' => 'autoFeatured'
],
'options' => array(
'label' => 'Featured',
'value_options' => array(
array('value' => '0',
'label' => 'No',
'selected' => true,
'label_attributes' => array(
'class' => 'col-sm-2 btn btn-default',
),
),
array(
'value' => '1',
'label' => 'Yes',
'label_attributes' => array(
'class' => 'col-sm-2 btn btn-danger',
),
),
),
'column-size' => 'sm-12',
'label_attributes' => array(
'class' => 'col-sm-2',
),
),
]);
}
}
use Zend\Form\Form;
//use Zend\InputFilter\InputFilter;
class AddForm extends Form
{
public function init()
{
$this->add([
'name' => 'dependentForm',
'type' => AddFieldset::class,
]);
$this->add([
'type' => 'submit',
'name' => 'submit',
'attributes' => [
'value' => 'Submit',
],
]);
}
}
i know hydration can solve this problem but i dont know how to use it yet.

ZF2 inputfilter doctrine NoObjectExists editing object does not validate

So i got a ZF2 application, got a Form and a InputFilter in the InputFilter i have:
$this->add(
array(
'name' => 'email',
'required' => true,
'validators' => array(
array(
'name' => 'EmailAddress'
),
array(
'name' => 'DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $sm->get('doctrine.entitymanager.orm_default')->getRepository('YrmUser\Entity\User'),
'fields' => 'email'
),
),
),
)
);
works great, however when i edit a existing object and save it the NoObjectExists validator says a matching object is found so it doesn't validate.
Is there a solution to this problem?
Or should i just remove the validator on the edit form and catch the exception when a duplicate is inserted?
UPDATE:
How to use DoctrineModule\Validator\NoObjectExists in edit forms - Zend Framework 2 & Doctrine 2
is the same issue but the answer is to just remove the validator on editing, this off-course is not a solution. As you would still have to catch the exception thrown for when inserting a duplicate. I could do that no problem but what im asking for is a solution to make it work WITH NoObjectExists (otherwise whats the use of this validator if i have to catch the exception for duplicates anyway)
UPDATE, added other relevant code (my form and entity have more fields than this but i removed them to keep it readable on here)
FORM:
namespace YrmUser\Form;
use Zend\Form\Form;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use DoctrineORMModule\Stdlib\Hydrator\DoctrineEntity;
use YrmUser\Entity\User;
class UserForm extends Form
{
protected $objectManager;
/**
* __construct description
*
* #param String $name form name
*
* #return void
*/
public function __construct($name = null)
{
parent::__construct('new-user');
}
public function init()
{
$this->setHydrator(
new DoctrineHydrator($this->objectManager, 'YrmUser\Entity\User')
)->setObject(new User());
$this->setAttribute('method', 'post');
$this->add(
array(
'name' => 'email',
'attributes' => array(
'type' => 'email',
'placeholder' =>'Email',
),
'options' => array(
'label' => 'Email',
),
)
);
}
}
FILTER:
class UserFilter extends InputFilter
{
/**
* [__construct description]
*
* #param ServiceLocator $sm servicelocator
*/
public function __construct($sm)
{
$this->add(
array(
'name' => 'email',
'required' => true,
'validators' => array(
array(
'name' => 'EmailAddress'
),
array(
'name' => 'DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $sm->get('doctrine.entitymanager.orm_default')->getRepository('YrmUser\Entity\User'),
'fields' => 'email'
),
),
),
)
);
}
}
CONTROLLER ACTION:
public function editAction()
{
$id = (int) $this->params('id', null);
if (null === $id) {
return $this->redirect()->toRoute('manage-users');
}
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$formManager = $this->getServiceLocator()->get('FormElementManager');
$form = $formManager->get('UserForm');
$user = $em->find('YrmUser\Entity\User', $id);
$form->setInputFilter(new UserFilter($this->getServiceLocator()));
$form->bind($user);
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$em->persist($user);
$em->flush();
return $this->redirect()->toRoute('manage-users');
}
}
return array(
'form' => $form,
'id' => $id
);
}
ENTITY:
class User
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #ORM\Column(type="string", unique=true, length=255)
*/
protected $email;
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
*
* #param int $id user id
*
* #return void
*/
public function setId($id)
{
$this->id = (int) $id;
}
/**
* Get email.
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set email.
*
* #param string $email user email adress
*
* #return void
*/
public function setEmail($email)
{
$this->email = $email;
}
}
thanks in advance,
Yrm
I lately had the same issue on my project, I spend lot of time searching for a solution and I've finally found this module LosBase.
It uses two customs validators which extend DoctrineModule\Validator\NoObjectExists : NoEntityExists for Add action and NoOtherEntityExists for Edit action.
So I used this appraoch to resolve my problem. This is the solution I've made so far :
NoOtherEntityExists validator :
use Zend\Validator\Exception\InvalidArgumentException;
use DoctrineModule\Validator\NoObjectExists;
class NoOtherEntityExists extends NoObjectExists
{
private $id; //id of the entity to edit
private $id_getter; //getter of the id
private $additionalFields = null; //other fields
public function __construct(array $options)
{
parent::__construct($options);
if (isset($options['additionalFields'])) {
$this->additionalFields = $options['additionalFields'];
}
$this->id = $options['id'];
$this->id_getter = $options['id_getter'];
}
public function isValid($value, $context = null)
{
if (null != $this->additionalFields && is_array($context)) {
$value = (array) $value;
foreach ($this->additionalFields as $field) {
$value[] = $context[$field];
}
}
$value = $this->cleanSearchValue($value);
$match = $this->objectRepository->findOneBy($value);
if (is_object($match) && $match->{$this->id_getter}() != $this->id) {
if (is_array($value)) {
$str = '';
foreach ($value as $campo) {
if ($str != '') {
$str .= ', ';
}
$str .= $campo;
}
$value = $str;
}
$this->error(self::ERROR_OBJECT_FOUND, $value);
return false;
}
return true;
}
}
NoEntityExists validator :
use Zend\Validator\Exception\InvalidArgumentException;
use DoctrineModule\Validator\NoObjectExists;
class NoEntityExists extends NoObjectExists
{
private $additionalFields = null;
public function __construct(array $options)
{
parent::__construct($options);
if (isset($options['additionalFields'])) {
$this->additionalFields = $options['additionalFields'];
}
}
public function isValid($value, $context = null)
{
if (null != $this->additionalFields && is_array($context)) {
$value = (array) $value;
foreach ($this->additionalFields as $field) {
$value[] = $context[$field];
}
}
$value = $this->cleanSearchValue($value);
$match = $this->objectRepository->findOneBy($value);
if (is_object($match)) {
if (is_array($value)) {
$str = '';
foreach ($value as $campo) {
if ($str != '') {
$str .= ', ';
}
$str .= $campo;
}
$value = $str;
}
$this->error(self::ERROR_OBJECT_FOUND, $value);
return false;
}
return true;
}
}
Using this validators with inputFilter :
In my custom input filters, I added two methods : one to append the NoEntityExists validator, and the other to append the NoOtherEntityExists validator :
/**
* Appends doctrine's NoObjectExists Validator for Add FORM .
*
* #param \Doctrine\ORM\EntityRepository $repository
* #return \Zend\InputFilter\InputFilter
*/
public function appendAddValidator(EntityRepository $repository)
{
$this->add($this->getFactory()->createInput( array(
'name' => 'libellesite', //unique field name
'validators' => array(
array(
'name' => 'Netman\Form\NoEntityExists',//use namespace
'options' => array(
'object_repository' => $repository,
'fields' => 'libellesite',
'messages' => array(
'objectFound' => 'custom message here'
),
),
),
)
)));
return $this;
}
/**
* Appends doctrine's NoObjectExists Validator for EDIT FORM.
*
* #param \Doctrine\ORM\EntityRepository $repository
* #return \Zend\InputFilter\InputFilter
*/
public function appendEditValidator(EntityRepository $repository, $id)
{
$this->add($this->getFactory()->createInput( array(
'name' => 'libellesite',
'validators' => array(
array(
'name' => 'Netman\Form\NoOtherEntityExists',
'options' => array(
'object_repository' => $repository,
'fields' => 'libellesite',
'id'=>$id, //
'id_getter'=>'getCodesite',//getter for ID
'messages' => array(
'objectFound' => 'custom message here'
),
),
),
)
)));
return $this;
}
Controller :
In the addAction :
$repository = $em->getRepository('Entity\Name');
$form->setInputFilter($filter->appendAddValidator($repository));
In the editAction :
$id = $this->params('id', null);
$repository = $em->getRepository('Entity\Name');
$form->setInputFilter($filter->appendEditValidator($repository,$id));

Zend Framework 2 Doctrine 2 one-to-many checkbox hydration

I have a ManyToMany that I broke into OneToMany and ManyToOne relationship. I want to build a form that has checkboxes instead of collection, and I am using the 'DoctrineObject' hydrator, but it does not work and I don't know what is going wrong.
I removed from my code below all of the other not related fields.
Role Entity:
/**
* #orm\Entity
* #orm\Table(name="roles")
*/
class RolesEntity extends HemisEntity {
/**
* #orm\Id
* #orm\Column(type="integer");
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #orm\Column(name="role_code",type="string")
*/
protected $roleCode;
/**
* #orm\OneToMany(targetEntity="RolesPermissionsEntity", mappedBy="role", cascade={"persist"})
*/
protected $rolePermissions;
public function __construct()
{
$this->rolePermissions = new ArrayCollection();
}
public function setRolePermissions($rolePermissions)
{
$this->rolePermissions = $rolePermissions;
return $this;
}
public function addRolePermissions(Collection $rolePermissions)
{
foreach ($rolePermissions as $rolePermission) {
$rolePermission->setRole($this);
$this->rolePermissions->add($rolePermission);
}
}
public function removeRolePermissions(Collection $rolePermissions)
{
foreach ($rolePermissions as $rolePermission) {
$rolePermission->setRole(null);
$this->rolePermissions->removeElement($rolePermission);
}
}
public function getRolePermissions()
{
return $this->rolePermissions;
}
}
The ManyToMany table entity (it has more fields and so I broke it):
/**
* #orm\Entity
* #orm\Table(name="roles_permissions")
*/
class RolesPermissionsEntity extends HemisEntity {
/**
* #orm\Id
* #orm\Column(type="integer");
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #orm\ManyToOne(targetEntity="RolesEntity", inversedBy="rolePermissions")
* #orm\JoinColumn(name="role_id", referencedColumnName="id")
**/
protected $role;
/**
* #orm\ManyToOne(targetEntity="PermissionsEntity", inversedBy="permissionRoles")
* #orm\JoinColumn(name="permission_id", referencedColumnName="id")
**/
protected $permission;
public function setRole($role)
{
$this->role = $role;
return $this;
}
public function getRole()
{
return $this->role;
}
public function setPermission($permission)
{
$this->permission = $permission;
return $this;
}
public function getPermission()
{
return $this->permission;
}
}
My form look like this:
class RoleForm extends Form implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct('role');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new RolesEntity());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'roleCode',
'options' => array(
'label' => 'Role Code'
),
));
$this->add(array(
'name' => 'rolePermissions',
'type' => 'DoctrineModule\Form\Element\ObjectMultiCheckbox',
'options' => array(
'label' => 'Permissions',
'object_manager' => $objectManager,
'target_class' => 'Hemis\Fnd\PermissionsEntity',
'property' => 'permissionDesc'
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Submit',
),
));
}
public function getInputFilterSpecification()
{
return array(
'roleCode' => array(
'required' => false
),
'rolePermissions' => array(
'required' => true
)
);
}
}
The problem is that when I dump the $role it does not contains any rolePermissions and even that they are passed from the form they are just not hydrated into the object. I hope that my question is clear.
Any idea about what is wrong with my code or there is a better way to do that using checkboxes?
class RoleForm extends Form implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
// ...
$this->add(array(
'name' => 'rolePermissions',
'type' => 'Zend\Form\Element\Collection',
'options' => array(
'label' => 'Role Permissions',
'count' => 0,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Zend\Form\Fieldset',
'options' => array(
'use_as_base_fieldset' => true
),
'elements' => array(
// add form fields for the properties of the RolesPermissionsEntity class here
array(
'name' => 'id',
'type' => 'Zend\Form\Element\Hidden',
),
array(
'name' => 'role',
'type' => 'Zend\Form\Element\Checkbox',
// other options
),
// ...
),
),
),
));
// ...
}
// ...
}

How to paginate using Zend2/Doctrine combo (using the Doctrine provided paginator adapter)?

I've been looking for examples/guides on how to do what I asked.
I've found several examples and "best" I've found yet is this one => http://blog.loftdigital.com/blog/doctrine-plus-zf2-tips-pagination
2 problems
I'm not really sure if my paginator object contains the right number of records (I limited it to 5 records on my adapter object)
I don't know how to traverse the paginator object in my view file. it seems very complex. I did a print_r on the object enclosing the thing in a pre HTML tag and it's easily 20+K lines on my text editor (after copy/paste)
Can you please help?
thank you very much
my controller code based from the example (not really working but no zend/doctrine errors too. problem is that it gives me all the records instead of just 10)
$directory->populate($form->getData());
$adapter = new DoctrineAdapter(new ORMPaginator($directoryDao->searchStaffDirectory($this->getEntityManager()->createQueryBuilder(), $directory)));
$adapter->getItems(0, 5);
//var_dump($adapter->getItems(0, 5)); **//display the corrent number of records**
$paginator = new Paginator($adapter);
$paginator->setDefaultItemCountPerPage(5);
$page = (int)$this->params()->fromQuery("page");
if($page) $paginator->setCurrentPageNumber($page);
return array('staffList' => $paginator);
my DirectoryDAO class (the relevant parts)
public function searchStaffDirectory(QueryBuilder $queryBuilder, DirectoryModel $directory) {
$conditions = new Andx;
$queryBuilder
->select('directory')
->from('Directory\Model\DirectoryModel', 'directory');
if (strlen($directory->surnameSearch)) {
$conditions->add($queryBuilder->expr()->like('directory.surnameSearch', "'".preg_replace('/\s+/', '', $directory->surnameSearch)."%'"));
}
if (strlen($directory->surnameSoundsSearch)) {
$conditions->add($queryBuilder->expr()->like('directory.surnameSoundsSearch', preg_replace('/\s+/', '', $directory->surnameSoundsSearch)));
}
if (strlen($directory->firstnameSearch)) {
$conditions->add($queryBuilder->expr()->like('directory.firsnameSearch', preg_replace('/\s+/', '', $directory->firstnameSearch)));
}
if (strlen($directory->telephoneNumber)) {
$conditions->add($queryBuilder->expr()->like('directory.telephoneNumber', preg_replace('/\s+/', '', $directory->telephoneNumber)));
}
if (strlen($directory->departmentSearch)) {
$conditions->add($queryBuilder->expr()->like('directory.departmentSearch', preg_replace('/\s+/', '', $directory->departmentSearch)));
}
if (strlen($directory->roleSearch)) {
$conditions->add($queryBuilder->expr()->like('directory.roleSearch', preg_replace('/\s+/', '', $directory->roleSearch)));
}
if ($conditions->count()) {
$queryBuilder->andWhere($conditions);
}
$queryBuilder
->orderBy('directory.surname');
return $queryBuilder->getQuery();
}
my DirectoryModel class
<?php
namespace Directory\Model;
use Doctrine\ORM\Mapping;
use Zend\InputFilter\Factory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
/**
* #Mapping\Entity
* #Mapping\Table(name="staffdirectory_vw")
*/
class DirectoryModel {
/**
*
* #Mapping\Id
* #Mapping\Column(name="mytable_pk", type="integer", unique=true)
*/
protected $pk;
/**
*
* #Mapping\Column(name="mytable_id", type="string")
*/
protected $id;
/**
*
* #Mapping\Column(name="mytable_parent_id", type="string")
*/
protected $parentId;
/**
*
* #Mapping\Column(name="mytable_auth_code", type="string")
*/
protected $fan;
/**
*
* #Mapping\Column(name="mytable_full_name", type="string")
*/
protected $fullname;
/**
*
* #Mapping\Column(name="mytable_name_title", type="string")
*/
protected $title;
/**
*
* #Mapping\Column(name="mytable_first_pref_name", type="string")
*/
protected $firstname;
/**
*
* #Mapping\Column(name="mytable_surname", type="string")
*/
protected $surname;
/**
*
* #Mapping\Column(name="mytable_bldg_long_desc", type="string")
*/
protected $building;
/**
*
* #Mapping\Column(name="mytable_display_department", type="string")
*/
protected $department;
/**
*
* #Mapping\Column(name="mytable_alias", type="string")
*/
protected $email;
/**
*
* #Mapping\Column(name="mytable_alias_list", type="string")
*/
protected $emailList;
/**
*
* #Mapping\Column(name="mytable_entity_type", type="string")
*/
protected $entityType;
/**
*
* #Mapping\Column(name="mytable_org_heirarchy", type="string")
*/
protected $organisationalHeirarchy;
/**
*
* #Mapping\Column(name="mytable_role", type="string")
*/
protected $role;
/**
*
* #Mapping\Column(name="mytable_room", type="string")
*/
protected $room;
/**
*
* #Mapping\Column(name="mytable_tele_number", type="string")
*/
protected $telephoneNumber;
/**
*
* #Mapping\Column(name="mytable_tele_number_formats", type="string")
*/
protected $telephoneNumberFormats;
/**
*
* #Mapping\Column(name="mytable_tele_rank", type="string")
*/
protected $teleRank;
/**
*
* #Mapping\Column(name="mytable_url", type="string")
*/
protected $url;
/**
*
* #Mapping\Column(name="mytable_search_surname", type="string")
*/
protected $surnameSearch;
/**
*
* #Mapping\Column(name="mytable_surname_soundex", type="string")
*/
protected $surnameSoundsSearch;
/**
*
* #Mapping\Column(name="mytable_search_first_name", type="string")
*/
protected $firstnameSearch;
/**
*
* #Mapping\Column(name="mytable_search_department", type="string")
*/
protected $departmentSearch;
/**
*
* #Mapping\Column(name="mytable_search_role", type="string")
*/
protected $roleSearch;
/**
*
* #Mapping\Column(name="mytable_tele_directory", type="string")
*/
protected $teleDirectory;
protected $inputFilter;
/**
* Magic getter to expose protected properties.
*
* #param string $property
* #return mixed
*/
public function __get($property) {
return $this->$property;
}
/**
*
* Magic setter to save protected properties.
*
* #param string $property
* #param mixed $value
*/
public function __set($property, $value) {
$this->$property = $value;
}
/**
* Convert the object to an array.
*
* #return array
*/
public function getArrayCopy() {
return get_object_vars($this);
}
/**
* Populate from an array.
*
* #param array $data
*/
public function populate($data = array()) {
$this->pk = isset($data['pk']) ? $data['pk'] : null;
$this->id = isset($data['id']) ? $data['id'] : null;
$this->fan = isset($data['fan']) ? $data['fan'] : null;
$this->fullname = isset($data['fullname']) ? $data['fullname'] : null;
$this->surname = isset($data['surname']) ? $data['surname'] : null;
$this->building = isset($data['building']) ? $data['building'] : null;
$this->department = isset($data['department']) ? $data['department'] : null;
$this->email = isset($data['email']) ? $data['email'] : null;
$this->emailList = isset($data['emailList']) ? $data['emailList'] : null;
$this->entityType = isset($data['entityType']) ? $data['entityType'] : null;
$this->organisationalHeirarchy = isset($data['organisationalHeirarchy']) ? $data['organisationalHeirarchy'] : null;
$this->role = isset($data['role']) ? $data['role'] : null;
$this->room = isset($data['room']) ? $data['room'] : null;
$this->telephoneNumber = isset($data['telephoneNumber']) ? $data['telephoneNumber'] : null;
$this->telephoneNumberFormats = isset($data['telephoneNumberFormats']) ? $data['telephoneNumberFormats'] : null;
$this->teleRank = isset($data['teleRank']) ? $data['teleRank'] : null;
$this->url = isset($data['url']) ? $data['url'] : null;
$this->surnameSearch = isset($data['surnameSearch']) ? $data['surnameSearch'] : null;
$this->surnameSoundsSearch = isset($data['surnameSoundsSearch']) ? $data['surnameSoundsSearch'] : null;
$this->firstnameSearch = isset($data['firstnameSearch']) ? $data['firstnameSearch'] : null;
$this->departmentSearch = isset($data['departmentSearch']) ? $data['departmentSearch'] : null;
$this->roleSearch = isset($data['roleSearch']) ? $data['roleSearch'] : null;
$this->teleDirectory = isset($data['teleDirectory']) ? $data['teleDirectory'] : null;
}
public function setInputFilter(InputFilterInterface $inputFilter) {
throw new \Exception("Not used");
}
public function getInputFilter() {
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new Factory();
$inputFilter->add($factory->createInput(array(
'name' => 'surnameSearch',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringToUpper'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 30,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'surnameSoundsSearch',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringToUpper'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 30,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'firstnameSearch',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringToUpper'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 30,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'telephoneNumberSearch',
'required' => false,
'filters' => array(
array('name' => 'Int'),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'departmentSearch',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringToUpper'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 30,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'roleeSearch',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringToUpper'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 30,
),
),
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
I assume DoctrineAdapter is actually DoctrineORMModule\Paginator\Adapter\DoctrinePaginator just you imported it with a different name. If not, then this is the class you should be using.
Your controller should be:
$directory->populate($form->getData());
$adapter = new DoctrineAdapter(new ORMPaginator($directoryDao->searchStaffDirectory($this->getEntityManager()->createQueryBuilder(), $directory)));
$paginator = new Paginator($adapter);
$paginator->setItemCountPerPage(5);
$page = (int)$this->params()->fromQuery("page");
$paginator->setCurrentPageNumber($page);
return array('staffList' => $paginator);
No need to call getItems and when you cast $page to int then it will automatically default to the first page if no page parameter is passed.
Using the paginator in the view is more complex. First you need to implement a view script that renders the paginator. There are a number of example scripts in the ZF2 documentation which you can either use outright or base your own paginator off:
http://framework.zend.com/manual/2.2/en/modules/zend.paginator.usage.html#example-pagination-controls
To use the paginator in your actual view, you can iterate over it like any other query result to display your items:
<?php foreach($staffList as $staff): ?>
Firstname: <?php echo $staff->firstname; ?>
etc.
<?php endforeach; ?>
This will only display items currently for the current page that the paginator is on, which is what you want.
To display the paginator controls:
<?php echo $this->paginationControl($staffList, '<paginator type>', '<my paginator view script>', array('route' => '<route name>')); ?>
Paginator type can be: All, Elastic, Jumping, Sliding and determines how and what page numbers are displayed on the paginator controls. Sliding is the default and is most likely the best choice.

Form collections in SF2

Offers.php
/**
* #var \ZGoffers\MainBundle\Entity\OfferParameter
*
* #ORM\OneToMany(targetEntity="OfferParameter", mappedBy="offer", cascade={"all"})
*/
private $parameters;
OfferParameter.php
/**
* #var \ZGoffers\MainBundle\Entity\Offer
*
* #ORM\ManyToOne(targetEntity="Offer", inversedBy="offer", cascade={"all"})
*/
private $offer;
OfferType.php
class OfferType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('advertiser')
->add('name')
->add('url', 'text', array('label' => 'URL'))
->add('externalUrl', 'text', array('label' => 'External URL'))
->add('dailyCap', 'text', array('label' => 'Daily Cap'))
->add('parameters', 'collection', array(
'type' => new OfferParameterType(),
'allow_add' => true,
'allow_delete' => true
))
->add('active', 'choice', array(
'choices' => array(0 => 'Disabled', 1 => 'Enabled')
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'ZGOffers\MainBundle\Entity\Offer'
);
}
}
OfferParameterType.php
class OfferParameterType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('field')
->add('type', 'choice', array(
'choices' => array(
'=' => 'EQUALS',
'>' => 'IS GREATER THAN',
'>=' => 'IS GREATER THAN OR EQUALS',
'<' => 'IS LESS THAN',
'<=' => 'IS GREATER THAN OR EQUALS'
)
))
->add('value');
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'ZGOffers\MainBundle\Entity\OfferParameter'
);
}
}
Form Handling
public function process()
{
if ('POST' == $this->request->getMethod()) {
// bind form data
$this->form->bindRequest($this->request);
// If form is valid
if ($this->form->isValid() && ($offer = $this->form->getData()) instanceof Offer) {
foreach ($offer->getParameters() as $parameter) {
$parameter->setOffer($offer); // THIS SHOULDNT BE NEEDED
}
// save offer to the database
$this->entityManager->persist($offer);
$this->entityManager->flush();
return true;
}
}
return false;
}
My question is.... How the hell do you delete elements in form collections in SF2????
I have multiple forms that are just like this one in my project and it's really putting a halt to development :(
Thanks for all help!
You may need to do something like below :
->add('parameters', 'collection', array(
'type' => new OfferParameterType(),
'allow_add' => true,
'allow_delete' => true,
'attr'=>array('style'=>'display:none;')
))
That makes your whole OfferParameterType collection hidden.
Or in OfferParameterType apply same thing for each field like below :
->add('field',null, array('attr'=>array('style'=>'display:none;')))