Doktrin 2'de Vekil Nedir?


112

Doctrine 2 belgelerinin tamamını okumayı yeni bitirdim, kendi sandbox'ımı başlattım, ilkelerin çoğunu anladım, ancak hala bir soru var ve belgede tam bir açıklama bulamadım.

  1. Nelerdir Proxysınıflar?
  2. Bunları varlıklar üzerinde ne zaman kullanmalıyım?

Anladığım kadarıyla, proxy sınıfları varlıklarınıza başka bazı özellikler eklemenize izin veren bir katman ekler, ancak yöntemleri varlık sınıfında uygulamak yerine neden bir proxy kullanasınız?

Yanıtlar:


160

GÜNCELLEME

Bu yanıt, proxy nesneler ve kısmi nesneler arasındaki farklar hakkında yanlış bilgiler içerir. Daha fazla ayrıntı için @ Kontrollfreak'in cevabına bakın: https://stackoverflow.com/a/17787070/252591


Proxy nesneleri, sorgunuz bir varlık oluşturmak için gereken tüm verileri döndürmediğinde kullanılır. Aşağıdaki senaryoyu hayal edin:

@Entity
class User {
     @Column protected $id;
     @Column protected $username;
     @Column protected $firstname;
     @Column protected $lastname;

     // bunch of setters/getters here
}

DQL query:

SELECT u.id, u.username FROM Entity\User u WHERE u.id = :id

Gördüğünüz gibi bu sorgu dönmez firstnameve lastnameözellikler, bu nedenle Usernesne oluşturamazsınız . Eksik varlık oluşturulması beklenmeyen hatalara yol açabilir.

Bu nedenle Doctrine, UserProxytembel yüklemeyi destekleyen nesneler yaratacaktır . Özelliğe erişmeye çalıştığınızda firstname(yüklenmemiş olan), ilk önce bu değeri veritabanından yükleyecektir.


Demek istediğim, neden bir proxy kullanmalıyım?

Kodunuzu her zaman proxy nesneleri kullanmamış gibi yazmalısınız. Doctrine tarafından kullanılan iç nesneler olarak değerlendirilebilirler.

Geç yükleme neden Varlığın kendisinde uygulanamıyor?

Teknik olarak olabilir, ancak rastgele bir proxy nesnesinin sınıfına bir göz atın. Kirli kodlarla dolu, ugh. Varlıklarınızda temiz bir koda sahip olmak güzel.

Bana bir kullanım alanı sağlayabilir misiniz?

En son 25 makalenin bir listesini görüntülüyorsunuz ve birincisinin ayrıntılarını görüntülemek istiyorsunuz. Her biri büyük miktarda metin içerir, bu nedenle tüm bu verileri getirmek hafıza kaybı olur. Bu yüzden gereksiz verileri getirmiyorsunuz.

SELECT a.title, a.createdAt
FROM Entity\Article a
ORDER BY a.createdAt DESC
LIMIT 25

$isFirst = true;
foreach ($articles as $article) {
    echo $article->getTitle();
    echo $article->getCreatedAt();

    if ($isFirst) {
        echo $article->getContent(); // Article::content is not loaded so it is transparently loaded 
                                     // for this single article.

        $isFirst = false;
    }
}

Cevabınız için teşekkürler, Kısmi Nesne ile olan farkı nedir? Demek istediğim, neden bir proxy kullanmalıyım? Geç yükleme neden Varlığın kendisinde uygulanamıyor? Bana bir kullanım alanı sağlayabilir misiniz?
Jérémy

1
Kısmi nesneler ve proxy nesneler aynı şeydir - eşanlamlılar olarak değerlendirilebilirler. Geri kalan sorular için güncellenmiş cevabımı kontrol edin.
Crozin

1
Niteliklerin yarısına sahipse, doktrinin nesneyi neden yaratamayacağını anlamıyorum. Php'de tüm özellikleri ayarlamasam bile bir nesne oluşturabiliyorum.
sanders

1
Bu tamamen harika bir cevap ve belgelerde yer almalı.
Jimbo

7
Bu cevap, vekiller ve kısmi nesneler hakkında bazı ciddi yanlış anlamaları içermektedir. Bkz Cevabımı anlamaya.
Kontrollfreak

81

Proxy

Bir Doctrine proxy'si, bir varlık sınıfını kendisi için Lazy Loading sağlamak üzere genişleten bir sarmalayıcıdır.

Varsayılan olarak, Varlık Yöneticisinden başka bir varlıkla ilişkilendirilmiş bir varlığı sorduğunuzda, ilişkili varlık veritabanından yüklenmez, ancak bir proxy nesnesine sarılır. Uygulamanız daha sonra bir özelliği talep ettiğinde veya bu proxy varlığın bir yöntemini çağırdığında, Doctrine varlığı veritabanından yükleyecektir (her zaman proxy tarafından bilinen kimliği talep ettiğiniz durumlar hariç).

Proxy'nin varlık sınıfınızı genişletmesi nedeniyle bu, uygulamanız için tamamen şeffaf olur.

Doktrin, JOINsorgunuzda yoksa veya getirme modunu olarak ayarlamazsanız, ilişkilendirmeleri varsayılan olarak tembel yük vekilleri olarak nemlendirir EAGER.


Şimdi bunu eklemeliyim çünkü her yerde yorum yapacak kadar itibarım yok:

Ne yazık ki Crozin'in cevabı yanlış bilgiler içeriyor.

Gibi bir DQL sorgusu yürütürseniz

SELECT u.id, u.username FROM Entity\User u WHERE u.id = :id

bir (vekil) varlık nesnesi değil, ilişkilendirilebilir bir dizi elde edersiniz. Bu nedenle herhangi bir ek özelliği tembel olarak yüklemek mümkün değildir.

Bunu akılda tutarak, kullanım örneği örneğinin de işe yaramayacağı sonucuna varılır. $articleNesne olarak erişmek için DQL'in böyle bir şeye değiştirilmesi gerekir :

SELECT a FROM Entity\Article a ORDER BY a.createdAt DESC LIMIT 25

Ve tarafından döndürülen getContent()mülkün, 25 varlığın tümünün içerik özelliklerini yüklememek için bir ilişkilendirme olması gerekir .


Kısmi Nesneler

İlişkilendirme olmayan varlık özelliklerini kısmen yüklemek istiyorsanız, bu Doktrini açıkça belirtmeniz gerekir:

SELECT partial u.{id, username} FROM Entity\User u WHERE u.id = :id

Bu size kısmen yüklenmiş bir varlık nesnesi verir.

Ancak kısmi nesnelerin proxy olmadığına dikkat edin ! Tembel Yükleme onlar için geçerli değildir. Bu nedenle, kısmi nesnelerin kullanılması genellikle tehlikelidir ve bundan kaçınılmalıdır. Daha fazla bilgi edinin: Kısmi Nesneler - Doctrine 2 ORM 2 belgeleri


1
Teşekkürler, bu Doctrine'in Proxy'leri ve Kısmi Nesneleri nasıl kullandığı hakkında, kabul edilen yanıttan çok daha fazla ayrıntı sağlar! Dokümanlara atıfta bulunmak da faydalıdır.
Sean Bean

1
Ayrıca referans için, Proxy nesneleriyle ilgili dokümanların bölümü: doctrine-orm.readthedocs.org/en/latest/reference/…
Sean the Bean

Öyleyse, istekli bir yük yaparken, temelde sadece sonuç kümeleri mi ekliyor?
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.