2012-07-10 31 views
5

Tôi không understad tại sao với một số đối tượng Entity tôi có thể đặt Id và cho những đối tượng khác tôi gặp lỗi và nói rằng Id không thể rỗng và tôi phải chuyển đối tượng thay thế.Doctrine2, chuyển Id hoặc Đối tượng?

ví dụ .:

$log = new Log(); 
$log->setTypeId(1); 
$log->setUserId(1); 
$entityManager->persist($log); 
$entityManager->flush(); 

Nếu tôi thử các mã trên tôi nhận được lỗi nói rằng: Liêm hạn chế vi phạm: 1048 Cột 'user_id' không thể được null. Và trước tiên tôi phải tạo đối tượng Loại và đối tượng Người dùng và vượt qua chúng:

$log->setType($TypeObject) 
$log->setUser($UserObject) 

Nhưng đối với các đối tượng thực thể khác, tôi không có vấn đề khi gán giá trị trực tiếp, tại sao?

Đây là Entity Log của tôi:

<?php 
/** 
* @Entity 
* @Table(name="log") 
* @HasLifecycleCallbacks 
*/ 
class Log 
{ 
    /** 
    * @var type 
    * @Id 
    * @Column(type="integer") 
    * @GeneratedValue 
    */ 
    protected $id; 

    /** 
    * 
    * @var type 
    * @Column(type="integer") 
    */ 
    protected $user_id; 

    /** 
    * 
    * @var type 
    * @Column(type="integer") 
    */ 
    protected $type_id; 

    /** 
    * 
    * @var type 
    * @Column(type="datetime") 
    */ 
    protected $created; 

    /** 
    * 
    * @var type 
    * @ManyToOne(targetEntity="User", inversedBy="logs") 
    */ 
    protected $user; 

    /** 
    * 
    * @ManyToOne(targetEntity="Type", inversedBy="logs") 
    */ 
    protected $type; 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function getUserId() 
    { 
     return $this->user_id; 
    } 

    public function getTypeId() 
    { 
     return $this->type_id; 
    } 

    public function getCreated() 
    { 
     return $this->created; 
    } 

    public function setUserId($userId) 
    { 
     $this->user_id = $userId; 
    } 

    public function setTypeId($typeId) 
    { 
     $this->type_id = $typeId; 
    } 

    public function setCreated($created) 
    { 
     $this->created = $created; 
    } 

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

    public function setType($type) 
    { 
     $this->type = $type; 
    } 

    /** 
    * @PrePersist 
    */ 
    public function prePersist() 
    { 
     $this->setCreated(new DateTime()); 
    } 

} 
?> 
+1

vui vì điều đó đã giúp ích. Điều này dẫn tôi vào mốc 1K. woohoo. –

Trả lời

4

EDIT

tôi thấy tuyên bố này trên trang web của Doctrine2. Đó là phương pháp hay nhất mà bạn có thể muốn theo dõi khi viết mã cho các mô hình của mình.

Doctrine2 Best Practices

25.9. Không ánh xạ khóa ngoài vào các trường trong thực thể

Khóa ngoài không có ý nghĩa gì trong mô hình đối tượng. Các khóa ngoại là cách một cơ sở dữ liệu quan hệ thiết lập các mối quan hệ. Mô hình đối tượng của bạn thiết lập các mối quan hệ thông qua các tham chiếu đối tượng. Vì vậy việc lập bản đồ các phím nước ngoài để phản đối các lĩnh vực chủ yếu rò rỉ thông tin chi tiết của mô hình quan hệ vào mô hình đối tượng, một cái gì đó bạn thực sự không nên làm

EDIT

thuyết hiện ánh xạ từ đối tượng của bạn để Id tương ứng của họ.

Điều bạn đã làm ở đây hơi dư thừa.

Về cơ bản, bạn đã nói với giáo lý điều tương tự hai lần.

Bạn đã nói với nó rằng cột này có cột 'user_id' và nó cũng có đối tượng User, giống như vậy. Nhưng học thuyết có thể đoán rằng mối quan hệ này sẽ có một cột user_id dựa trên thực tế là lớp log có một đối tượng người dùng bên trong.

Bạn chỉ nên làm như sau thay vì

<?php 
/** 
* @Entity 
* @Table(name="log") 
* @HasLifecycleCallbacks 
*/ 
class Log 
{ 
    /** 
    * @var type 
    * @Id 
    * @Column(type="integer") 
    * @GeneratedValue 
    */ 
    protected $id; 

    /** 
    * 
    * @var type 
    * @Column(type="datetime") 
    */ 
    protected $created; 

    /** 
    * 
    * @var type 
    * @ManyToOne(targetEntity="User", inversedBy="logs") 
    */ 
    protected $user; 

    /** 
    * 
    * @ManyToOne(targetEntity="Type", inversedBy="logs") 
    */ 
    protected $type; 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function getCreated() 
    { 
     return $this->created; 
    } 

    public function setCreated($created) 
    { 
     $this->created = $created; 
    } 

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

    public function setType($type) 
    { 
     $this->type = $type; 
    } 

    /** 
    * @PrePersist 
    */ 
    public function prePersist() 
    { 
     $this->setCreated(new DateTime()); 
    } 

} 

thuyết sẽ lo lắng về user_id và type_id trên riêng của nó. Bạn không phải lo lắng về nó. Bằng cách này, bạn có thể làm việc với các đối tượng chính thức, làm cho chương trình dễ dàng hơn, thay vì phải lo lắng về id. Giáo lý sẽ xử lý điều đó.

Nếu TẤT CẢ bạn có là id, bởi vì đó là những gì bạn đang sử dụng ở giao diện người dùng, sau đó chỉ cần tìm đối tượng được liên kết với id đó bằng Entitymanager.

$user = $em->getEntity('User', $idFromWeb); 
$log = new Log(); 
$log->setUser($user); 
+1

Truy xuất $ user từ db có vẻ giống như một overhead. Nếu mục nhập nhật ký chỉ yêu cầu UserId, tại sao bạn nên truy xuất toàn bộ hồ sơ người dùng. Có cách nào để tránh điều này? –

+0

Mubix, bạn nói đúng. Tuy nhiên, trong yêu cầu này, bạn có thể đã tìm nạp thực thể người dùng để nhận tùy chọn của họ hoặc xác minh thông tin mật khẩu hoặc những thứ khác. Doctrine2 cũng chỉ bao giờ tìm nạp thực thể một lần. Nếu bạn gọi hàm getEntity nhiều lần Doctrine2 sẽ tiếp tục trả về cùng một đối tượng mà không cần quay lại cơ sở dữ liệu. –

+1

Và trong một kịch bản mà bạn đang thực hiện một số thao tác theo lô và tải lên tất cả các thực thể được tham chiếu chỉ để có Doctrine snag FK? Không có cách nào để giải quyết vấn đề này? Tôi cảm thấy bẩn làm cho tất cả các cuộc gọi thêm. Gonna viết một câu lệnh PDO thô hoặc không sử dụng ánh xạ và chỉ tải thực thể đó thông qua kho lưu trữ từ mã điều khiển. – ficuscr

20

Câu trả lời hiện tại chưa bao giờ phù hợp với tôi.Có rất nhiều kịch bản hợp lệ, nơi tải một đối tượng chỉ để xác định mối quan hệ trong khi đã có FK tiện dụng chỉ không có ý nghĩa gì cả.

Giải pháp tốt hơn là sử dụng phương pháp getRefrence của EntityManager.

Reference Proxies...

Phương pháp EntityManager # getReference ($ Tên pháp nhân, $ định danh) cho phép bạn có được một tham chiếu đến một thực thể mà nhận dạng được biết đến, mà không bốc mà tổ chức từ cơ sở dữ liệu. Điều này hữu ích, ví dụ: ví dụ như nâng cao hiệu suất, khi bạn muốn thiết lập liên kết cho một thực thể mà bạn có số nhận dạng. Bạn có thể chỉ đơn giản là làm điều này:

<?php 
    // $em instanceof EntityManager, $cart instanceof MyProject\Model\Cart 
    // $itemId comes from somewhere, probably a request parameter 
    $item = $em->getReference(\MyProject\Model\Item::class, $itemId); 
    $cart->addItem($item); 

Có lẽ đây không phải là có sẵn khi câu hỏi này lần đầu tiên được đăng tải - Tôi không biết.

+3

Tôi không biết về phương pháp này và nó trông giống như chính xác những gì các poster ban đầu được yêu cầu. –

+0

Điều này thật hoàn hảo. Đây có phải là một tính năng mới không? – pagliuca

+0

Tôi đã cố gắng xác định điều đó và không chắc chắn khi điều này có sẵn (2.0>?). Đã được thêm vào năm ngoái. – ficuscr

Các vấn đề liên quan