Chathura86
Chathura86

Reputation: 15

ZF2 Form / Doctrine Self Referring Relation Dropdown

First of all thanks for looking into this. I'm building a form to add categories to the db table and these categories can have a parent category (self referring). there is a dropdown to select the parent category. I'm using ZF2 and Doctrine 2 to build this form. Everything works fine but the only issue i have is that on the edit page, the parent category dropdown it shows the current category as well. I'd like to know how to exclude it from the dropdown. I'm posting some of my codes below. To keep it simple i removed some unrelated lines and shorten some names.

I defined the self referring relationship on the model

//Category model
use Doctrine\ORM\Mapping as ORM;
Class Category {
/**
 *
 * @var integer
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
protected $id;
.....
.....
/**
 * Parent category if available
 * @var self 
 * @ORM\OneToOne(targetEntity="Category")
 * @ORM\JoinColumn(name="parent", referencedColumnName="id", nullable=true)
 */
protected $parent;

On the form I have a dropdown listing all the categories

$parent = new \DoctrineModule\Form\Element\ObjectSelect('parent');
$parent->setOptions(array(
        'label' => 'Parent Category',
        'class' => '',
        'object_manager' => $this->em,
        'target_class' => \Data\Entity\Category::class,
        'property' => 'name',
        'display_empty_item' => true,
        'empty_item_label'   => '- Select Category -',
        'required' => false
    ))->setAttributes(array(
        'class' => 'form-control'
    ));

On the edit controller i load the form and and bind it to the db entry

public function editAction()
{
    //get id from url
    $id = $this->params()->fromRoute('id', 0);

    $request = $this->getRequest();

    //load selected category from database
    $category = $this->em->getRepository(\Data\Entity\Category::class)->find($id);

    //create form
    $form = new Form\Category($this->em);

    //bind selected category to form
    $form->bind($category);

    ......
}

Thanks.

Upvotes: 0

Views: 120

Answers (1)

Garry
Garry

Reputation: 1485

You need to pass the category id of the category being edited to the form and set object selects search params to pass the id to the entity repository. You will then need to create a search query in the repository to exclude the category id from being returned in the search results.

You can pass the category id to the form with a simple setter.

protected $categoryId;

public function setCategoryId($categoryId)
{
    $this->categoryId = $categoryId;
}

In your form you will need something like

$parent->setOptions(array(
            'label' => 'Parent Category',
            'class' => '',
            'object_manager' => $this->em,
            'target_class' => \Data\Entity\Category::class,
            'property' => 'name',
            'is_method' => true,
            'find_method' => array(
                'name' => 'findCategories',
                'params' => array(
                    'searchParams' => array('id' => $this->categoryId),
                ),
            ),
            'display_empty_item' => true,
            'empty_item_label' => '- Select Category -',
            'required' => false
        ))->setAttributes(array(
            'class' => 'form-control'
        ));

and in your categories repository

public function findCategories($searchParams)
    {
        $builder = $this->getEntityManager()->createQueryBuilder();
        $builder->select('c')
                ->from(\Data\Entity\Category::class, 'c')
                ->where('c.id != ?1')
                ->setParameter(1, $searchParams['id'])
                ->orderBy('c.category', 'ASC');

        return $builder->getQuery()->getResult(Query::HYDRATE_OBJECT);
    }

note the orderBy is optional.

I hope this makes sense.

Upvotes: 1

Related Questions