İnversedBy ve mappedBy arasındaki fark nedir?


103

Zend Framework 2 ve Doctrine 2 kullanarak uygulamamı geliştiriyorum.

Ek açıklamalar yazarken mappedByve arasındaki farkı anlayamıyorum inversedBy.

Ne zaman kullanmalıyım mappedBy?

Ne zaman kullanmalıyım inversedBy?

Ne zaman ikisini de kullanmamalıyım?

İşte bir örnek:

 /**
 *
 * @ORM\OneToOne(targetEntity="\custMod\Entity\Person", mappedBy="customer")
 * @ORM\JoinColumn(name="personID", referencedColumnName="id")
 */
protected $person;

/**
 *
 * @ORM\OneToOne(targetEntity="\Auth\Entity\User")
 * @ORM\JoinColumn(name="userID", referencedColumnName="id")
 */
protected $user;

/**
 *
 * @ORM\ManyToOne (targetEntity="\custMod\Entity\Company", inversedBy="customer")
 * @ORM\JoinColumn (name="companyID", referencedColumnName="id")
 */
protected $company;

Hızlı bir arama yaptım ve aşağıdakileri buldum, ancak hala kafam karıştı:

Yanıtlar:


159
  • mappedBy , bir (çift yönlü) ilişkilendirmenin ters tarafında belirtilmelidir
  • inversedBy , (çift yönlü) bir ilişkinin sahibi tarafında belirtilmelidir

doktrin belgelerinden:

  • ManyToOne, her zaman çift yönlü bir derneğin sahibi olan taraftır.
  • OneToMany her zaman çift yönlü bir ilişkinin ters tarafıdır.
  • Bir OneToOne ilişkilendirmesinin sahip tarafı, yabancı anahtarı içeren tabloya sahip varlıktır.

Bkz. Https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html


1
İşin garibi, Doktrin dokümantasyon yazarı, muhtemelen en yaygın olarak kullanılan, çoka bir çift yönlü haritalamanın yaml örneğini dışarıda bırakmaya karar verdi!
Peter Wooster

4
@PeterWooster, en iyi uygulama, o zaman varlık hakkında tüm bilgileri tek bir yerde toplayacağınız için Ek Açıklamaları kullanmaktır!
Andreas Linden

Bu aynı zamanda birçok ilişki için de geçerlidir. Bunlar için: çoktan çoğa bir derneğin sahibi olan tarafını kendiniz seçebilirsiniz.
MB

5
@AndreasLinden'in yaygın olarak kullanılması, en iyi uygulama anlamına gelmez. Anında kod yazmak için yorumları kullanan bir şey hiçbir zaman en iyi uygulama olarak kabul edilemez, php yerel değildir ve hatta varsayılan olarak tüm çerçevelere dahil edilmez. Bir varlık hakkındaki tüm bilgileri tek bir yerde bulundurmak, bir anti-argümandır. Tüm kodunuzu tek bir yerde gruplamak ne zamandan beri iyi bir şeydir? Projenizdeki organizasyonu yazmak, sürdürmek ve küçültmek acıdır. en iyi pratik ? Duh.
JesusTheHun

4
@JesusTheHun sen elma ve armutları karşılaştırıyorsun. "tüm kod", "bir varlık hakkındaki tüm bilgiler" den çok farklıdır;)
Andreas Linden

56

Yukarıdaki cevaplar neler olup bittiğini anlamam için yeterli değildi, bu yüzden biraz daha derinlemesine inceledikten sonra, anlamaya çalıştığım gibi mücadele eden insanlar için mantıklı olacak bir açıklama yolum olduğunu düşünüyorum.

inversedBy ve mappedBy, INTERNAL DOCTRINE motoru tarafından ihtiyaç duyduğunuz bilgileri almak için yapması gereken SQL sorgularının sayısını azaltmak için kullanılır . İnversedBy veya mappedBy eklemezseniz açık olmak gerekirse, kodunuz yine de çalışır ancak optimize edilmeyecektir .

Örneğin, aşağıdaki sınıflara bakın:

class Task
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="task", type="string", length=255)
     */
    private $task;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="dueDate", type="datetime")
     */
    private $dueDate;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="tasks", cascade={"persist"})
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $category;
}

class Category
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity="Task", mappedBy="category")
     */
    protected $tasks;
}

Bu sınıflar, şemayı oluşturmak için komutu çalıştırırsanız (örneğin bin/console doctrine:schema:update --force --dump-sql), Kategori tablosunda görevler için bir sütun olmadığını fark edeceksiniz. (bunun nedeni, üzerinde sütun ek açıklaması olmamasıdır)

Burada anlaşılması gereken önemli şey, değişken görevlerin yalnızca orada olmasıdır, böylece dahili doktrin motoru, üstündeki mappedBy Category yazan referansı kullanabilir. Şimdi ... burada benim gibi karıştırmayın ... Kategori, SINIF ADINA atıfta bulunmuyor, Görev sınıfındaki 'korumalı $ kategori' adlı özelliğe atıfta bulunuyor.

Bilge gibi, Görevler sınıfında $ category özelliği bunun tersBy = "görevler" olduğundan bahseder, bunun çoğul olduğuna dikkat edin, bu SINIF ADININ ÇOĞULU DEĞİLDİR , ancak özelliğin Kategori içinde 'korumalı $ görevler' olarak adlandırılması nedeniyle sınıf.

Bunu anladıktan sonra, inversedBy ve mappedBy'nin ne yaptığını ve bu durumda nasıl kullanılacağını anlamak çok kolay hale gelir.

Örneğimdeki 'görevler' gibi yabancı anahtara başvuran taraf her zaman inversedBy özniteliğini alır çünkü o sınıfta hangi sınıfın (targetEntity komutu aracılığıyla) ve hangi değişkenin (inversedBy =) 'geriye doğru çalışacağını' bilmesi gerekir. konuşun ve kategori bilgilerini alın. Bunu hatırlamanın kolay bir yolu, foreignkey_id'ye sahip olan sınıf, inversedBy'ye sahip olması gereken sınıftır.

Kategori ve onun $ tasks özelliği (tabloda olmayan, optimizasyon amaçları için sınıfın sadece bir kısmı hatırlayın) MappedBy 'görevler' olduğunda, bu iki varlık arasındaki ilişkiyi resmi olarak oluşturur, böylece doktrin artık güvenle iki ayrı SELECT deyimi yerine JOIN SQL deyimleri kullanın. MappedBy olmadan, doktrin motoru JOIN ifadesinden bilemez, kategori bilgisini yerleştirmek için 'Görev' sınıfında hangi değişkeni yaratır.

Umarım bu biraz daha iyi açıklar.


6
Bu çok iyi açıklanmıştır ve çabanız için teşekkür ederiz. Laravel Eloquent'ten doktrine geldim ve buradaki mantığı anlamak benim için zordu. Aferin. Category is NOT referring TO THE CLASS NAME, its referring to the property on the Task class called 'protected $category'tüm ihtiyacım olan. Sadece sorunumu çözmedi, aynı zamanda anlamama da yardımcı oldu. En iyi cevap IMO :-)
The Alpha

1
Ben de Eloquent'ten geldim, bu bana çok yardımcı oldu. Şu anki tek anlaşmazlığım bunun için ayarlayıcıyı / alıcıyı nasıl ayarlayacağım, hala bunun iplerini öğreniyorum
Eman

1
Evet, bu gerçekten çok kolay ve hatta bazı araçlarla otomatik hale getirildi, benimle daha sonra sohbet etmeye başlayın ve size yardımcı olabilirim
Joseph Astrahan,


1
symfony.com/doc/current/doctrine/associations.html , bu aslında öğrenmek daha iyidir, symfony doktrini kullanır, böylece size aynı şeyi öğretecektir.
Joseph Astrahan

21

Çift yönlü ilişkide hem sahip hem de ters taraf vardır

mappedBy : iki yönlü bir ilişkinin ters tarafına koyun Sahip olan tarafa atıfta bulunmak için

inversedBy : iki yönlü bir ilişkinin sahip tarafına koy Ters tarafına atıfta bulunmak için

VE

OneToOne , OneToMany veya ManyToMany eşleme bildirimiyle kullanılan mappedBy özniteliği.

inversedBy OneToOne, ManyToOne veya ManyToMany haritalama bildirimiyle kullanılan özelliktir.

İkaz : Çift yönlü ilişkinin sahibi olan taraf, yabancı anahtarı içeren taraftır.

inversedBy ve mappedBy into Doctrine Documentation hakkında iki referans var: İlk Bağlantı , İkinci Bağlantı


1
bağlantılar öldü mü?
Scaramouche

2

5.9.1. Sahiplik ve Ters Taraf

Çoktan Çoğa ilişkilendirmeler için hangi varlığın sahip olduğunu ve hangisinin ters tarafını seçebilirsiniz. Geliştiriciler açısından hangi tarafın sahip olmak için daha uygun olduğuna karar vermek için çok basit bir anlamsal kural vardır. Sadece bağlantı yönetiminden hangi varlığın sorumlu olduğunu kendinize sormanız ve bunu sahip olan taraf olarak seçmeniz gerekir.

Makale ve Etiket adlı iki varlık örneğini ele alalım. Bir Makaleyi bir Etikete bağlamak istediğinizde ve bunun tersi de, bu ilişkiden sorumlu olan çoğunlukla Makaledir. Yeni bir makale eklediğinizde, onu mevcut veya yeni etiketlerle birleştirmek istersiniz. Makale oluşturma formunuz muhtemelen bu fikri destekleyecek ve etiketleri doğrudan belirtmenize izin verecektir. Bu nedenle, kodu daha anlaşılır kıldığı için Makaleyi sahiplik tarafı olarak seçmelisiniz:

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html

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.