我正在努力正确设置实体。 情况如下:
“国家/地区”有一个或多个“客户”
我是一个包含所有国家/地区的国家/地区表,我想为每个客户保存对国家/地区的引用。很简单,经常需要。
但我无法正确配置实体。如果我没有在“Customer”类中定义级联方法,我会得到一个例外。如果我添加级联方法,那么国家/地区对象也会作为新记录添加到国家/地区表中,但我只想在Customer表中引用此对象。
客户类
/**
* @ORM\Entity
* @ORM\Table(name="PS_Customer")
*/
class Customer {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="Country",inversedBy="id")
* @ORM\JoinColumn(name="country_id", referencedColumnName="id")
*/
protected $country;
}
国家/地区类
/**
* @ORM\Entity
* @ORM\Table(name="PS_Country")
*/
class Country {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
* @ORM\OneToMany(targetEntity="Customer", mappedBy="country")
*/
protected $id;
/** @ORM\Column(type="string") */
protected $name;
/** @ORM\Column(type="string") */
protected $iso2;
}
如果我想使用此定义存储Customer对象,则会收到以下错误:
A new entity was found through the relationship 'Photoshop\Entity\Customer#country' that was not configured to cascade persist operations for entity: Photoshop\Entity\Country@000000004c6f8efb00000000b695d273. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Photoshop\Entity\Country#__toString()' to get a clue.
ActionController(已解压缩):
$forms = $this->getServiceLocator()->get('FormElementManager');
$form = $forms->get('Photoshop\Form\CheckoutForm');
$customer = new Customer;
$form->bind($customer);
$order = new Order;
$order->setCustomer($customer);
// Order object is put into a session during checkout process here...
/**
* Commit Order to database
*/
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$em->persist($sessionCheckout->order); // Fetch the order object from session
$em->flush();
结帐表格
class CheckoutForm extends Form implements ObjectManagerAwareInterface {
protected $objectManager;
public function __construct() {
parent::__construct('checkout');
}
public function init() {
$this->setAttribute('action', 'checkout');
$this->setAttribute('method', 'post');
$this->setHydrator(new DoctrineHydrator($this->getObjectManager()));
$this->setInputFilter(new \Photoshop\Form\CheckoutFilter());
$this->add(array(
'name' => 'country',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
'label' => 'Country:',
'empty_option' => 'Please choose...',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Photoshop\Entity\Country',
'property' => 'name',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'gender',
'options' => array(
'label' => 'Title*:',
'empty_option' => 'Please choose...',
'value_options' => array(
'f' => 'Mrs.',
'm' => 'Mr.'
),
)
));
$this->add(array(
'name' => 'firstName',
'attributes' => array(
'type' => 'text',
'id' => 'firstName'
),
'options' => array(
'label' => 'First name*:'
),
));
$this->add(array(
'name' => 'lastName',
'attributes' => array(
'type' => 'text',
'id' => 'lastName'
),
'options' => array(
'label' => 'Last name*:'
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Pay with PayPal or Credit Card now',
'class' => 'btn btn-primary btn-lg btn-block'
)
));
}
public function setObjectManager(ObjectManager $objectManager) {
$this->objectManager = $objectManager;
}
/**
* Get the object manager
*
* @return ObjectManager
*/
public function getObjectManager() {
return $this->objectManager;
}
}
我很确定解决起来很简单。但我现在看不到解决方案:)
也许有人可以给我一个提示?!?会很感激...
谢谢, 迈克尔
答案 0 :(得分:2)
//在此结账过程中将订单对象放入会话中......这是重要的部分
因此,如果我理解,您可以在一个请求中创建订单和客户,然后通过会话将其转移到其他请求并将其保留在那里。真正发生的是你有像order-> customer-> country这样的对象图,前两个是新实体,所以序列化反序列化对它们没有任何问题,但country是已经存在于DB中的被管实体。通过将其序列化为会话,它与实体管理器分离,并且在反序列化之后,它被呈现给新的实体管理器实例,该实例管理器实例不知道它曾经被管理过,因此决定持久化是新的实体管理器实例。
通常您需要将未序列化的实体合并到当前的实体管理器
$managedOrder = $em->merge($sessionCheckout->order);
并使用$ managedOrder。为此,您可能需要在Customer :: country和Order :: customer上设置cascade = {“merge”}。
Doctrine有关于此主题的Entities in session文档页面。