2

I have a category table and product table. The categories are listed in product form in a drop down select box. When i edit a product then category saved in product table should be auto selected in category drop down at product edit form (selected="selected").

I have already tried empty_data and empty_value but they does not work.

I am searching for the solution since 2 days but could not find any tutorial or such example. I will be really thankful if someone can refer me a tutorial or can see below code to sort out the problem:

Controller

<?php

// src/Scsp/CmsBundle/Controller/ProductController.php

namespace Scsp\CmsBundle\Controller;    
use Scsp\CmsBundle\Entity\CategoryEntity;
use Scsp\CmsBundle\Entity\ProductEntity;
use Scsp\CmsBundle\Form\ProductForm;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\HttpFoundation\Session\Session;

class ProductController extends Controller {     

    public function editAction($id, $request) {

        $em = $this->getDoctrine()->getManager();
        $product = $em->getRepository('ScspCmsBundle:ProductEntity')->find($id);

        if (!$product){ 
            throw $this->createNotFoundException('No product found for id ' . $id);
        }

        $productForm=new ProductForm($id);

        $form = $this->createForm($productForm, $product, array(            
            'attr' => array('class' => 'form-horizontal')
        ));

        $form->handleRequest($request);

        if ($request->isMethod('POST') && $form->isValid()) {

                $product->setCategoryid(3);                

                $em->persist($product);
                $em->flush();                
                $this->session->getFlashBag()->add('success', $product->getProducts() . ' successfully edited!');
                return $this->redirect($this->generateUrl('scsp_cms_products', array('action' => 'list', 'id' => 0)));           
        }

        return $this->render('ScspCmsBundle:Default:form.html.twig', array(
                    'form' => $form->createView(),
                    'page_title' => 'Edit product',
                    'type' => 'products',
                    'id' => $id
        ));
    }

}

Product Entity:

<?php

// src/Scsp/CmsBundle/Entity/ProductEntity.php

namespace Scsp\CmsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="Scsp\CmsBundle\Repository\ProductRepository")
 * @ORM\Table(name="products")
 */
class ProductEntity {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $products;

    /**
     * @ORM\Column(type="integer")
     * @ORM\ManyToOne(targetEntity="CategoryEntity", inversedBy="products")
     * @ORM\JoinColumn(name="categoryid", referencedColumnName="id")
     */
    protected $categoryid;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId() {
        return $this->id;
    }

     /**
     * Set id
     *
     * @param string $id
     * @return Id
     */
    public function setId($id) {
        $this->id = $id;

        return $this;
    }

    /**
     * Set products
     *
     * @param string $products
     * @return ProductEntity
     */
    public function setProducts($products)
    {
        $this->products = $products;

        return $this;
    }

    /**
     * Get products
     *
     * @return string 
     */
    public function getProducts()
    {
        return $this->products;
    }

    /**
     * Set categoryid
     *
     * @param integer $categoryid
     * @return ProductEntity
     */
    public function setCategoryid($categoryid)
    {
        $this->categoryid = $categoryid;

        return $this;
    }

    /**
     * Get categoryid
     *
     * @return integer 
     */
    public function getCategoryid()
    {
        return $this->categoryid;
    }
}

Category Entity:

<?php

// src/Scsp/CmsBundle/Entity/CategoryEntity.php

namespace Scsp\CmsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="Scsp\CmsBundle\Repository\CategoryRepository")
 * @ORM\Table(name="categories")
 */
class CategoryEntity {

    /**
     * @ORM\OneToMany(targetEntity="ProductEntity", mappedBy="categorid")
     */
    protected $products;

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $categories;

    public function __construct(){
        $this->products = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId() {
        return $this->id;
    }

     /**
     * Set id
     *
     * @param string $id
     * @return Id
     */
    public function setId($id) {
        $this->id = $id;

        return $this;
    }

    /**
     * Set categories
     *
     * @param string $categories
     * @return Categories
     */
    public function setCategories($categories) {
        $this->categories = $categories;

        return $this;
    }

    /**
     * Get categories
     *
     * @return string 
     */
    public function getCategories() {
        return $this->categories;
    }

    public function __toString() {
        return $this->getCategories();
    }

    /**
     * Add products
     *
     * @param \Scsp\CmsBundle\Entity\ProductEntity $products
     * @return CategoryEntity
     */
    public function addProduct(\Scsp\CmsBundle\Entity\ProductEntity $products)
    {
        $this->products[] = $products;

        return $this;
    }

    /**
     * Remove products
     *
     * @param \Scsp\CmsBundle\Entity\ProductEntity $products
     */
    public function removeProduct(\Scsp\CmsBundle\Entity\ProductEntity $products)
    {
        $this->products->removeElement($products);
    }

    /**
     * Get products
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getProducts()
    {
        return $this->products;
    }
}

Product Form:

<?php

// src/Scsp/CmsBundle/Form/ProductForm.php

namespace Scsp\CmsBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use \Scsp\CmsBundle\Entity\ProductEntity;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormInterface;

class ProductForm extends AbstractType
{
    private $id;


    public function __construct($id) {
        $this->id=$id;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        if($this->id>0){

            $builder->add('id', 'text', 
                    array(
                        'label' => false,                        
                        'attr' => array(
                                    'class' => 'form-control',
                                    'readonly' => 'readonly'
                                  )
                        )
            ); 
        }       

        $builder     
            ->add('products', 'text', 
                    array(
                        'label' => false,                        
                        'max_length' => 100,
                        'attr' => array(
                                    'class' => 'form-control',
                                    'autocomplete' => 'off'
                                  )
                        )
                 )

            ->add('categoryid', 'entity', array(
                'label' => false,
                'class' => 'ScspCmsBundle:CategoryEntity',
                'property' => 'categories',
                'data'=>$builder->getData()->getCategoryId(),
                'attr' => array(
                )
                    )
            )

            ->add('save', 'submit',array(
                    'attr' => array(
                            'formnovalidate' => 'formnovalidate',
                            'class' => 'btn btn-primary',
                            'label' => 'Save Changes'
                        )
                    )   
                 )

            ->getForm();
    }

    public function getName()
    {
        return 'products';
    }    

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'empty_data' => 'Scsp\CmsBundle\Entity\CategoryEntity'
        ));
    }        

}
Salman
  • 49
  • 1
  • 10

3 Answers3

1
categoryid 

is not an entity, so you must to add a property called category in ProductEntity and stablish the relation ManyToOne there, the code:

/**
* @ORM\Column(type="integer")
* @ORM\ManyToOne(targetEntity="CategoryEntity", inversedBy="products")
* @ORM\JoinColumn(name="categoryid", referencedColumnName="id")
*/
protected $categoryid;

must be replaced by:

/**
* @ORM\Column(name="categoryid", type="integer")
*/
protected $categoryid;

/**
* @var CategoryEntity
* @ORM\ManyToOne(targetEntity="CategoryEntity", inversedBy="products")
* @ORM\JoinColumn(name="categoryid", referencedColumnName="id")
*/
protected $category;

//Here generate the get and the set customized
 /**
 * @return CategoryEntity
 */
public function getCategory()
{
    return $this->category;
}

/**
 * @param CategoryEntity $category
 * @return $this
 */
public function setCategory($category)
{
    //this is the owning side
    //all changes will be detected
    //in this side by doctrine
    $category->addProduct($this);
    $this->category= $category;

    //The line below is important to set the categoryid 
    //field in the product table
    $this->setCategoryid($category->getId());
    return $this;
}

Now in the Product Form replace:

->add('categoryid', 'entity', array(
            'label' => false,
            'class' => 'ScspCmsBundle:CategoryEntity',
            'property' => 'categories',
            'data'=>$builder->getData()->getCategoryId(),
            'attr' => array(
            )
                )
        )

by:

 ->add('category', 'entity', array(
            'label' => false,
            'class' => 'ScspCmsBundle:CategoryEntity',
            'property' => 'categories',
            'attr' => array(
            )
                )
        )

That's all, enjoy it!

0

I see many things wrong in your form type, nonetheless, what are you looking for is the data option in the field definition:

->add('categoryid', 'entity', 
        array(
            'label' => false,
            'class' => 'ScspCmsBundle:CategoryEntity',
            'property' => 'categories',
            'data' => $builder->getData()->getCategoryId()
        )
     )

This data field must contain the select value property, which is the categoryId, at least when using an entity field type as normal. I don't know if this will work with you current setup!

Alberto Fernández
  • 1,568
  • 13
  • 22
  • @Amberto I tried but still would not achieve the goal. Can you please explain $options->getData()->getCategoryId() with some example or code? – Salman Apr 01 '14 at 14:10
  • Sorry, there was a typo in my anser. It's not `$options` but `$builder`. Doing a `$builder->getData()` will give you the original data passed to the form, for example, when you do `$this->buildForm(new MyType(), $data)`, `$builder->getData()` will return exactly the data passed `$data`. In your case a `Product` instance; then you can use `$data->getCategoryId()`. – Alberto Fernández Apr 01 '14 at 14:24
  • I am new to symfony 2 and appropriate your kind help. I have updated the Product Form in original post (see above). $builder->getData()->getCategoryId() returns the categoryid saved in product table but in drop down list that category is still not selected in product's edit action. – Salman Apr 01 '14 at 16:38
0

I have a solution for Symfony 1.4.18.

The key is use jQuery.

You can view a detail explanation (including images) in my blog (in Spanish) here: http://symfonyandme.com/2013/10/09/como-usar-select-dependientes-en-symfony-1-4-con-tres-tablas/

And the same solution here: Symfony 1.4 with AJAX jQuery. How can I improve the AJAX's function that contains a select box which depends on another select box?

Then you would work for adjust this example for Symfony 2

Community
  • 1
  • 1
Jorge H
  • 306
  • 1
  • 4
  • 19