Ожидаемое значение типа «SourcingBundle Entity RequestForEstimate» для поля ассоциации

#symfony

#symfony

Вопрос:

Я получаю следующую ошибку:

Ожидаемое значение типа «SourcingBundle Entity RequestForEstimate» для поля ассоциации «SourcingBundle Entity RequestForEstimateDetail # $ detail» вместо этого получило «Doctrine Common Collections ArrayCollection».

Я пытаюсь создать структуру, в которой есть объект RequestForEstimate, который может иметь несколько узлов RequestForEstimateDetails. Просто каждая строка в RequestForEstimateDetails будет содержать запрос на другой продукт и его детали, когда requestforest оценивает только общую информацию. Я новичок в Symfony, и мне трудно в тот момент, когда я хочу сохранить родительский элемент вместе с дочерними элементами в БД. Я следил за этим руководством по Symfony: как внедрить коллекцию форм

Вот мой код:

SourcingBundle Entity RequestForEstimate:

 <?php

namespace SourcingBundleEntity;

use DoctrineORMMapping as ORM;

/**
 * RequestForEstimate
 *
 * @ORMTable(name="request_for_estimate")
 * @ORMEntity(repositoryClass="SourcingBundleRepositoryRequestForEstimateRepository")
 */
class RequestForEstimate
{
    /**
     * @var int
     *
     * @ORMColumn(name="request_id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */

    private $id;

    /**
     * @var int
     *
     * @ORMColumn(name="status", type="integer")
     */
    private $status;

    /**
     * @var DateTime
     *
     * @ORMColumn(name="create_time", type="datetime")
     */
    private $createTime;

    /**
     * @var DateTime
     *
     * @ORMColumn(name="update_time", type="datetime")
     */
    private $updateTime;

    /**
     * @var string
     *
     * @ORMColumn(name="name", type="string", length=255)
     */
    private $name;
    /**
     * @ORMOneToMany(targetEntity="RequestForEstimateDetail", mappedBy="detail", cascade={"persist", "remove"}, orphanRemoval=true)
     */
    private $details;

    /**
     * Get id
     *
     * @return int
     */
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->details = new DoctrineCommonCollectionsArrayCollection();
    }

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

    /**
     * Set status
     *
     * @param integer $status
     *
     * @return RequestForEstimate
     */
    public function setStatus($status)
    {
        $this->status = $status;

        return $this;
    }

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

    /**
     * Set createTime
     *
     * @param DateTime $createTime
     *
     * @return RequestForEstimate
     */
    public function setCreateTime($createTime)
    {
        $this->createTime = $createTime;

        return $this;
    }

    /**
     * Get createTime
     *
     * @return DateTime
     */
    public function getCreateTime()
    {
        return $this->createTime;
    }

    /**
     * Set updateTime
     *
     * @param DateTime $updateTime
     *
     * @return RequestForEstimate
     */
    public function setUpdateTime($updateTime)
    {
        $this->updateTime = $updateTime;

        return $this;
    }

    /**
     * Get updateTime
     *
     * @return DateTime
     */
    public function getUpdateTime()
    {
        return $this->updateTime;
    }

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

        return $this;
    }

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

    /**
     * Add detail
     *
     * @param SourcingBundleEntityRequestForEstimateDetail $detail
     *
     * @return RequestForEstimate
     */
    public function addDetail(SourcingBundleEntityRequestForEstimateDetail $detail)
    {
        $this->details[] = $detail;
        return $this;
    }

    /**
     * Remove detail
     *
     * @param SourcingBundleEntityRequestForEstimateDetail $detail
     */
    public function removeDetail(SourcingBundleEntityRequestForEstimateDetail $detail)
    {
        $this->details->removeElement($detail);
    }

    /**
     * Get details
     *
     * @return DoctrineCommonCollectionsCollection
     */
    public function getDetails()
    {
        return $this->details;
    }

}
  

SourcingBundle Entity RequestForEstimateDetail:

 <?php

namespace SourcingBundleEntity;

use DoctrineORMMapping as ORM;

/**
 * RequestForEstimateDetail
 *
 * @ORMTable(name="request_for_estimate_detail")
 * @ORMEntity(repositoryClass="SourcingBundleRepositoryRequestForEstimateDetailRepository")
 */
class RequestForEstimateDetail
{
    /**
     * @var int
     *
     * @ORMColumn(name="request_detail_id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @ORMManyToOne(targetEntity="RequestForEstimate", inversedBy="details")
     * @ORMJoinColumn(name="request_id", referencedColumnName="request_id")
     */
    private $detail;
    /**
     * @var int
     *
     * @ORMColumn(name="product_id", type="integer")
     */
    private $productId;

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

    /**
     * @var string
     *
     * @ORMColumn(name="price_per_unit", type="decimal", precision=2, scale=0)
     */
    private $pricePerUnit;

    /**
     * @var string
     *
     * @ORMColumn(name="shipping_cost", type="decimal", precision=2, scale=0)
     */
    private $shippingCost;

    /**
     * @var string
     *
     * @ORMColumn(name="other_fees", type="decimal", precision=2, scale=0)
     */
    private $otherFees;


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

    /**
     * Set product
     *
     * @param integer $product
     *
     * @return RequestForEstimateDetail
     */
    public function setProduct($product)
    {
        $this->product = $product;

        return $this;
    }

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

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

        return $this;
    }

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

    /**
     * Set pricePerUnit
     *
     * @param string $pricePerUnit
     *
     * @return RequestForEstimateDetail
     */
    public function setPricePerUnit($pricePerUnit)
    {
        $this->pricePerUnit = $pricePerUnit;

        return $this;
    }

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

    /**
     * Set shippingCost
     *
     * @param string $shippingCost
     *
     * @return RequestForEstimateDetail
     */
    public function setShippingCost($shippingCost)
    {
        $this->shippingCost = $shippingCost;

        return $this;
    }

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

    /**
     * Set otherFees
     *
     * @param string $otherFees
     *
     * @return RequestForEstimateDetail
     */
    public function setOtherFees($otherFees)
    {
        $this->otherFees = $otherFees;

        return $this;
    }

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

    /**
     * Set requestId
     *
     * @param SourcingBundleEntityRequestForEstimate $requestId
     *
     * @return RequestForEstimateDetail
     */
    public function setRequestId(SourcingBundleEntityRequestForEstimate $requestId = null)
    {
        $this->requestId = $requestId;

        return $this;
    }

    /**
     * Get requestId
     *
     * @return SourcingBundleEntityRequestForEstimate
     */
    public function getRequestId()
    {
        return $this->requestId;
    }

    /**
     * Set productId
     *
     * @param SourcingBundleEntityProduct $productId
     *
     * @return RequestForEstimateDetail
     */
    public function setProductId(SourcingBundleEntityProduct $productId = null)
    {
        $this->productId = $productId;

        return $this;
    }

    /**
     * Get productId
     *
     * @return SourcingBundleEntityProduct
     */
    public function getProductId()
    {
        return $this->productId;
    }

    /**
     * Set detail
     *
     * @param SourcingBundleEntityRequestForEstimate $detail
     *
     * @return RequestForEstimateDetail
     */
    public function setDetail(SourcingBundleEntityRequestForEstimate $detail = null)
    {
        $this->detail = $detail;

        return $this;
    }

    /**
     * Get detail
     *
     * @return SourcingBundleEntityRequestForEstimate
     */
    public function getDetail()
    {
        return $this->detail;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->detail = new DoctrineCommonCollectionsArrayCollection();
    }

    /**
     * Add detail
     *
     * @param SourcingBundleEntityRequestForEstimate $detail
     *
     * @return RequestForEstimateDetail
     */
    public function addDetail(SourcingBundleEntityRequestForEstimate $detail)
    {
        $this->detail[] = $detail;

        return $this;
    }

    /**
     * Remove detail
     *
     * @param SourcingBundleEntityRequestForEstimate $detail
     */
    public function removeDetail(SourcingBundleEntityRequestForEstimate $detail)
    {
        $this->detail->removeElement($detail);
    }
}
  

Мой контроллер:

 <?php

namespace SourcingBundleController;

use SourcingBundleEntityRequestForEstimate;
use SourcingBundleEntityRequestForEstimateDetail;
use SourcingBundleFormTypeRequestForEstimateType;
use SourcingBundleFormTypeRequestForEstimateDetailType;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormExtensionCoreTypeDateType;
use SymfonyComponentFormExtensionCoreTypeCollectionType;
use SymfonyComponentFormExtensionCoreTypeSubmitType;
use SensioBundleFrameworkExtraBundleConfigurationRoute;

class RequestForEstimateController extends Controller
{
/**
     * @Route("sourcing/request-for-estimate", name="request_for_estimate")
     */
    public function addRequest(Request $request)
    {

        $RequestForEstimate = new RequestForEstimate();
        $form = $this->createForm(RequestForEstimateType::class, $RequestForEstimate);

        $form->handleRequest($request);
        if ($form->isSubmitted() amp;amp; $form->isValid()) {

            $request = $form->getData();

            foreach($form->get('details')->getData() as $detail)
            {
                $request->addDetail($detail);
            }

            print_r($form->get('details')->getData());
            $request->setStatus(0);
            $request->setupdateTime(new DateTime());
            $request->setcreateTime(new DateTime());
            $em = $this->getDoctrine()->getManager();
            $em->persist($request);
            $em->flush();

            return $this->redirectToRoute('RequestsForEstimate');
        }


        return $this->render('sourcing/requestforestimate/create.html.twig', array(
           'form' => $form->createView(),
        ));



    }
}
  

Мои формы:

 <?php
namespace SourcingBundleFormType;

use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolver;
use SymfonyComponentFormExtensionCoreTypeTextareaType;
use SymfonyComponentFormExtensionCoreTypeEmailType;
use SymfonyComponentFormExtensionCoreTypeDateTimeType;
use SymfonyComponentFormExtensionCoreTypeCollectionType;
use SymfonyComponentFormExtensionCoreTypeSubmitType;

class RequestForEstimateType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name');
        $builder->add('details', CollectionType::class, array(
            'entry_type' => RequestForEstimateDetailType::class,
            'allow_add'     => true,
            'allow_delete' => true,
            'by_reference' => false,

        ));
        $builder->add('save', SubmitType::class, array('label' => 'Create Request'));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'SourcingBundleEntityRequestForEstimate',
        ));
    }
}



<?php
namespace SourcingBundleFormType;

use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolver;

class RequestForEstimateDetailType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('quantity');  
        $builder->add('pricePerUnit'); 
        $builder->add('shippingCost'); 
        $builder->add('otherFees'); 
        // $builder->add('product'); 


    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'SourcingBundleEntityRequestForEstimateDetail',
        ));
    }
}
  

Ответ №1:

В RequestForEstimateDetail методе getter / setter поля detail предназначены для управления самой коллекцией (методы добавления / удаления предназначены для одного элемента коллекции), поэтому измените метод getter / setter для обработки ArrayCollection объекта.

В качестве примера:

RequestForEstimateDetail

 /**
 * Set detail
 *
 * @param DoctrineCommonCollectionsArrayCollection an array of $detail
 *
 * @return RequestForEstimateDetail
 */
public function setDetail(DoctrineCommonCollectionsArrayCollection $detail = null)
{
    $this->detail = $detail;

    return $this;
}

/**
 * Get detail
 *
 * @return DoctrineCommonCollectionsArrayCollection
 */
public function getDetail()
{
    return $this->detail;
}
  

Надеюсь, это поможет

Комментарии:

1. Спасибо за ваш ответ, но он ничего не изменил. Все та же ошибка. Из того, что я вижу, вы только что изменили аннотацию doctrine, верно?

2. Привет, я предлагаю изменить сигнатуру методов, чтобы принять объект ArrayCollection.

3. Не могли бы вы привести пример?

Ответ №2:

Что ж, существующий метод addDetail в сущности RequestForEstimate сделал свое дело:

 public function addDetail(SourcingBundleEntityRequestForEstimateDetail $detail)
{
    $this->details->add($detail);
    $detail->setDetail($this);
    return $this;
}