2012-10-09 19 views
13

Tôi đang gặp khó khăn khi tìm cách mở rộng một thực thể thích hợp trên các bó trong Symfony2 bằng Doctrine2 làm ORM.Mở rộng các thực thể trong Symfony2 với Doctrine2

Hiện tại có ba phương pháp mà tôi đã tìm thấy để mở rộng các thực thể trong Symfony2 bằng cách sử dụng Doctrine2 làm ORM. Mapped Superclass, Single Table InheritanceClass Table Inheritance. Không ai trong số này làm việc cho những gì tôi đang tìm kiếm để làm.

Tôi có hai Nhóm: UserBundle và BlogBundle. Tôi muốn có thể sử dụng UserBundle trong các dự án không có BlogBundle, nhưng BlogBundle sẽ luôn được sử dụng trong các dự án có Gói Người dùng. Không sao nếu BlogBundle có phụ thuộc vào UserBundle, nhưng không phải là cách khác.

Tôi có hai thực thể: BlogBundle \ Entity \ Bưu UserBundle \ Entity \ User

Mối quan hệ: Cần có một đến nhiều mối quan hệ giữa người sử dụng và Blog bài. Điều này đạt được thông qua một tài sản AUTHOR_ID (cột) trên đối tượng BlogBundle \ Entity \ Post (bảng) được ánh xạ tới UserBundle \ Entity \ User.id

Vấn đề: Tôi có thể gọi UserBundle \ Entity \ Thực thể người dùng trực tiếp từ bên trong BlogBundle và đạt được những gì tôi đang tìm kiếm bằng cách sử dụng ánh xạ Uni-Directional. Điều này không cho phép tôi truy cập tất cả các bài viết của một người dùng từ bên trong một đối tượng User. Tôi có thể truy cập dữ liệu qua truy vấn tùy chỉnh nhưng điều này không sạch như truy cập bài đăng của người dùng thông qua đối tượng người dùng.

Điều tôi muốn làm là mở rộng đối tượng UserBundle \ Entity \ User từ bên trong BlogBundle và thêm các phương thức và thuộc tính vào đối tượng này để thiết lập ánh xạ Một đến Nhiều được sử dụng trong BlogBundle. Không có điều nào trong số này tồn tại, nó chỉ định nghĩa mối quan hệ và cho phép tôi truy cập một cách hợp lý tất cả các bài viết được tạo bởi người dùng trong một ứng dụng thực hiện cả BlogBundle và UserBundle bằng cách thêm chức năng cần thiết vào đối tượng User trong gói blog (do đó tránh sự phụ thuộc từ UserBundle đến BlogBundle).

Khi tôi tạo đối tượng BlogBundle \ Entity \ User và mở rộng UserBundle \ Entity \ Người dùng, tôi phải khai báo @ORM \ Table (name = "usertablename"). Nếu không, mọi nỗ lực truy cập đối tượng BlogBundle \ Entity \ User sẽ không truy cập được vào cơ sở dữ liệu. Vì không có phần bổ sung nào trong đối tượng mở rộng tồn tại, điều này hoạt động tốt trên các gói. Vấn đề với điều này là khi tôi gọi "php app/giao diện điều khiển: schema: update --force", có một xung đột vì hai thực thể cố gắng ánh xạ tới & tạo cùng một bảng. Tôi đã thử bằng cách sử dụng tính năng ResolveTargetEntityListener đã được triển khai gần đây nhưng điều này, cùng với Bản đồ Superclas, STI và CTI tất cả đều buộc phụ thuộc vào BlogBundle từ UserBundle.

Dưới đây là các đối tượng của tôi để giúp minh họa cho thiết lập của tôi. Họ đã được viết tắt cho rõ ràng. Tôi nhận ra một số ngữ nghĩa không chính xác nhưng nó có ý định truyền đạt ý tưởng cấu hình &.

UserBundle \ Entity \ User

@ORM\Table(name="app_user") 
@ORM\Entity 
class User implements UserInterface 
{ 
    ... 
} 

BlogBundle \ Entity \ bài

@ORM\Table(name="app_post") 
@ORM\Entity 
class Post 
{ 
    ... 

    @ORM\Column(name="author_id", type="integer") 
    protected $author_id; 

    @ORM\ManyToOne(targetEntity="\App\BlogBundle\Entity\User", inversedBy="posts") 
    @ORM\JoinColumn(name="author_id", referencedColumnName="id") 
    protected $author; 
} 

BlogBundle \ Entity \ User

use App\UserBundle\Entity\User as BaseUser 
@ORM\Entity 
@ORM\table(name="app_user") 
class User extends BaseUser 
{ 
    .... 

    @ORM\OneToMany(targetEntity="App\BlogBundle\Entity\Post", mappedBy="author") 
    protected $posts; 

    public function __construct() 
    { 
     parent::_construct(); 

     $this->posts = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    .... 
    /* Getters & Setters, nothing that defines @ORM\Column, nothing persisted */ 
} 

này hoạt động nhưng vấn đề là tôi ánh xạ hai thực thể trong dự án đến cùng một bảng. Đối tượng mở rộng không lấy @ORM \ Table (name = "app_user") từ cha mẹ của nó để nó phải được định nghĩa trong BlogBundle \ Entity \ User. Nếu không có bất kỳ tham chiếu đến đối tượng này từ một bộ điều khiển sẽ không truy cập cơ sở dữ liệu. Vì không có gì được duy trì từ đối tượng mở rộng, không có gì bị hỏng ngoại trừ khi tôi cố cập nhật lược đồ cơ sở dữ liệu từ giao diện điều khiển.

Tôi có thể sử dụng mối quan hệ một chiều, nhưng điều này giới hạn cách tôi có thể truy cập dữ liệu từ bên trong bộ điều khiển.

+0

Tôi biết đây là một câu hỏi rất cũ ; nhưng bạn đã bao giờ giải quyết nó chưa? Tôi đang đối mặt với những vấn đề tương tự và phải vật lộn để tìm ra bất kỳ giải pháp làm việc nào. – bigstylee

Trả lời

6

Bạn có thể thấy trong liên kết này để biết về thừa kế: http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance

Bạn phải khai báo trong UserBundle \ Entity \ User:

/** 
* @Entity 
* @InheritanceType("SINGLE_TABLE") 
* @DiscriminatorColumn(name="discr", type="string") 
* @DiscriminatorMap({"baseuser" = "UserBundle\Entity\User", "blogUser" = "BlogBundle\Entity\User"}) 
*/ 
class User implements UserInterface 
{ 
    ... 
} 

Và BlogBundle \ Entity \ User

use App\UserBundle\Entity\User as BaseUser; 
/** 
* @ORM\Entity 
*/ 
class User extends BaseUser 
{ 
    .... 
} 

Chúc may mắn!

+1

Tôi không nghĩ rằng đây là một giải pháp thỏa đáng, vì có một tham chiếu từ UserBundle đến BlogBundle trong '@ DiscriminatorMap'. Tôi muốn được quan tâm trong một giải pháp mà UserBundle không có tài liệu tham khảo/phụ thuộc vào BlogBundle ở tất cả. – aimfeld

0

Tôi nghĩ bạn có thể tìm Bundle này thú vị:

https://github.com/mmoreram/SimpleDoctrineMapping

Nó cho phép bạn xác định bởi các thông số gì các file đang lập bản đồ các đơn vị bạn, cho phép ghi đè lên mỗi thực thể của bó chung của bạn.

Ví dụ:

parameters: 

    # 
    # Mapping information 
    # 
    test_bundle.entity.user.class: "TestBundle\Entity\User" 
    test_bundle.entity.user.mapping_file_path: "@TestBundle/Mapping/Class.orm.yml" 
    test_bundle.entity.user.entity_manager: default 
    test_bundle.entity.user.enable: true 

Các chỉ Contra tôi thấy là bạn phải xác định tất cả các đối tượng tiếp theo cùng một cách nguyên nhân bạn vô hiệu hóa auto_mapping ...