2012-07-06 28 views
10

tôi phát hiện vấn đề này "nhờ" đến một ngoại lệ tôi nhận:Symfony 2 - tuôn ra trong postUpdate kiện preUpdate lửa

Catchable Fatal Error: Argument 3 passed to 
Doctrine\ORM\Event\PreUpdateEventArgs::__construct() 
must be an array, null given, called in 
/.../vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php on line 804 
and defined in 
/.../vendor/doctrine/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php line 28 

tôi đang làm việc trên một dự án mà requieres một logic cụ thể:
Khi lĩnh vực order trong thực thể book được sửa đổi, tôi cần cập nhật trường books_order_modified_at trong thực thể cha mẹ bookstore (trường này cho phép tôi biết liệu thứ tự sách trong cửa hàng sách có thay đổi hay không).

Tôi quyết định làm điều đó trong trình xử lý sự kiện vì có nhiều nơi trong mã có thể thay đổi thứ tự sách.

tôi không tìm thấy bất cứ cách nào để cập nhật một thực thể có liên quan từ preUpdate sự kiện, vì vậy tôi có một lĩnh vực riêng trong lớp nghe mà tôi sử dụng để nói lên sự kiện postUpdate để cập nhật các bookstore thực thể có liên quan.

Vấn đề của tôi là khi tôi làm như vậy sự kiện preUpdate của thực thể book được kích hoạt.
Khi tôi kiểm tra bộ thay đổi, nó chỉ chứa trường modified_at, nhưng nó có cùng giá trị trước và sau.

Nếu ai đó có ý tưởng khác về cách giải quyết vấn đề - tuyệt vời.

Nếu không - bất kỳ ý tưởng nào làm cách nào tôi có thể ngăn sự kiện preUpdate bị sa thải khi xả được gọi trong sự kiện postUpdate?

+0

Bạn đã tìm thấy giải pháp cho vấn đề này chưa? – ownking

+0

Không, thực ra tôi đã giải quyết được vấn đề của mình bằng máy chủ thời gian thực (node.js) nên tôi không còn tìm kiếm giải pháp cho việc này nữa. Tuy nhiên, nếu bạn có bất kỳ, nó sẽ là thú vị để xem nó. Cảm ơn! – guyaloni

Trả lời

1

Điều gì về việc cập nhật modified_at trong thực thể của bạn và để giáo lý xử lý nó? Bạn sẽ thay đổi phương thức setOrder của bạn trong cuốn sách của bạn để cập nhật các thực thể BookOrder như thế này:

class Book { 
    public function setOrder($order) { 
     // modify book 
     $this->bookOrder->updateModifiedAt(); 
    } 
} 

Tất nhiên BookOrder bạn sẽ phải thực hiện modifiedAt:

class BookOrder { 
    public function updateModifiedAt() { 
     $this->modifiedAt = new \DateTime(); 
    } 
} 

Nếu bạn sử dụng các lớp khác cho Datetime của bạn, bạn tất nhiên phải thay đổi mã này!

Học thuyết sẽ nhận ra rằng BookOrder đã thay đổi và nên cập nhật nó mà không cần sử dụng trình xử lý sự kiện.

0

Tôi có thể đề nghị bạn sử dụng tiện ích Timestampable cho Doctrine từ DoctrineExtensionsBundle.

Bằng cách sử dụng nó, bạn không cần đặt giá trị created_at hoặc modified_at. Tiện ích mở rộng này tự động thực hiện. Ngay cả khi chỉ có thể đặt modified_at chỉ khi các trường cụ thể được sửa đổi. Xem example.

Tôi nghĩ bạn đang viết một cái gì đó giống như tiện ích mở rộng này. Vì vậy, bạn không cần phải làm điều đó vì điều này đã được thực hiện :)

+1

Vấn đề của tôi là trường thời gian mà tôi muốn cập nhật là một thực thể khác, không phải của thực thể được sửa đổi. Nó là một phần mở rộng tốt đẹp, nhưng tôi nghĩ rằng trong trường hợp của tôi nó sẽ không giải quyết được vấn đề. – guyaloni

6

Thực ra, đây là vấn đề từ học thuyết Doctrine Issue DDC-2726. Giải quyết nó bằng cách thêm một cuộc gọi rõ ràng vào trình quản lý thực thể sau khi xóa trong trình lắng nghe để đối số thứ 3 cho hàm tạo đó, thực sự là entityChangeSets, sẽ được viết lại.

+1

Làm thế nào để bạn thực hiện một "cuộc gọi rõ ràng về người quản lý thực thể, bạn có thể mô tả điều đó không? Cảm ơn! – tomazahlin

+2

" $ args-> getEntityManager() -> clear(); "Đơn giản chỉ cần gọi phương thức rõ ràng của người quản lý thực thể –

+0

Cảm ơn, Tôi cần phải xem xét điều này, để thực sự hiểu những gì đang xảy ra – tomazahlin

0

Tôi gặp vấn đề tương tự với vấn đề này. Cố gắng sử dụng preupdate để sửa đổi các phần tử con gây ra cùng một lỗi.Cuối cùng, giải pháp của tôi chỉ đơn giản là cập nhật các trẻ em thuộc về cha mẹ. Không có yêu cầu rõ ràng để yêu cầu flush.

/** 
* Update expiry dates for all runners belonging to a campaign 
* 
* @param $runners 
* @param $expiryDate 
*/ 
private function updateCampaignRunners($runners, $expiryDate){ 
    foreach($runners as $runner){ 
     $runner->setExpiresAt($expiryDate); 
     $this->getModelManager()->update($runner); 
    } 
} 

/** 
* Post update and persist lifecycle callback 
* 
* @param Campaign $campaign 
*/ 
private function postAction(Campaign $campaign) 
{ 
    $runnerExpire = $this->getForm()->get("runnerExpire")->getData(); 
    if($runnerExpiryDate && $campaign->getRunners()){ 
     $this->updateCampaignRunners($campaign->getRunners(), $runnersExpiryDate); 
    } 
} 
Các vấn đề liên quan