Pavlin Petkov
Pavlin Petkov

Reputation: 1142

Symfony Could not determine access type when using EntityType form builder

I have 2 entities Cars and Parts and I want to be able to create new Car with multiple parts. For this reason I made this form in CarsType

$builder->
        add('make')->
        add('model')->
        add('travelledDistance')->
        add('parts',EntityType::class,array(
            'class' => Parts::class,
            'choice_label'=>"name",
            'query_builder' => function(PartsRepository $partsRepository){
                return $partsRepository->getAllPartsForCarsForm();
            },
            'multiple' => true
        ));

It gives me this error

Could not determine access type for property "parts" in class "AppBundle\Entity\Cars".

Here is my entity Cars

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Cars
 *
 * @ORM\Table(name="cars")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CarsRepository")
 */
class Cars
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Make", type="string", length=255)
     */
    private $make;

    /**
     * @var string
     *
     * @ORM\Column(name="Model", type="string", length=255)
     */
    private $model;

    /**
     * @var int
     *
     * @ORM\Column(name="TravelledDistance", type="bigint")
     */
    private $travelledDistance;

    /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Parts", inversedBy="cars")
     * @ORM\JoinTable(
     *  name="Parts_Cars",
     *  joinColumns={
     *      @ORM\JoinColumn(name="Part_Id", referencedColumnName="id")
     *  },
     *  inverseJoinColumns={
     *      @ORM\JoinColumn(name="Car_Id", referencedColumnName="id")
     *  })
     */
    private $parts;
    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set make
     *
     * @param string $make
     *
     * @return Cars
     */
    public function setMake($make)
    {
        $this->make = $make;

        return $this;
    }

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

    /**
     * Set model
     *
     * @param string $model
     *
     * @return Cars
     */
    public function setModel($model)
    {
        $this->model = $model;

        return $this;
    }

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

    /**
     * Set travelledDistance
     *
     * @param integer $travelledDistance
     *
     * @return Cars
     */
    public function setTravelledDistance($travelledDistance)
    {
        $this->travelledDistance = $travelledDistance;

        return $this;
    }

    /**
     * Get travelledDistance
     *
     * @return int
     */
    public function getTravelledDistance()
    {
        return $this->travelledDistance;
    }

    /**
     * @return mixed
     */
    public function getParts()
    {
        return $this->parts;
    }

}

And in case it matters here is my Parts entity

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Parts
 *
 * @ORM\Table(name="parts")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\PartsRepository")
 */
class Parts
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Name", type="string", length=255)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="Price", type="decimal", precision=10, scale=2)
     */
    private $price;

    /**
     * @var int
     *
     * @ORM\Column(name="Quantity", type="integer")
     */
    private $quantity;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Suppliers", inversedBy="parts")
     * @ORM\JoinColumn(name="Supplier_Id", referencedColumnName="id")
     */
    private $supplier;

    /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Cars", mappedBy="parts")
     */
    private $cars;

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

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Parts
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set price
     *
     * @param string $price
     *
     * @return Parts
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

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

    /**
     * Set quantity
     *
     * @param integer $quantity
     *
     * @return Parts
     */
    public function setQuantity($quantity)
    {
        $this->quantity = $quantity;

        return $this;
    }

    /**
     * Get quantity
     *
     * @return int
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * @return mixed
     */
    public function getSupplier()
    {
        return $this->supplier;
    }

    /**
     * @return mixed
     */
    public function getCars()
    {
        return $this->cars;
    }
    public function __toString()
    {
       return $this->getName();
    }

}

To save time here is the mapping between the 2 entities as well as the property parts in Cars

/**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Parts", inversedBy="cars")
     * @ORM\JoinTable(
     *  name="Parts_Cars",
     *  joinColumns={
     *      @ORM\JoinColumn(name="Part_Id", referencedColumnName="id")
     *  },
     *  inverseJoinColumns={
     *      @ORM\JoinColumn(name="Car_Id", referencedColumnName="id")
     *  })
     */
    private $parts;

and In Parts

 /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Cars", mappedBy="parts")
     */
    private $cars;

Here is the newAction in CarsController

/**
     * Creates a new car entity.
     *
     * @Route("/new", name="cars_new")
     * @Method({"GET", "POST"})
     */
    public function newAction(Request $request)
    {
        $carsRepository = $this->getDoctrine()->getManager()->getRepository('AppBundle:Cars');
        $car = new Cars();
        $form = $this->createForm('AppBundle\Form\CarsType', $car);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($car);
            $em->flush();

            return $this->redirectToRoute('cars_show', array('id' => $car->getId()));
        }

        return $this->render('cars/new.html.twig', array(
            'car' => $car,
            'form' => $form->createView(),
        ));
    }

My question is - How can I make it so that I can create new Car with several Parts and to save the relationship in the database so that when I retrieve the Car I can get the parts as well?

Basically how to make it so when I create a new car the relationship is saved in the parts_cars table which holds the id's?

Upvotes: 0

Views: 240

Answers (1)

Tony Chiboucas
Tony Chiboucas

Reputation: 5683

Let Doctrine do the JOIN work

Since you're doing a ManyToMany (EntityToEntity), the @JoinColumn directives are not needed.

Try removing it from the Cars entity.

Cars

/**
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Parts", inversedBy="cars")
 */
$parts

The only cases in which you need to specify the JoinColumns are:

  • Joining against self
  • Joining where the primary key is not the Entity ID.
  • Need to define fields in the join_table
    • Would be MUCH easier in this case to do A OneToMany J ManyToOne B

Since you're doing none of the above, Doctrine is having trouble accessing the Entities' IDENTITY fields for the join.

Upvotes: 1

Related Questions