Doktrin 2 ve fazladan alan içeren çoktan çoğa bağlantı tablosu


88

(Tutarsız sorum için özür dilerim: Bu yazıyı yazarken bazı soruları cevaplamaya çalıştım ama işte burada :)

Bir bağlantı tablosu içinde çoka çok ilişkisi olan, ancak aynı zamanda bağlantı başına bir değer, bu durumda bir stok tutma tablosu olan bir veritabanı modeli oluşturmaya çalışıyorum. (Bu, yaşadığım daha fazla sorun için temel bir örnek, ancak devam etmeden önce bununla test edeceğimi düşündüm).

Temel bir çok mağazalı, çok ürünlü mağaza tutma sistemi için veritabanı modeli

Bu basit örnek için iki Varlık Mağazasını ve Ürünü oluşturmak için exportmwb kullandım , her ikisi de aşağıda gösterilmektedir.

Ancak şu anda sorun şu ki, Doctrine kullanarak stock.amount değerine (işaretli int, negatif olabilir) nasıl erişeceğimi çözemiyorum. Ayrıca, doktrinin orm: schema-tool: create function'ı kullanarak tabloları oluşturmaya çalıştığımda

HeidiSQL'den görüldüğü şekliyle veritabanı düzeni

Bu, yalnızca iki Varlık ve üç tablo verdi; biri değer içermeyen bir bağlantı tablosu ve iki veri tablosu, çünkü çoktan çoğa ilişkiler varlıklar değil, bu nedenle yalnızca Ürün ve Mağaza'ya bir varlık olarak sahip olabilirim.

Dolayısıyla, mantıksal olarak, veritabanı modelimi, depolanacak ve ürüne yönelik ilişkileri olan ayrı bir tablo olarak stok olacak şekilde değiştirmeyi denedim. Ayrıca, sorunun kaynağı olarak bunu dışlayabilmek için alan adlarını yeniden yazdım:

veritabanı düzeni değiştirildi

Sonra bulduğum şey, hala bir Stok varlığı alamadığım ve veritabanının kendisinde bir 'miktar' alanı bulunmadığıydı.

Bu mağazaları ve ürünleri bir stok tablosunda birbirine bağlayabilmem gerekiyordu (diğer şeylerin yanı sıra) ... bu nedenle, sadece ürünün kendisine stok eklemek bir seçenek değil.

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

Ve veritabanını oluşturduğumda, hisse senedi tablosunda hala bana doğru alanları vermiyor:

HeidiSQL'den görüldüğü şekliyle veritabanı düzeni

Bu yüzden, burada bazı şeylere baktığımda, çoktan çoğa bağlantıların varlıklar olmadığını ve dolayısıyla değerlere sahip olamayacaklarını öğrendim. Bu yüzden onu diğerleriyle ilişkileri olan ayrı bir tabloya dönüştürmeyi denedim, ama yine de işe yaramadı.

Burada neyi yanlış yapıyorum?


Tamam, Doctrine kullanarak çoktan çoğa bağlantı kurmanın mümkün olmadığını belirten birkaç söz buldum, bu ilişkileri önlemeyi tavsiye eden yorumlar var .. ama ya gerçekten anlattığım gibi bir duruma takılıp kalırsanız benim asıl sorum? Tamamen çoktan çoğa ilişkilere dayanan, Magento ile uyumlu bütün bir veritabanım var. Yani temelde bana "Doktrin ORM çoktan çoğa işleyemez, kullanma" deniyor mu?
Henry van Megen

Ayrıca bkz.
Doktrin2

3
Merak ettiğim şeyi bu kadar güzel bir şekilde açıklamak için göstermiş olduğunuz çaba için size +100 verir :-)
Torsten Römer

Yanıtlar:


143

Ek değerlerle Çoktan Çoğa ilişkilendirme, Çoktan Çoka değil, aslında yeni bir varlıktır, çünkü artık bir tanımlayıcıya (bağlı varlıklarla iki ilişki) ve değerlere sahiptir.

Yani Birçok-çok dernek çok nadir neden de sebebidir, aşağıdaki gibi onlara ek özellikler, saklamak eğilimindedir sorting, amountvb

Muhtemelen ihtiyacınız olan şey aşağıdaki gibi bir şeydir (Her iki ilişkiyi de çift yönlü yaptım, en az birini tek yönlü yapmayı düşünün):

Ürün:

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

Mağaza:

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

Stok, mevcut:

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

Tamam, bazı alıcılar ve ayarlayıcılar ekleyeceğim, çünkü bu kurulumla, yalnızca birincil anahtarları herhangi bir değer olmadan çalışır duruma
getiriyorum

Bu kurulumu kullandığımda ve ardından Stock.store_id kullanarak sorgulamayı denediğimde, "Stokta store_id adında alan veya ilişkilendirme yok" hatasını alıyorum. Sütun veritabanında bulunduğu için bulunmalıdır.
afilina

@afilina, şemayı oluştururken db'nin bir önemi yoktur - DBAL, sütunu DDL meta verilerinde (bellekte) bulamadığı için istisnayı atar
Ocramius

@Ocramius Demek istediğim, DB'nin meta verilerden üretildiğiydi. S Sütunu ilk etapta üretebildiyse, sorgu sırasında onu bulabilmelidir. Sorunumun çözümü Stock.store'u istenen id ile karşılaştırmaktı.
afilina

% 100 ihtiyacım olan şey ve bir cazibe gibi çalışıyor! Mağaza ve ürün başına miktarı düzenlemek için fieldset ile nasıl form oluşturacağınızı biliyor musunuz?
cwhisperer

17

Doktrin çoktan çoğa ilişkileri gayet iyi idare eder.

Karşılaştığınız sorun, basit bir ManyToMany ilişkilendirmesine ihtiyacınız olmamasıdır, çünkü ilişkilendirmeler "fazladan" veriye sahip olamaz.

Ortadaki (stok) tablonuz, product_id ve store_id'den fazlasını içerdiğinden, bu ekstra verileri modellemek için kendi varlığına ihtiyaç duyar.

Yani gerçekten üç sınıf varlık istiyorsunuz:

  • Ürün
  • Stok seviyesi
  • Mağaza

ve iki dernek:

  • Ürün oneToMany StockLevel
  • OneToMany StockLevel'i saklayın

1
Cevabınız için teşekkür ederim ! "Stok" gibi tabloma ekstra alanlar ekledim. Ancak, doktrin hala bu "birleştirme tablosunu" dikkate almıyor php app/console doctrine:mapping:import AppBundle ymlve şemayı veritabanından içe aktarmak için çalıştırdığımda atlıyor. Bu ekstra eşleme yaml dosyasını oluşturmasını istiyorum. Herhangi bir fikri olan var mı? :(
Stphane

"Bağlantı" varlığına veri yazmayı çözmeyen yanıt. Bu bir problem. Varlıkları beyan etmemek. Formdan verilerin aktarıldığı bir örneği destekleyebilirsiniz (CollectionType alanında EntityType alanı ile gömülü form vardır). Ben düzgün ana forma gömülmüş formdan veri aktarmak ve alanların koleksiyon tasarrufu olamaz
zoore
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.