Doctrine 2 và bảng liên kết Nhiều đến nhiều với một trường bổ sung


88

(Xin lỗi vì câu hỏi không mạch lạc của tôi: Tôi đã cố gắng trả lời một số câu hỏi khi viết bài này, nhưng đây rồi :)

Tôi đang cố gắng tạo một mô hình cơ sở dữ liệu với mối quan hệ nhiều-nhiều bên trong một bảng liên kết, nhưng cũng có một giá trị trên mỗi liên kết, trong trường hợp này là một bảng lưu kho. (đây là một ví dụ cơ bản cho nhiều vấn đề khác mà tôi đang gặp phải, nhưng tôi nghĩ tôi chỉ cần kiểm tra nó với điều này trước khi tiếp tục).

Mô hình cơ sở dữ liệu cho một hệ thống lưu trữ nhiều cửa hàng, nhiều sản phẩm cơ bản

Tôi đã sử dụng exportmwb để tạo hai Entities Store và Product cho ví dụ đơn giản này, cả hai đều được hiển thị bên dưới.

Tuy nhiên, vấn đề bây giờ là tôi không thể tìm ra cách truy cập giá trị stock.amount (int có dấu, vì nó có thể là số âm) bằng Doctrine. Ngoài ra, khi tôi cố gắng tạo các bảng bằng hàm orm: schema-tool: create của học thuyết

bố cục cơ sở dữ liệu như được thấy từ HeidiSQL

Điều này chỉ mang lại hai Thực thể và ba bảng, một dưới dạng bảng liên kết không có giá trị và hai bảng dữ liệu, vì bản thân mối quan hệ nhiều-nhiều không phải là thực thể nên tôi chỉ có thể có Sản phẩm và Cửa hàng dưới dạng thực thể.

Vì vậy, về mặt logic, tôi đã thử thay đổi mô hình cơ sở dữ liệu của mình để có kho dưới dạng một bảng riêng biệt với các mối quan hệ để lưu trữ và sản phẩm. Tôi cũng đã viết lại các tên trường chỉ để có thể loại trừ nó như một nguồn của vấn đề:

đã thay đổi bố cục cơ sở dữ liệu

Sau đó, những gì tôi phát hiện ra là tôi vẫn không nhận được thực thể Cổ phiếu ... và bản thân cơ sở dữ liệu không có trường 'số tiền'.

Tôi thực sự cần có thể liên kết các cửa hàng và sản phẩm này lại với nhau trong một bảng kho (trong số những thứ khác) ... vì vậy chỉ thêm hàng vào chính sản phẩm không phải là một lựa chọn.

root@hdev:/var/www/test/library# php doctrine.php orm:info
Found 2 mapped entities:
[OK]   Entity\Product
[OK]   Entity\Store

Và khi tôi tạo cơ sở dữ liệu, nó vẫn không cung cấp cho tôi các trường phù hợp trong bảng stock:

bố cục cơ sở dữ liệu như được thấy từ HeidiSQL

Vì vậy, khi tra cứu một số thứ ở đây, tôi phát hiện ra rằng kết nối nhiều-nhiều không phải là thực thể và do đó không thể có giá trị. Vì vậy, tôi đã thử thay đổi nó thành một bảng riêng biệt với các mối quan hệ với những người khác, nhưng nó vẫn không hoạt động.

Tôi làm gì sai ở đây?


Được rồi, tôi đã tìm thấy một số đề cập nói rằng không thể có nhiều kết nối bằng Doctrine, với các nhận xét khuyên bạn nên ngăn chặn những mối quan hệ này .. nhưng nếu bạn thực sự bị mắc kẹt với một tình huống như tôi đã mô tả trong câu hỏi ban đầu của tôi? Tôi có toàn bộ cơ sở dữ liệu, tương thích với Magento, hoàn toàn dựa vào các mối quan hệ nhiều-nhiều. Vì vậy, về cơ bản tôi đang được thông báo "Doctrine ORM không thể xử lý nhiều-nhiều, không sử dụng nó" ??
Henry van Megen


3
Sẽ cung cấp cho bạn 100 nếu tôi có thể cho các nỗ lực bạn đã thực hiện để giải thích chính xác những gì tôi đã tự hỏi về một cách thoải mái như vậy :-)
Torsten Römer

Câu trả lời:


141

Liên kết Nhiều-Nhiều với các giá trị bổ sung không phải là Nhiều-Nhiều, nhưng thực sự là một thực thể mới, vì nó hiện có một định danh (hai quan hệ với các thực thể được kết nối) và các giá trị.

Đó cũng là lý do tại sao Nhiều-To-Nhiều hiệp hội rất hiếm: bạn có xu hướng lưu trữ thuộc tính bổ sung trong họ, chẳng hạn như sorting, amountvv

Những gì bạn có thể cần là một cái gì đó như sau (Tôi đã thực hiện cả hai quan hệ hai chiều, hãy xem xét tạo ít nhất một trong số chúng là đơn hướng):

Sản phẩm:

namespace Entity;

use Doctrine\ORM\Mapping as ORM;

/** @ORM\Table(name="product") @ORM\Entity() */
class Product
{
    /** @ORM\Id() @ORM\Column(type="integer") */
    protected $id;

    /** ORM\Column(name="product_name", type="string", length=50, nullable=false) */
    protected $name;

    /** @ORM\OneToMany(targetEntity="Entity\Stock", mappedBy="product") */
    protected $stockProducts;
}

Cửa hàng:

namespace Entity;

use Doctrine\ORM\Mapping as ORM;

/** @ORM\Table(name="store") @ORM\Entity() */
class Store
{
    /** @ORM\Id() @ORM\Column(type="integer") */
    protected $id;

    /** ORM\Column(name="store_name", type="string", length=50, nullable=false) */
    protected $name;

    /** @ORM\OneToMany(targetEntity="Entity\Stock", mappedBy="store") */
    protected $stockProducts;
}

Cổ phần:

namespace Entity;

use Doctrine\ORM\Mapping as ORM;

/** @ORM\Table(name="stock") @ORM\Entity() */
class Stock
{
    /** ORM\Column(type="integer") */
    protected $amount;

    /** 
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="Entity\Store", inversedBy="stockProducts") 
     * @ORM\JoinColumn(name="store_id", referencedColumnName="id", nullable=false) 
     */
    protected $store;

    /** 
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="Entity\Product", inversedBy="stockProducts") 
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=false) 
     */
    protected $product;
}

Ok, tôi sẽ thêm một số phương thức getter và setters, bởi vì với thiết lập này, tôi chỉ nhận được những chìa khóa chính và chạy mà không cần bất kỳ giá trị :)
Henry van Megen

Khi tôi sử dụng thiết lập này và sau đó cố gắng truy vấn bằng Stock.store_id, tôi gặp lỗi "Cổ phiếu không có trường hoặc liên kết có tên store_id". Nó sẽ được tìm thấy vì cột tồn tại trong cơ sở dữ liệu.
afilina

@afilina db không quan trọng khi tạo giản đồ - các DBAL ném ngoại lệ bởi vì nó không tìm thấy cột trong siêu dữ liệu DDL (trong bộ nhớ)
Ocramius

@Ocramius Ý tôi là DB được tạo từ siêu dữ liệu. Nếu nó có thể tạo cột ngay từ đầu, thì nó sẽ có thể tìm thấy nó trong quá trình truy vấn. Giải pháp cho vấn đề của tôi là so sánh Stock.store với id mong muốn.
afilina

100% những gì tôi cần và nó hoạt động như một sự quyến rũ! Bạn có biết cách tạo biểu mẫu với tập trường để chỉnh sửa số tiền trên mỗi cửa hàng và sản phẩm không?
cwhisperer

17

Doctrine xử lý tốt các mối quan hệ nhiều-nhiều.

Vấn đề bạn đang gặp phải là bạn không cần một liên kết ManyToMany đơn giản, bởi vì các liên kết không thể có dữ liệu "bổ sung".

Bảng giữa (kho) của bạn, vì nó chứa nhiều hơn product_id và store_id, nên cần có thực thể riêng để tạo mô hình cho dữ liệu bổ sung đó.

Vì vậy, bạn thực sự muốn có ba lớp thực thể:

  • Sản phẩm
  • StockLevel
  • Cửa hàng

và hai hiệp hội:

  • Product oneToMany StockLevel
  • Cửa hàng oneToMany StockLevel

1
Cảm ơn về câu trả lời của bạn ! Tôi đã thêm các trường bổ sung vào bảng giống như "cổ phiếu" của mình. Tuy nhiên, học thuyết vẫn không xem xét "bảng tham gia" này và bỏ qua nó khi tôi chạy php app/console doctrine:mapping:import AppBundle ymlđể nhập lược đồ từ cơ sở dữ liệu. Tôi muốn nó tạo tệp yaml ánh xạ bổ sung này. Có ai có ý kiến ​​gì không ? :(
Stphane

Trả lời không giải quyết việc ghi dữ liệu vào thực thể "kết nối". Đây là một vấn đề. Không khai báo các thực thể. Có thể vui lòng ai đó hỗ trợ ví dụ về nơi dữ liệu được chuyển từ Biểu mẫu (trường CollectionType có biểu mẫu nhúng với trường EntityType). Tôi không thể chuyển dữ liệu từ biểu mẫu được nhúng sang biểu mẫu chính và lưu bộ sưu tập các trường đúng cách
zoore 22/02
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.