Symfony2 - show one property in form, mapping by another property

145 views Asked by At

So I'm working on application to handle library maintenance. In my database I have three tables: Book, Category and BookCategory. In Book table I have two fields: BookID and BookTitle, in Category I have CategoryID and CategoryName and in BookCategory I have BookID (foreign key of Book(BookID)) and CategoryID (foreign key of Category(CategoryID). I autogenerated controllers and form by using php app/console generate:doctrine:crud --entity=AppBundle:EntityName

The point is, when I try to add new book to database, I can enter title of book and it's category by category ID (picture related), but I want to add new book using category name, not category ID, though it still should be mapped by category ID to BookCategory table. How to do it? How it looks like and how I want it to look like

Book.php

<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
* Book
*
* @ORM\Table(name="book")
* @ORM\Entity
*/
class Book
{
/**
 * @var integer
 *
 * @ORM\Column(name="book_id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $bookId;

/**
 * @var string
 *
 * @ORM\Column(name="title", type="string", length=50, nullable=false)
 */
private $title;

/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\ManyToMany(targetEntity="Category", inversedBy="bookId")
 * @ORM\JoinTable(name="book_category",
 *   joinColumns={
 *     @ORM\JoinColumn(name="book_id", referencedColumnName="book_id")
 *   },
 *   inverseJoinColumns={
 *     @ORM\JoinColumn(name="category_id", referencedColumnName="category_id")
 *   }
 * )
 */
private $categoryId;

/**
 * Constructor
 */
public function __construct()
{
    $this->categoryId = new \Doctrine\Common\Collections\ArrayCollection();
}


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

/**
 * Set title
 *
 * @param string $title
 * @return Book
 */
public function setTitle($title)
{
    $this->title = $title;

    return $this;
}

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


/**
 * Add categoryId
 *
 * @param \AppBundle\Entity\Category $categoryId
 * @return Book
 */
public function addCategoryId(\AppBundle\Entity\Category $categoryId)
{
    $this->categoryId[] = $categoryId;

    return $this;
}

/**
 * Remove categoryId
 *
 * @param \AppBundle\Entity\Category $categoryId
 */
public function removeCategoryId(\AppBundle\Entity\Category $categoryId)
{
    $this->categoryId->removeElement($categoryId);
}

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

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

}

Category.php

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Category
 *
 * @ORM\Table(name="category")
 * @ORM\Entity
 */
class Category
{
/**
 * @var integer
 *
 * @ORM\Column(name="category_id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $categoryId;

/**
 * @var string
 *
 * @ORM\Column(name="category_name", type="string", length=50, nullable=false)
 */
private $categoryName;

/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\ManyToMany(targetEntity="Book", mappedBy="categoryId")
 */
private $bookId;

/**
 * Constructor
 */
public function __construct()
{
    $this->bookId = new \Doctrine\Common\Collections\ArrayCollection();
}


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

/**
 * Set categoryName
 *
 * @param string $categoryName
 * @return Category
 */
public function setCategoryName($categoryName)
{
    $this->categoryName = $categoryName;

    return $this;
}

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

/**
 * Add bookId
 *
 * @param \AppBundle\Entity\Book $bookId
 * @return Category
 */
public function addBookId(\AppBundle\Entity\Book $bookId)
{
    $this->bookId[] = $bookId;

    return $this;
}

/**
 * Remove bookId
 *
 * @param \AppBundle\Entity\Book $bookId
 */
public function removeBookId(\AppBundle\Entity\Book $bookId)
{
    $this->bookId->removeElement($bookId);
}

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

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

BookType.php

<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;


class BookType extends AbstractType
{
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('title')
        ->add('categoryId')
    ;
}

/**
 * @param OptionsResolver $resolver
 */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'AppBundle\Entity\Book'
    ));
}
}
2

There are 2 answers

1
Medard On BEST ANSWER

This should do it:

$builder->add('categoryId', EntityType::class, array(
    'class' => 'AppBundle:Category',
    'choice_label' => 'categoryName',
    'expanded' => true,
));
0
Agedan On

Add category to the form as entity:

$builder
    ->add('title')
    ->add('category', 'entity', [
        'class' => Category::class,
        'choice_label' => 'categoryName'
    ])
;