2013-04-01 15 views
21

Tôi gặp vấn đề với Doctrine2 trong Symfony2 và hai thực thể có quan hệ.Symfony2 Doctrine2 gặp rắc rối với mối quan hệ một đến một tùy chọn

Có một người dùng thực thể mà thể (không phải) có một usermeta thực thể tham chiếu chứa các thông tin như tiểu sử, vv

Các usermeta là không bắt buộc vì sử dụng được nhập khẩu bởi một hệ thống khác, trong khi usermeta là được quản lý trong ứng dụng của tôi.

Tất nhiên tôi muốn lưu cả hai cùng nhau, để lưu người dùng phải tạo hoặc cập nhật thực thể usermeta.

Cả hai đều được nối với nhau bằng một cột có tên aduserid (cùng tên trong cả hai bảng).

Tôi đã nhận ra rằng nếu usermeta là tham chiếu tùy chọn, trường hợp sở hữu trong trường hợp này phải là usermeta, nếu không học thuyết sẽ tải người dùng và cần thực thể usermeta - nhưng không phải lúc nào cũng ở đó.

Xin lưu ý các ý kiến ​​trong user-> setMeta ..

/** 
* User 
* 
* @ORM\Table(name="user") 
* @ORM\Entity 
*/ 
class User 
{ 
/** 
* @var Usermeta 
* @ORM\OneToOne(targetEntity="Usermeta", mappedBy="user", cascade={"persist"}) 
*/ 
protected $meta; 

public function getMeta() 
{ 
    return $this->meta; 
} 

/** 
* 
* @param Usermeta $metaValue 
*/ 
public function setMeta($metaValue) 
{   
// I've tried setting the join-column-value here 
// - but it's not getting persisted 
// $metaValue->setAduserid($this->getAduserid()); 

// Then I've tried to set the user-object in Usermeta - but then 
// it seems like Doctrine wants to update Usermeta and searches 
// for ValId names aduserid (in BasicEntityPersister->_prepareUpdateData) 
// but only id is given - so not luck here 
// $metaValue->setUser($this);   

    $this->meta = $metaValue; 
} 

/** 
* @var integer 
* 
* @ORM\Column(name="rowid", type="integer", nullable=false) 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="IDENTITY") 
*/ 
private $id; 


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

/** 
* @var integer 
* 
* @ORM\Column(name="ADuserid", type="integer", nullable=false) 
*/ 
private $aduserid; 

/** 
* Set aduserid 
* 
* @param integer $aduserid 
* @return User 
*/ 
public function setAduserid($aduserid) 
{ 
    $this->aduserid = $aduserid; 

    return $this; 
} 

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

// some mor fields.... 
} 

Và lớp Usermeta:

/** 
* Usermeta 
* 
* @ORM\Table(name="userMeta") 
* @ORM\Entity 
*/ 
class Usermeta 
{ 
/** 
* @ORM\OneToOne(targetEntity="User", inversedBy="meta") 
* @ORM\JoinColumn(name="ADuserid", referencedColumnName="ADuserid") 
*/ 
protected $user; 

public function getUser() 
{ 
    return $this->$user; 
}  

public function setUser($userObj) 
{ 
    $this->user = $userObj; 
} 

/** 
* @var integer 
* 
* @ORM\Column(name="id", type="integer", nullable=false) 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="IDENTITY") 
*/ 
private $id; 

/** 
* @var integer 
* 
* @ORM\Column(name="ADuserid", type="integer", nullable=false) 
*/ 
private $aduserid; 

/** 
* Set aduserid 
* 
* @param integer $aduserid 
* @return User 
*/ 
public function setAduserid($aduserid) 
{ 
    $this->aduserid = $aduserid; 

    return $this; 
} 

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

mã điều khiển trông như thế này:

... 

$userForm->bind($request); 

    if($userForm->isValid()) { 
     $em->persist($user); 
     $em->flush(); 
    } 
... 
+0

Không phải là lừa để cài đặt meta - nullable = true /** * @var Usermeta * @ORM \ OneToOne (targetEntity = "Usermeta", mappedBy = "user" , cascade = {"persist"}, nullable = true) */ được bảo vệ $ meta; –

+1

@Zdenek, chú thích OneToOne không có tham số nullable. Nó là tham số của '@ JoinColumn'. – Athlan

Trả lời

-4

Đọc câu hỏi cũ của mình là khá thú vị vì tôi thấy vấn đề ở cái nhìn đầu tiên tại ..

Khi nói đến một giải pháp tôi đã nghĩ rằng học thuyết chỉ có thể xử lý Id tên "id", nhưng. .. aduserid không được đánh dấu là ID, thiếu chú thích và giáo lý Id không thể sử dụng các trường cho cột tham gia.

Điều thứ hai, Zdenek Machek đã đúng: Nó phải được đánh dấu là không thể sử dụng.

7

Bạn' đang sử dụng loại Quan hệ sai cho vấn đề của bạn.

Những gì bạn muốn là một unidirectional one to one từ Usermeta để tài.

Một một hai chiều cho một mối quan hệ có nghĩa như sau:

  1. Một người sử dụng phải có một đối tượng Usermeta.
  2. Đối tượng Usermeta PHẢI có Người dùng.

Trong trường hợp của bạn, bạn chỉ đang cố gắng yêu cầu điều kiện thứ hai.

Điều này có nghĩa là bạn chỉ có thể hydrate Người dùng từ Usermeta chứ không phải theo cách khác.

Thật không may là học thuyết does not support Zero or One to Many mối quan hệ.

0

Tôi nhận được thông báo lỗi "spl_object_hash() dự kiến ​​tham số 1 là đối tượng, được cho trong ..." trong khi thử cùng một thứ.Tôi đã cố gắng xác định mối quan hệ hai chiều One to One trong khi giá trị đảo ngược có thể là null. Điều này đã đưa ra thông báo lỗi. Lấy đi mặt nghịch đảo của mối quan hệ đã giải quyết được vấn đề. Thật đáng tiếc là mối quan hệ Zero or One to One không được hỗ trợ.

0

Tôi hy vọng tôi không làm phiền bất cứ ai bằng cách gửi câu trả lời rất muộn này, nhưng đây là cách tôi giải quyết vấn đề này:

/** 
* @var Takeabyte\GripBundle\Entity\PDF 
* @ORM\OneToOne(targetEntity="Takeabyte\GripBundle\Entity\PDF", inversedBy="element", fetch="EAGER", orphanRemoval=true) 
*/ 
protected $pdf = null; 

tôi thêm = null; để khai báo thuộc tính. Tôi hy vọng điều này là giúp đỡ cho bất cứ ai đọc này.

+2

Giá trị mặc định của bất kỳ trường nào là null. –

14

Số Zdenek Machek nhận xét gần như chính xác. Như bạn có thể thấy từ tài liệu Doctrine2, tùy chọn nullable phải ở trong chú thích tham gia (@JoinColumn), không phải trong bản đồ (@OneToOne).

@JoinColumn doc:

chú thích này được sử dụng trong bối cảnh quan hệ trong @ManyToOne, ruộng @OneToOne và trong bối cảnh @JoinTable lồng vào bên trong một @ManyToMany. Chú thích này không bắt buộc. Nếu nó không được chỉ định tên thuộc tính và referencedColumnName được suy ra từ bảng và tên khóa chính. thuộc tính

Yêu cầu:

tên: tên cột chứa định danh chính nước ngoài cho mối quan hệ này. Trong ngữ cảnh của @JoinTable nó chỉ định tên cột trong bảng kết nối.

được tham chiếuColumnName: Tên của số nhận dạng khóa chính được sử dụng để tham gia quan hệ này.

thuộc tính bắt buộc:

độc đáo: Xác định mối quan hệ này độc quyền giữa các đối tượng bị ảnh hưởng và nên được áp dụng như vậy trên cơ sở dữ liệu mức hạn chế. Mặc định là sai.

không thể xác định được: Xác định xem thực thể có liên quan là bắt buộc hay null là trạng thái được phép cho mối quan hệ. Mặc định là đúng.

onDelete: Cascade Action (Cơ sở dữ liệu cấp)

onUpdate: Cascade Action (Cơ sở dữ liệu cấp)

ColumnDefinition: DDL đoạn SQL bắt đầu sau tên cột và xác định định nghĩa cột hoàn chỉnh (không di động!). Thuộc tính này cho phép sử dụng các tính năng RMDBS nâng cao. Sử dụng thuộc tính này trên @JoinColumn là cần thiết nếu bạn cần các định nghĩa cột hơi khác nhau để nối các cột, ví dụ liên quan đến các giá trị mặc định NULL/NOT NULL. Tuy nhiên theo mặc định, thuộc tính "columnDefinition" trên @Column cũng đặt cộtDefinition của @ JoinColumn có liên quan.Điều này là cần thiết để làm cho các phím nước ngoài hoạt động.

http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#annref-joincolumn

@OneToOne doc:

Chú thích @OneToOne làm việc gần như chính xác như @ManyToOne với một lựa chọn bổ sung có thể được xác định. Mặc định cấu hình cho @JoinColumn bằng cách sử dụng bảng thực thể đích và tên cột khóa chính cũng áp dụng ở đây.

buộc thuộc tính:

targetEntity: FQCN của thực thể mục tiêu tham chiếu. Có thể là tên lớp không đủ tiêu chuẩn nếu cả hai lớp nằm trong cùng một không gian tên. QUAN TRỌNG: Không có dấu gạch chéo ngược hàng đầu!

thuộc tính bắt buộc:

thác: Cascade Lựa chọn

lấy: Một trong những lười biếng hoặc háo hức

orphanRemoval: Boolean mà xác định nếu trẻ mồ côi, ngược OneToOne thực thể không được kết nối với bất kỳ cá thể sở hữu nào, nên được Doctrine loại bỏ. Mặc định là sai.

inversedBởi: Thuộc tính inversedBy chỉ định trường trong thực thể là mặt trái của mối quan hệ.

http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#onetoone