2

相互にマッピングされるように設定された2つのエンティティ(PlanとPricingTier)があります。PricingTierはoneToManyになるように設定され、PlanはmanyToOneになるように設定されています。マップされた列はPlanエンティティにあります。プランデータベーステーブルには、2つのテーブル/エンティティをリンクするpricing_tier_id列があります。

新しい計画を作成するフォームがあります。フォームはTwigファイルで適切に生成され、投稿されると$ request-> request-> getAll(); 投稿された値の配列を返します。配列では、pricingTierIdが選択した価格帯のIDに明確に設定されていることがわかります。私が以下を実行するとき:

$form->bind($request);
$newPlan = $form->getData();
$em = $this->getDoctrine()->getEntityManager();
$em->perist($newPlan);
$em->flush();

Pricing_tier_idをNULLにすることはできないという例外がスローされます。$ newPlan変数に対してvar_dump()を実行しましたが、マップされた価格帯のオブジェクトを含むオブジェクトが返されるように見えます。

誰かが私がこのエラーを受け取る理由の解決策を提案できますか?関連するコードとエラーは以下のとおりです。

PlanController.php

namespace etrak\CustomerServiceBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use etrak\OnlineOrderProcessingBundle\Entity\Plan;
use etrak\OnlineOrderProcessingBundle\Entity\PricingTier;
use etrak\CustomerServiceBundle\Form\Type\PlanType;
use Symfony\Component\HttpFoundation\Request;

class PlanController extends Controller
{
    public function indexAction($name)
    {
        return $this->render('etrakCustomerServiceBundle:Default:index.html.twig', array('name' => $name));
    }

    public function addPlanAction(Request $request)
    {
        // Set up a new Plan object
        $plan = new Plan();

        $form = $this->createForm(new PlanType(), $plan);

        // Check to see if the form has been submitted
        if ($request->isMethod('POST')) {
            $form->bind($request);
            var_dump($request->request->all()); die();
            // Validate the form
            if ($form->isValid()) {
                $newPlan = $form->getData();
//var_dump($newPlan->getPricingTierId()); die();
                $em = $this->getDoctrine()->getEntityManager();
                $em->persist($newPlan);
                $em->flush();
            }
        }

        return $this->render('etrakCustomerServiceBundle:Plan:new.html.twig', array("form" => $form->createView()));
    }
}

PlanType.php

namespace etrak\CustomerServiceBundle\Form\Type;

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

class PlanType extends AbstractType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'etrak\OnlineOrderProcessingBundle\Entity\Plan',
            'cascade_validation' => true,
        ));


    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $termsConditionsArray = array("1 Year Contract" => "1 Year Contract", "2 Year Contract" => "2 Year Contract");
        $billingFrequencyArray = array("1" => "Monthly", "6" => "6 Months", "12" => "Yearly");

        // Create the form
        $builder->add('name', 'text', array('label' => 'Plan Name: ', 'required' => false));
        $builder->add('description', 'text', array('label' => 'Plan Description: '));
        $builder->add('termsConditions', 'choice', array('choices' =>                 $termsConditionsArray, 'label' => 'Terms & Conditions'));
        $builder->add('amount', 'text', array('label' => 'Plan Price: '));
        $builder->add('affinity', 'choice', array('choices' => array('0' => 'Yes', '1' => 'No'), 'label' => 'Affinity? ', 'expanded' => true));
        $builder->add('deactivationFee', 'text', array('label' => "Deactivation Fee: "));
        $builder->add('recurringInMonths', 'choice', array('choices' => $billingFrequencyArray, 'label' => 'Billing Frequency: '));
        $builder->add('pricingTierId', 'entity', array(
        'class' => 'etrakOnlineOrderProcessingBundle:pricingTier',
        'property' => 'name',
        'label' => "Select Pricing Tier: "
    ));
        $builder->add('activeStartDate', 'datetime', array('label' => "Effective Start Date: "));
        $builder->add('activeEndDate', 'datetime', array('label' => "Effective End Date: "));
    }

    public function getName()
    {
        return 'plan';
    }
}

Plan.php 名前空間etrak\OnlineOrderProcessingBundle \ Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Plan
 */
class Plan
{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * @var string
     */
    private $description;

    /**
     * @var string
     */
    private $termsConditions;

    /**
     * @var boolean
     */
    private $active;

    /**
     * @var decimal
     */
    private $amount;

    /**
     * @var boolean
     */
    private $affinity;

    /**
     * @var integer
     */
    private $deactivationFee;

    /**
     * @var integer
     */
    private $gracePeriodDays;

    /**
     * @var integer
     */
    private $recurringInMonths;

    /**
     * @var integer
     */
    private $pricingTierId;

    /**
     * @var date
     */
    private $activeStartDate;

    /**
     * @var date
     */
    private $activeEndDate;

    /**
     * @var \etrak\OnlineOrderProcessingBundle\Entity\PricingTier
     */
    private $pricingTier;


    /**
     * Set pricingTier
     *
     * @param \etrak\OnlineOrderProcessingBundle\Entity\PricingTier $pricingTier
     * @return Plan
     */
    public function setPricingTier(\etrak\OnlineOrderProcessingBundle\Entity\PricingTier $pricingTier = null)
    {
        $this->pricingTier = $pricingTier;

        return $this;
    }

    /**
     * Get pricingTier
     *
     * @return \etrak\OnlineOrderProcessingBundle\Entity\PricingTier 
     */
    public function getPricingTier()
    {
        return $this->pricingTier;
    }

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

    /**
     * Set name
     *
     * @param string $name
     * @return Plan
     */
    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 Plan
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

    /**
     * Set termsConditions
     *
     * @param string $termsConditions
     * @return Plan
     */
    public function setTermsConditions($termsConditions)
    {
        $this->termsConditions = $termsConditions;

        return $this;
    }

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

    /**
     * Set active
     *
     * @param boolean $active
     * @return Plan
     */
    public function setActive($active)
    {
        $this->active = $active;

        return $this;
    }

    /**
     * Get active
     *
     * @return boolean 
     */
    public function getActive()
    {
        return $this->active;
    }

    /**
     * Set amount
     *
     * @param decimal $amount
     * @return Plan
     */
    public function setAmount($amount)
    {
        $this->amount = $amount;

        return $this;
    }

    /**
     * Get amount
     *
     * @return decimal 
     */
    public function getAmount()
    {
        return $this->amount;
    }

    /**
     * Set affinity
     *
     * @param boolean $affinity
     * @return Plan
     */
    public function setAffinity($affinity)
    {
        $this->affinity = $affinity;

        return $this;
    }

    /**
     * Get affinity
     *
     * @return boolean 
     */
    public function getAffinity()
    {
        return $this->affinity;
    }

    /**
     * Set deactivationFee
     *
     * @param integer $deactivationFee
     * @return Plan
     */
    public function setDeactivationFee($deactivationFee)
    {
        $this->deactivationFee = $deactivationFee;

        return $this;
    }

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

    /**
     * Set gracePeriodDays
     *
     * @param integer $gracePeriodDays
     * @return Plan
     */
    public function setGracePeriodDays($gracePeriodDays)
    {
        $this->gracePeriodDays = $gracePeriodDays;

        return $this;
    }

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

    /**
     * Set recurringInMonths
     *
     * @param integer $recurringInMonths
     * @return Plan
     */
    public function setRecurringInMonths($recurringInMonths)
    {
        $this->recurringInMonths = $recurringInMonths;

        return $this;
    }

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

    /**
     * Set pricingTierId
     *
     * @param integer $pricingTierId
     * @return Plan
     */
    public function setPricingTierId($pricingTierId)
    {
        $this->pricingTierId = $pricingTierId;

        return $this;
    }

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

    /**
     * Set activeStartDate
     *
     * @param \DateTime $activeStartDate
     * @return Plan
     */
    public function setActiveStartDate($activeStartDate)
    {
        $this->activeStartDate = $activeStartDate;

        return $this;
    }

    /**
     * Get activeStartDate
     *
     * @return \DateTime 
     */
    public function getActiveStartDate()
    {
        return $this->activeStartDate;
    }

    /**
     * Set activeEndDate
     *
     * @param \DateTime $activeEndDate
     * @return Plan
     */
    public function setActiveEndDate($activeEndDate)
    {
        $this->activeEndDate = $activeEndDate;

        return $this;
    }

    /**
     * Get activeEndDate
     *
     * @return \DateTime 
     */
    public function getActiveEndDate()
    {
        return $this->activeEndDate;
    }

    /**
     * 
     */
    public function prePersist()
    {
        if (!isset($this->affinity)) {
            $this->setAffinity(0);
        }

        if (!isset($this->active)) {
            $this->setActive(1);
        }
    }
}

Plan.orm.yml

#etrak/OnlineOrderProcessingBundle/Resources/config/doctrine/Entity/Plan.orm.yml
etrak\OnlineOrderProcessingBundle\Entity\Plan:
  type: entity
  table: plans
  id:
    id:
      type: integer
      generator: { strategy: AUTO }
  fields:
    name:
      type: string
      length: 255
      nullable: true
    description:
      type: text
      nullable: true
    termsConditions:
      column: terms_conditions
      type: text
      nullable: true
    active:
      type: boolean
      nullable: true
    amount:
      type: decimal
      nullable: true
      scale: 2
      precision: 5
    affinity:
      type: boolean
      nullable: true
    deactivationFee:
      column: deactivation_fee
      type: decimal
      scale: 2
      precision: 5
      nullable: true
    gracePeriodDays:
      column: grace_period_days
      type: integer
      nullable: true
    recurringInMonths:
      column: recurring_in_months
      type: integer
      nullable: true
    pricingTierId:
      column: pricing_tier_id
      type: integer
    activeStartDate:
      column: active_start_date
      type: date
    activeEndDate:
      column: active_end_date
      type: date
  lifecycleCallbacks:
    prePersist: [ prePersist ]
  manyToOne:
    pricingTier:
      targetEntity: PricingTier
      inversedBy: plans
      joinColumn:
        name: pricing_tier_id
        referencedColumnName: id

PricingTier.php

namespace etrak\OnlineOrderProcessingBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * PricingTier
 */
class PricingTier
{

    /**
     * @var integer
     */
    private $id;

    /**
     * @var integer
     */
    private $productId;

    /**
     * @var string
     */
    private $name;

    /**
     * @var string
     */
    private $description;

    /**
     * @var integer
     */
    private $minimumDevices;

    /**
     * @var boolean
     */
    private $isAffinity;

    /**
     * @var string
     */
    private $keyname;

    /**
     * @var string
     */
    private $createdBy;

    /**
     * @var datetime
     */
    private $createdOn;

    /**
     * @var datetime
     */
    private $updatedOn;

    /**
     * Set productId
     *
     * @param integer $productId
     * @return PricingTier
     */
    public function setProductId($productId)
    {
        $this->productId = $productId;

        return $this;
    }

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

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $plans;

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

    /**
     * Add plans
     *
     * @param \etrak\OnlineOrderProcessingBundle\Entity\Plan $plans
     * @return PricingTier
     */
    public function addPlan(\etrak\OnlineOrderProcessingBundle\Entity\Plan $plans)
    {
        $this->plans[] = $plans;

        return $this;
    }

    /**
     * Remove plans
     *
     * @param \etrak\OnlineOrderProcessingBundle\Entity\Plan $plans
     */
    public function removePlan(\etrak\OnlineOrderProcessingBundle\Entity\Plan $plans)
    {
        $this->plans->removeElement($plans);
    }

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

    /**
     * Set name
     *
     * @param string $name
     * @return PricingTier
     */
    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 PricingTier
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

    /**
     * Set minimumDevices
     *
     * @param integer $minimumDevices
     * @return PricingTier
     */
    public function setMinimumDevices($minimumDevices)
    {
        $this->minimumDevices = $minimumDevices;

        return $this;
    }

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

    /**
     * Set isAffinity
     *
     * @param boolean $isAffinity
     * @return PricingTier
     */
    public function setIsAffinity($isAffinity)
    {
        $this->isAffinity = $isAffinity;

        return $this;
    }

    /**
     * Get isAffinity
     *
     * @return boolean 
     */
    public function getIsAffinity()
    {
        return $this->isAffinity;
    }

    /**
     * Set keyname
     *
     * @param string $keyname
     * @return PricingTier
     */
    public function setKeyname($keyname)
    {
        $this->keyname = $keyname;

        return $this;
    }

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

    /**
     * Set createdBy
     *
     * @param string $createdBy
     * @return PricingTier
     */
    public function setCreatedBy($createdBy)
    {
        $this->createdBy = $createdBy;

        return $this;
    }

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

    /**
     * Set createdOn
     *
     * @param \DateTime $createdOn
     * @return PricingTier
     */
    public function setCreatedOn($createdOn)
    {
        $this->createdOn = $createdOn;

        return $this;
    }

    /**
     * Get createdOn
     *
     * @return \DateTime 
     */
    public function getCreatedOn()
    {
        return $this->createdOn;
    }

    /**
     * Set updatedOn
     *
     * @param \DateTime $updatedOn
     * @return PricingTier
     */
    public function setUpdatedOn($updatedOn)
    {
        $this->updatedOn = $updatedOn;

        return $this;
    }

    /**
     * Get updatedOn
     *
     * @return \DateTime 
     */
    public function getUpdatedOn()
    {
        return $this->updatedOn;
    }

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

    /**
     * @ORM\PrePersist
     */
    public function onPrePersist()
    {
        if (!isset($this->isAffinity)) {
            $this->setIsAffinity(0);
        }
        $this->setCreatedOn(new \DateTime());
    }

    /**
     * @ORM\PreUpdate
     */
    public function onPreUpdate()
    {
        $this->setUpdatedOn(new \DateTime());
    }
}

PricingTier.orm.yml

#etrak/OnlineOrderProcessingBundle/Resources/config/doctrine/Entity/PricingTier.orm.yml
etrak\OnlineOrderProcessingBundle\Entity\PricingTier:
  type: entity
  table: pricing_tiers
  id:
    id:
      type: integer
      generator: { strategy: AUTO }
  fields:
    productId:
      column: product_id
      type: integer
    name:
      type: string
      length: 50
    description:
      type: string
      length: 100
      nullable: true
    minimumDevices:
      column: minimum_devices
      type: integer
    isAffinity:
      column: is_affinity
      type: boolean
    keyname:
      type: string
      length: 55
    createdBy:
      column: created_by
      type: string
      length: 20
    createdOn:
      column: created_on
      type: datetime
    updatedOn:
      column: updated_on
      type: datetime
      nullable: true
  lifecycleCallbacks:
    prePersist: [ onPrePersist ]
    preUpdate: [ onPreUpdate ]
  oneToMany:
    plans:
      targetEntity: Plan
      mappedBy: pricingTier

これに関連するすべてのファイルである必要があります。PlanControllerのcreateView()マジックメソッドによって生成されたフォームをレンダリングするのは1行であるため、Twigファイルは含めませんでした。

よろしくお願いします!

4

1 に答える 1

1

Plan.orm.yml内:

pricingTierId:
      column: pricing_tier_id
      type: integer

これは、多対1結合と同じ列名です。これはおそらく悪い習慣です。これはnullable:trueに設定されておらず、おそらく問題の原因です。明示的に、このフィールドは必要ありません。また、あなたのフォームでは、エンティティではないpricingTierIdのエンティティクラスをロードしていますが、symfonyはこれによってかなり混乱していると思います。

    $builder->add('pricingTierId', 'entity', array(             // add pricingTier
    'class' => 'etrakOnlineOrderProcessingBundle:pricingTier',  // not pricingTierId
    'property' => 'name',
    'label' => "Select Pricing Tier: "
    ));

問題のあるyaml部分を削除し、フォームタイプを調整すると、問題が解決することを期待しています。

于 2013-03-20T21:49:28.333 に答える