2016-06-02 3 views
6

도와 주시면 감사하겠습니다. Symfony 2.x와 Doctrine 2.x을 사용하고 있으며 양식을 하나 만들고 싶습니다. 두 개의 엔티티로 구성되어 있습니다. 이 양식을 작성하여 데이터를 두 개의 교리 실체에 보관하고 싶습니다.Symfony2 임베디드 양식이 데이터를 데이터베이스에 저장하지 않습니다.

간단히하기 위해 예제를 만들었습니다. 다국어 웹샵은 영어와 프랑스어로 이름과 제품 설명이 필요합니다. 한 가지 양식을 사용하여 새 제품을 만들고 싶습니다. 이 생성 양식에는 Product 엔터티 (id, productTranslations, price, productTranslations)의 데이터와 ProductTranslation 엔터티 (ID, 이름, 설명, 언어, 제품)의 데이터가 포함됩니다. 결과 제품 작성 양식에는 다음 필드 (이름, 설명, 언어 (EN/FR), 가격)가 있습니다.

Product 및 ProductTranslation 엔티티는 양방향 일대 다 관계를 통해 서로 관련되어 있습니다. 관계의 소유 사이트가 ProductTranslation입니다.

양식을 제출 한 후 두 엔터티 (Product 및 ProductTranslation)에 데이터를 저장하려고합니다. 여기 그것이 일이 잘못되는 곳입니다. 나는 데이터를 유지할 수 없다.

제품 엔티티 :

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Component\Validator\Constraints as Assert; 

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

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

    /** 
    * @ORM\OneToMany(targetEntity="AppBundle\Entity\ProductTranslation", mappedBy="product") 
    */ 
    private $productTranslations; 

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

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

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

     return $this; 
    } 

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

    /** 
    * Set productTranslations 
    * 
    * @param \stdClass $productTranslations 
    * 
    * @return Product 
    */ 
    public function setProductTranslations($productTranslations) 
    { 
     $this->productTranslations = $productTranslations; 

     return $this; 
    } 

    /** 
    * Get productTranslations 
    * 
    * @return \stdClass 
    */ 
    public function getProductTranslations() 
    { 
     return $this->productTranslations; 
    } 

    /** 
    * Add productTranslation 
    * 
    * @param \AppBundle\Entity\ProductTranslation $productTranslation 
    * 
    * @return Product 
    */ 
    public function addProductTranslation(\AppBundle\Entity\ProductTranslation $productTranslation) 
    { 
     $this->productTranslations[] = $productTranslation; 

     return $this; 
    } 

    /** 
    * Remove productTranslation 
    * 
    * @param \AppBundle\Entity\ProductTranslation $productTranslation 
    */ 
    public function removeProductTranslation(\AppBundle\Entity\ProductTranslation $productTranslation) 
    { 
     $this->productTranslations->removeElement($productTranslation); 
    } 
} 

ProductTranslation 법인 :

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* ProductTranslation 
* 
* @ORM\Table(name="product_translation") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\ProductTranslationRepository") 
*/ 
class ProductTranslation 
{ 
    /** 
    * @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="description", type="text") 
    */ 
    private $description; 

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

    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Product", inversedBy="productTranslations",cascade={"persist"}) 
    * @ORM\JoinColumn(name="product_translation_id", referencedColumnName="id") 
    * 
    */ 
    private $product; 

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

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

     return $this; 
    } 

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

    /** 
    * Set description 
    * 
    * @param string $description 
    * 
    * @return ProductTranslation 
    */ 
    public function setDescription($description) 
    { 
     $this->description = $description; 

     return $this; 
    } 

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

    /** 
    * Set language 
    * 
    * @param string $language 
    * 
    * @return ProductTranslation 
    */ 
    public function setLanguage($language) 
    { 
     $this->language = $language; 

     return $this; 
    } 

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

    /** 
    * Set product 
    * 
    * @param \AppBundle\Entity\Product $product 
    * 
    * @return ProductTranslation 
    */ 
    public function setProduct(\AppBundle\Entity\Product $product = null) 
    { 
     $this->product = $product; 

     return $this; 
    } 

    /** 
    * Get product 
    * 
    * @return \AppBundle\Entity\Product 
    */ 
    public function getProduct() 
    { 
     return $this->product; 
    } 
} 

ProductType :

Thusfar, 나는 다음을 시도

<?php 

namespace AppBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolver; 
use Symfony\Component\Form\Extension\Core\Type\MoneyType; 

class ProductType extends AbstractType { 

    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) { 
     $builder->add('productTranslations', ProductTranslationType::class, array('label' => false, 'data_class' => null)); 
     $builder 
       ->add('price', MoneyType::class) 
     ; 
    } 

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

} 

ProductTranslationType :

<?php 

namespace AppBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolver; 
use Symfony\Component\Form\Extension\Core\Type\TextType; 
use Symfony\Component\Form\Extension\Core\Type\TextareaType; 
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; 

class ProductTranslationType extends AbstractType 
{ 
    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('name', TextType::class) 
      ->add('description', TextareaType::class) 
      ->add('language', ChoiceType::class, array('choices' => array('en' => 'EN', 'fr' => 'FR'))) 
     ; 
    } 

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

ProductController :

<?php 

namespace AppBundle\Controller; 

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use AppBundle\Entity\Product; 
use AppBundle\Form\ProductType; 
use AppBundle\Entity\ProductTranslation; 

/** 
* Product controller. 
* 
*/ 
class ProductController extends Controller { 

    /** 
    * Creates a new Product entity. 
    * 
    */ 
    public function newAction(Request $request) { 
     $em = $this->getDoctrine()->getManager(); 
     $product = new Product(); 

     $productTranslation = new ProductTranslation(); 

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

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

      $product->getProductTranslations()->add($product); 

      $productTranslation->setProduct($product); 

      $em->persist($productTranslation); 
      $em->flush(); 

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

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

오류 :

Warning: spl_object_hash() expects parameter 1 to be object, string given 
500 Internal Server Error - ContextErrorException 

도움말에 대한 요리 책을 보았습니다 : http://symfony.com/doc/current/book/forms.html#embedded-forms, 그러나 나는 그것을 얻을 수 없습니다.

업데이트 1

난 아직 내 질문에 대한 답을 발견하지 않았습니다. 아래의 코멘트에 이어 나는 협회를 살펴 보았다. ProductController를 조정하여 데이터베이스에 올바른 방식으로 데이터가 삽입되는지 테스트 할 수있게했습니다. 데이터가 올바르게 삽입되었지만 양식을 통해 삽입 할 수 없습니다. 잘만되면 누군가 나를 도울 수 있습니다.

ProductController : 이제 다음과 같은 오류 메시지가 얻을

<?php 

namespace AppBundle\Controller; 

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 

use AppBundle\Entity\Product; 
use AppBundle\Form\ProductType; 

/** 
* Creates a new Product entity. 
* 
*/ 
public function newAction(Request $request) { 
    $em = $this->getDoctrine()->getManager(); 
    $product = new Product(); 

    $productTranslation = new ProductTranslation(); 

    /* Sample data insertion */ 
    $productTranslation->setProduct($product); 
    $productTranslation->setName('Product Q'); 
    $productTranslation->setDescription('This is product Q'); 
    $productTranslation->setLanguage('EN'); 

    $product->setPrice(95); 
    $product->addProductTranslation($productTranslation); 

    $em->persist($product); 
    $em->persist($productTranslation); 
    $em->flush(); 
    /* End sample data insertion */ 

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

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

     $product->getProductTranslations()->add($product); 

     $productTranslation->setProduct($product); 

     $em->persist($productTranslation); 
     $em->flush(); 

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

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

:

Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\Product#$productTranslations", got "string" instead. 

업데이트를 2

ProductController newAction에서 변수 제품에서 위해 var_dump() 지속하기 전에 데이터는 다음과 같습니다 :

,
object(AppBundle\Entity\Product)[493] 
    private 'id' => null 
    private 'price' => float 3 
    private 'productTranslations' => 
    object(Doctrine\Common\Collections\ArrayCollection)[494] 
     private 'elements' => 
     array (size=4) 
      'name' => string 'abc' (length=45) 
      'description' => string 'alphabet' (length=35) 
      'language' => string 'en' (length=2) 
      0 => 
      object(AppBundle\Entity\ProductTranslation)[495] 
       ... 
+0

먼저 엔터티 매핑을 수정해야합니다. http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/association-mapping.html 및 올바른 연결 관리 방법 설정 http : // doctrine -orm.readthedocs.io/projects/doctrine-orm/ko/latest/reference/working-with-associations.html 컨트롤러에서 번역 된 제품을 유지하려고 시도하는 것보다 더 효과적입니다. – 1ed

+0

@ 1ed 나는 ProductTranslation 엔티티로 만든 실수를 언급했다고 생각합니다. 제품에 다 대일 주석을 추가하는 것을 잊어 버렸습니다. 그러나 그 결과는 여전히 동일합니다. –

+0

매핑을 변경 했습니까? 그렇다면'php app/console doctrine : schema : update --force'를 실행해야합니다. 그렇지 않으면 다른 제안이 없습니다. 오류 메시지가 많이 표시되지 않습니다. URL에 "app_dev.php"를 사용하면 어떻게됩니까? –

답변

2

나는 당신의 컨트롤러를 통해 찾고 있었고, 난 당신이 ProductTranslation을 지속하는 그러나 ProductTranslation 엔티티에 당신이 제품 엔티티의 관계에 cascade={"persist"}에 대한 주석을 누락 알 수 있습니다. 관련 엔터티를 저장하려면 유지하려는 엔터티에 지정해야합니다.

+0

실수를했습니다. 현재 버전에서는'cascade = { "persist"}'를 가지고 있지만 오류를 변경하지는 않습니다. –

4

오류 자체는 설명 적입니다. productTranslations은 Array 또는 arrayCollection이되어야합니다. 대신 "문자열"입니다.

그래서 제품의 생성자에서 : 세터를 들어

public function __construct() 
{ 
    $this->activityTranslations = new ArrayCollection(); 
    $this->productTranslations = new \Doctrine\Common\Collections\ArrayCollection(); 
} 

는/당신이 사용할 수있는 게터 :

public function addProductTranslation(AppBundle\Entity\ProductTranslation $pt) 
{ 
    $this->productTranslations[] = $pt; 
    $pt->setProduct($this); 
    return $this; 
} 


public function removeProductTranslation(AppBundle\Entity\ProductTranslation $pt) 
{ 
    $this->productTranslations->removeElement($pt); 
} 

public function getProductTranslations() 
{ 
    return $this->productTranslations; 
} 

편집 : Symfony2.3과 YAML에서 는, 여기 오브젝트 맵핑 구성은 나는 캐스케이드 지속성을 추가해야하는 강조점을 사용하고있다. 또한

//Product entity 
oneToMany: 
     productTranslations: 
     mappedBy: product 
     targetEntity: App\Bundle\...Bundle\Entity\ProductTranslation 
     cascade:  [persist] 

// ProductTranslation entity 
manyToOne: 
     product: 
     targetEntity: App\Bundle\..Bundle\Entity\Product 
     inversedBy: productTranslations 
     joinColumn: 
      name: product_id 
      type: integer 
      referencedColumnName: id 
      onDelete: cascade 

, 당신은 addremove 목표부터 제품 엔티티에서 필요 setProductTranslation() 세터를 교체하지 않으려면 참고.

class ProductType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
     { 
      $builder 
       ->add('productPrice','number',array('required' => false)) 
       ->add('productTranslations', 'collection', array(
        'type' => new ProducatTranslationType() 

        )) 

      ; 

     } 

당신이 당신의 formType에 모음을 지정하지 않는 이유를 모르겠어요 :

Edit2가 : 나는 컬렉션과 양식을 처리하는 방법 Symfony2에서

는 여기에있다. Symfony의 새로운 버전입니까?

+0

나의 실수. 나는 이미 이것을 발견하고 그것을 시정했다. 그러나 나는 그 질문을 잊어 버렸다. 한번보세요. –

+0

나는 당신의 편집을 보았다. 변경 후에도 동일한 오류가 발생한다는 것을 의미합니까? –

+0

예 동일한 오류가 발생합니다. 오류 메시지는 배열 문제라고 제안하지만 왜 문자열로 변환되는지 이해하지 못합니다. 나는 문제가 유효성 검사 후에 productcontroller에 있다고 생각한다. 객체는 문자열로 변환됩니다. –

2
$product->getProductTranslations()->add($product); 
$productTranslation->setProduct($product); 

당신이 여기 뭘 원하는지 나도 몰라,하지만 난 당신이 사용할 필요가 있다고 생각 :

$product->addProductTranslation($productTranslation); 
$productTranslation->setProduct($product); 

$ 제품 -> getProductTranslations을() 클래스의 ProductTranslation '의 ArrayCollection에를 반환하고 병합된다 그 배열은 'Product'유형의 값을가집니다.

다소 일관성이 없습니다. 내가 잘못하면 그 문장에서 무엇을하고 있는지 말할 수 있습니까?

감사합니다!

+0

입력 해 주셔서 감사합니다. 내 코드에 대해 걱정하지 마십시오. 데이터를 유지하면 문제가 남아 있습니다. 내 제품 변수의 var_dump를 만들었습니다. 내 문제를 해결하는 데 도움이되기를 바랍니다. –

관련 문제