Bir modeli yüklemek için doğru yol nedir ve neden?


9

Magento ile ilgili çok fazla deneyimim var, ancak bir modelin hangi yolunun yüklenmesinin doğru olduğunu ve neden olduğunu anlamadığımı fark ettim. Konu hakkında yapabileceğim her şeyi okudum ama böyle şeyler açıklayan insanlar açıklamak için yeterince derin gitmiyor, neden bu yöntemi başka bir yöntem yerine kullanmıyorlar. Diyelim ki yüklemek istediğim model için bir depo yok.

Şimdiye kadar yapıcıda her zaman model kullanıyordum ve sonra yükledim.

public function __construct(
    \Vendor\Module\Model\Something $somethingModel
) {
    $this->somethingModel = $somethingModel;
}

public function getTestById($id) {
    return $this->somethingModel->load($id);
}

Ve her zaman amaçlandığı gibi çalıştı, eminim ya da en azından çekirdekte yaygın olarak kullanıldığından eminim.

Ama sonra meslektaşlarımdan birinin

modelFactory->create()->load($id)

Fabrikaların yeni bir varlık oluşturmak için kullanıldığını anladığım kadarıyla, örneğin, yeni bir ürün oluşturmak istersem, o zaman fabrikayı oluşturabilir, verilerle doldurabilir ve kaydedebilirim. Ama sonra tekrar, konuyu araştırmaya başladım ve modeli bu şekilde yükleyen ve başkalarının sadece modelleri yüklemekten vazgeçiren Fabian Schmengler'den ( Magento 2'de Bir Depo ve Fabrika Ne Zaman Kullanmalıyız? ) Örnek gördüm. neden bunun 'hizmet sözleşmesinin bir parçası olmadığını' söylemenin yanı sıra nedenini açıklamayın. Depoların hizmet sözleşmelerinin bir parçası olduğunu anladığım kadarıyla, bir depo aracılığıyla bulunmayan modelleri yüklemek söz konusu olduğunda burada herhangi bir bağlantı görmüyorum.

Biraz daha karışıklık eklemek için, oluşturulan modelFactory'den resourceModel'i alarak modeli yüklemenin bir yolunu buldum, Vinai Kopp ( Magento 2'de özel bir modül için hizmet sözleşmesi nasıl uygulanır? ) Ve şimdi ben kaynak modellerini doğrudan kullanmamam gerektiğini her zaman okuduğum için tamamen kayboldum.

Öyleyse, biri bana hangisinin doğru yol olduğunu ve diğer tüm yöntemler yerine neden kullanmam gerektiğini söyleyebilir mi?


Kelimenin tam anlamıyla kafa karıştırıcı örnek içeriyor olarak bağlıyorum, yazımı bile okudun mu?
czs

1
Güzel soru, daha sonra ayrıntılı olarak cevaplamak için zaman bulmaya çalışacağım. Size zaten çok şey söyleyebilirim: kendi modellerinizi (örneğin Vinai tarafından) veya çekirdek veya üçüncü taraf modüllerin modellerini (cevabım) yüklerseniz farklı bir durum. Ayrıca, modelin yapıcı yoluyla enjekte edilmesi, her seferinde aynı örneği verecektir, bu da istenmeyen yan etkilere neden olabilir.
Fabian Schmengler

Yanıtlar:


12

Peki, söz konusu model için kontrol etmeniz gereken ilk adım şudur: Havuz Hizmet Sözleşmesi var mı? Eğer öyleyse, bunu kullanın, çünkü Hizmet Sözleşmeleri semantik sürümlemeye bağlıdır ve Magento 3.x çıkana kadar olması gerektiği gibi davranmaya devam edecektir. Söylemeye gerek yok, kalıcılık gerektiren modellerle kendi modüllerinizi oluştururken, bunun için de depo yazmalısınız.

public function __construct(
    \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
) {
    $this->productRepository = $productRepository;
    /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
    $this->productRepository->save($product);
}

Havuz yoksa, kaynak modelini kullanın . Kaynak modellerin bir durum içermediğini unutmayın: 'normal' modelleri için kalıcılık kullanıyorlar. Bu nedenle, bunları bir fabrika kullanarak eklemeniz gerekmez:

public function __construct(
    \Magento\Catalog\Model\ResourceModel\Product $productResource,
    \Magento\Catalog\Model\ProductFactory $productFactory
) {
    $this->productResource = $productResource;
    $this->productFactory = $productFactory;
    ...
    /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
    $product = $this->productFactory->create();
    $this->productResource->save($product);
}

"Öyleyse, bir Kaynak Model üzerinden bir Hizmet Sözleşmesi / Deposu hangi fayda sağlar?" sorabilirsiniz. Teoride, bir Kaynak Model yalnızca bir Veri Modelinin kalıcılığından sorumlu olmalıdır , buna karşılık bir Havuz da bir varlığın kaydedilmesiyle ilgili ek görevleri dikkate alır. Dizinleri güncellemeyi, diğer varlıklarla ilişkiler vb. Yaratmayı düşünün. Bu teoridir, ancak gerçek hayatta bu çizgiler oldukça sık bulanıklaşma eğilimindedir. Ancak bunu akılda tutmak kendiniz için iyidir.

Sen olmamalıdır modelleri doğrudan kullanmak save(), load()vb -Kullanılan. Anlamsız olduğu için kullanımdan kaldırıldı. Bunu katı bir şekilde düşünün:

  • (Veri) Modeller yalnızca veri içermekten sorumlu olmalıdır.
  • Bu tür verilerin kalıcılığından Kaynak Modelleri sorumlu olmalıdır.
  • Depolar, kalıcılık eylemleri için modülün içindeki ve dışındaki iletişimden sorumlu olmalıdır .

Ve bu fark yaratan son nokta: diğer modüllerle iletişim kurarken, ideal bir dünyada bu modüllerin dahili kalıcı mantığına (ya da bu konudaki herkese açık yöntemlerinden herhangi birine) asla güvenmek zorunda kalmamalı , ama bu başka bir tartışma, ancak yalnızca modüllerin Hizmet Sözleşmeleri tarafından sağlanan işlevleri kullanın .

Sonuç olarak

Sorunuzu cevaplamak için: tercih sırasına göre. Bir modeli yüklemenin doğru yolu:

  • Bir Depo varsa, Depoyu kullanarak yükleyin.
  • Yalnızca Havuz yoksa Kaynak Modelini kullanın (fabrika ile birlikte).

1
Tamam, bu yüzden doğru takip edersem - yeni verileri değiştirmek / eklemek ve veritabanına kaydetmek istediğimde Kaynak Modelini kullanmalıyım ve wen belleğe veri yüklemek istiyorum o zaman Fabrika kullanmalıyım? Öyleyse normal Model'i doğrudan kullanmam gereken herhangi bir durum var mı (yapıcıda bir Model sınıfında olduğu gibi)?
czs

@czs Aynı model yükleme için daha açıklayıcı bir örnek ekledim.
Milind Singh

2
  • ModelsVeri Arabirimi yalnızca nesnelerdeki verileri tutmak için kullanılır, yani bir satıra setve getbir satıra ait veriler.
  • ResourceModelsbu tür verilerin kalıcılığından sorumlu olan bir mekanizmadır, yani nesneye gerçek saveveya loadveri SQL sorgusu yürütmek Model.

İçin doğru bir şekilde loadve savebir oluşturarak olmalıdır depo ya da bir kaynaktan yükleme aşağıdaki gibi:

namespace MyVendor\MyModule\Model;

class QueueRepository impliments \MyVendor\MyModule\Api\QueueRepositoryInterface
{

    /** @var \MyVendor\MyModule\Model\ResourceModel\Queue  */
    public $resource;

    /** @var \MyVendor\MyModule\Model\QueueFactory  */
    public $modelFactory;

    public function __construct(
        \MyVendor\MyModule\Model\ResourceModel\Queue $resource,
        \MyVendor\MyModule\Model\QueueFactory $modelFactory
    ) {
        $this->resource = $resource;
        $this->modelFactory = $modelFactory;
    }

    /**
     * Save
     * @param \MyVendor\MyModule\Api\Data\QueueInterface $queue
     * @return $queue
     * @throws \Exception
     */
    public function save(\MyVendor\Integrator\Api\Data\QueueInterface $queue)
    {
        $this->resource->save($queue);
        return $queue;
    }

    /**
     * Save
     * @param \MyVendor\MyModule\Api\Data\QueueInterface $queue
     * @param int $id
     * @return $queue
     * @throws \Exception
     */
    public function load(\MyVendor\MyModule\Api\Data\QueueInterface $queue, $id)
    {
        $this->resource->load($queue, $id);
        return $queue;
    }

    public function getById($id)
    {
        $queue = $this->modelFactory->create();
        $this->resource->load($queue, $id);
        return $queue;
    }
}

Burada, Model \MyVendor\MyModule\Api\Data\QueueInterfacetarafından alıştırılmıştır Queue.

Yani, perde arkasında, aslında bir Modelnesne yaratıyoruz, sonra loadingo ResourceModelnesne tarafından . Bu, yüklemek veya kaydetmek için doğru yoldur.

        $queue = $this->modelFactory->create();
        $this->resource->load($queue, $id);
        return $queue;
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.