Symfony 3.4 OneToMany SQLSTATE [23000]: нарушение ограничения целостности: 1048 Столбец «shopping_list_id» не может быть нулевым

Список покупок содержит много фруктов, а фрукты содержатся во многих списках покупок с дополнительным количеством полей.

Я создал объект Many-To-Many под названием ShoppingRow, поэтому ShoppingList имеет ManyToOne с ShoppingRow, а ShoppingRow имеет ManyToOne с Fruits.

В действии newAction списка покупок я получаю сообщение об ошибке: произошло исключение при выполнении «ВСТАВИТЬ В Shopping_row (количество, shopping_list_id, fruit_id) VALUES (?, ?, ?)» с параметрами [1, null, 11]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'shopping_list_id' cannot be null

исходный код:

Сущность списка покупок:

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

    /**
     * @var ShoppingList
     * @ORM\OneToMany(targetEntity="ShoppingRow", mappedBy="shoppingList", cascade={"persist", "remove"}, orphanRemoval=TRUE)
     */
    private $shoppingRows;

Тип списка покупок:

class ShoppingListType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('shoppingRows', CollectionType::class, array(
            'entry_type' => ShoppingRowType::class,
            'allow_add' => true,
        ))
        ;

    }/**

Объект ShoppingRow:

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


/**
 * @var ShoppingList
 *
 * @ORM\ManyToOne(targetEntity="ShoppingList", inversedBy="shoppingRows")
 * @ORM\JoinColumn(name="shopping_list_id", referencedColumnName="id", nullable=FALSE)
 */
 private $shoppingList;

 /**
  * @var Fruit
  *
  * @ORM\ManyToOne(targetEntity="Fruit", inversedBy="shoppingRows")
  * @ORM\JoinColumn(name="fruit_id", referencedColumnName="id", nullable=FALSE)
  */
  private $fruit;

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

ShoppingRowType:

class ShoppingRowType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('quantity')
        ->add('fruit', EntityType::class, array(
            'class' => 'AppBundle:Fruit',
            'choice_label' => 'name',
        ));
        ;
    }/**

Шоппинглистконтроллер:

/**
 * Creates a new shopping list entity.
 *
 * @Route("/new", name="shopping_list_new")
 * @Method({"GET", "POST"})
 */
public function newAction(Request $request)
{
$shoppingList = new ShoppingList();

$form = $this->createForm('AppBundle\Form\ShoppingListType', $shoppingList);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {

    $em = $this->getDoctrine()->getManager();
    $em->persist($shoppingList);
    $em->flush();

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

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

}


person duodecimo    schedule 06.05.2018    source источник


Ответы (1)


Вы должны установить связанные объекты вручную.

$shoppingRow->setShoppingList($shoppingList)

Так, например, если вы добавляете $shoppingRow в существующий $shoppingList, скажем, из формы, вам нужно взять этот список и добавить shoppingList в строку покупок. Есть много способов выяснить, какой это список, это ваша бизнес-модель — независимо от того, находитесь ли вы в списке и можете ли вы получить к нему доступ через преобразователь параметров, передав его идентификатор в URI или передав его через форму, скажем, ChoiceType:: класс, в котором вы запрашивали у БД существующие списки. Здесь мы мало чем можем вам помочь, вам нужно разобраться с этим самостоятельно.

Теперь, когда вы выясните, как добраться до нужного списка, вы можете либо поместить свой код в контроллер, либо сделать это в каком-то сервисе, который обрабатывает ваши списки покупок.

person Domagoj    schedule 06.05.2018
comment
где это сделать? - person duodecimo; 06.05.2018
comment
Везде, где у вас есть доступ к обеим сущностям, скорее всего, к контроллеру. Если это существующий список, вам нужно получить его с помощью EntityManager, если нет, вам нужно создать экземпляр и сохранить новый. Сегодня у меня будет время, чтобы объяснить это немного подробнее. - person Domagoj; 06.05.2018