Doktrin 2 dan tabel tautan Banyak ke banyak dengan bidang ekstra

88

(Maaf atas pertanyaan saya yang tidak koheren: Saya mencoba menjawab beberapa pertanyaan ketika saya menulis posting ini, tetapi ini dia :)

Saya mencoba membuat model database dengan hubungan banyak-ke-banyak di dalam tabel tautan, tetapi yang juga memiliki nilai per tautan, dalam hal ini tabel penyimpanan stok. (ini adalah contoh dasar untuk lebih banyak masalah yang saya alami, tetapi saya pikir saya hanya akan mengujinya dengan ini sebelum melanjutkan).

Model database untuk sistem penyimpanan multi-toko dan multiproduk dasar

Saya telah menggunakan exportmwb untuk menghasilkan dua Entities Store dan Product untuk contoh sederhana ini, keduanya ditampilkan di bawah.

Namun, masalahnya sekarang adalah saya tidak tahu cara mengakses nilai stock.amount (ditandatangani int, karena bisa negatif) menggunakan Doctrine. Juga, ketika saya mencoba membuat tabel menggunakan doktrin orm: schema-tool: create function

tata letak database seperti yang terlihat dari HeidiSQL

Ini hanya menghasilkan dua Entitas dan tiga tabel, satu sebagai tabel tautan tanpa nilai dan dua tabel data, karena hubungan banyak-ke-banyak bukanlah entitas itu sendiri sehingga saya hanya dapat memiliki Produk dan Penyimpanan sebagai entitas.

Jadi, secara logika, saya mencoba mengubah model database saya agar memiliki stok sebagai tabel terpisah dengan hubungan ke toko dan produk. Saya juga menulis ulang nama bidang hanya untuk mengecualikannya sebagai sumber masalah:

mengubah tata letak database

Lalu apa yang saya temukan adalah bahwa saya masih belum mendapatkan entitas Saham ... dan database itu sendiri tidak memiliki kolom 'jumlah'.

Saya benar-benar perlu untuk dapat mengikat toko dan produk ini bersama-sama dalam tabel stok (antara lain) ... jadi menambahkan stok pada produk itu sendiri bukanlah suatu pilihan.

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

Dan ketika saya membuat database, itu masih tidak memberi saya bidang yang tepat di tabel stok:

tata letak database seperti yang terlihat dari HeidiSQL

Jadi, melihat beberapa hal di sini, saya menemukan bahwa koneksi banyak-ke-banyak bukanlah entitas dan karenanya tidak dapat memiliki nilai. Jadi saya mencoba mengubahnya ke tabel terpisah dengan hubungan ke yang lain, tetapi tetap tidak berhasil.

Apa yang saya lakukan salah di sini?

Henry van Megen
sumber
Oke, saya menemukan beberapa penyebutan yang menyatakan bahwa tidak mungkin memiliki koneksi banyak ke banyak menggunakan Doktrin, dengan komentar yang menyarankan untuk mencegah hubungan ini .. tetapi bagaimana jika Anda benar-benar terjebak dengan situasi seperti yang saya jelaskan di pertanyaan asli saya? Saya memiliki seluruh database, kompatibel dengan Magento, yang sepenuhnya bergantung pada hubungan banyak-ke-banyak. Jadi pada dasarnya saya diberitahu "Doctrine ORM tidak bisa menangani banyak-ke-banyak, jangan gunakan" ??
Henry van Megen
3
Akan memberi Anda +100 jika saya bisa atas upaya yang telah Anda lakukan untuk menjelaskan dengan tepat apa yang saya ingin tahu dengan cara yang baik :-)
Torsten Römer

Jawaban:

143

Asosiasi Many-To-Many dengan nilai tambahan bukanlah Many-To-Many, tapi merupakan entitas baru, karena sekarang memiliki sebuah identifier (dua relasi ke entitas yang terhubung) dan nilai.

Itu juga alasan mengapa Banyak-To-Banyak asosiasi sangat jarang: Anda cenderung untuk menyimpan sifat tambahan di dalamnya, seperti sorting, amount, dll

Yang mungkin Anda butuhkan adalah sesuatu seperti berikut (Saya membuat kedua relasi dua arah, pertimbangkan untuk membuat setidaknya salah satunya searah):

Produk:

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;
}

Toko:

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;
}

Persediaan:

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;
}
Ocramius
sumber
Oke, saya akan menambahkan beberapa pengambil dan penyetel, karena dengan penyiapan ini, saya hanya mengaktifkan dan menjalankan kunci utama tanpa nilai apa pun :)
Henry van Megen
Saat saya menggunakan penyiapan ini dan kemudian mencoba melakukan kueri menggunakan Stock.store_id, saya mendapatkan pesan kesalahan "Saham tidak memiliki bidang atau asosiasi bernama store_id". Ini harus ditemukan karena kolom tersebut ada di database.
afilina
@afilina, db tidak masalah saat membuat skema - DBAL mengeluarkan pengecualian karena tidak menemukan kolom dalam metadata DDL (dalam memori)
Ocramius
@Ocramius Yang saya maksud adalah bahwa DB dihasilkan dari metadata. Jika ia mampu menghasilkan kolom di tempat pertama, maka ia harus dapat menemukannya selama kueri. Solusi untuk masalah saya adalah membandingkan Stock.store dengan id yang diinginkan.
afilina
100% apa yang saya butuhkan dan berfungsi dengan baik! Apakah Anda tahu cara membuat formulir dengan fieldset untuk mengedit jumlah per toko dan produk?
cwhisperer
17

Doktrin menangani hubungan banyak-ke-banyak dengan baik.

Masalah yang Anda alami adalah Anda tidak memerlukan pengaitan ManyToMany sederhana, karena pengaitan tidak dapat memiliki data "ekstra".

Tabel tengah (stok) Anda, karena berisi lebih dari product_id dan store_id, membutuhkan entitasnya sendiri untuk memodelkan data tambahan itu.

Jadi Anda benar-benar menginginkan tiga kelas entitas:

  • Produk
  • StockLevel
  • Toko

dan dua asosiasi:

  • Produk satuToMany StockLevel
  • Simpan satuToMany StockLevel
timdev
sumber
1
Terima kasih atas jawaban Anda ! Saya menambahkan bidang ekstra ke tabel seperti "saham" saya. Namun, doktrin masih tidak mempertimbangkan "tabel gabung" ini dan lewati saat saya menjalankannya php app/console doctrine:mapping:import AppBundle ymluntuk mengimpor skema dari database. Saya ingin ini menghasilkan file yaml pemetaan ekstra ini. Apakah ada yang punya Ide? :(
Stphane
Jawaban tidak menyelesaikan penulisan data ke entitas "koneksi". Ini adalah sebuah masalah. Tidak mendeklarasikan entitas. Bisakah tolong seseorang mendukung contoh di mana data diteruskan dari Formulir (bidang CollectionType memiliki formulir yang disematkan dengan bidang EntityType). Saya tidak dapat meneruskan data dari formulir sematan ke formulir utama, dan menyimpan koleksi bidang dengan benar
zoore