모델을로드하는 올바른 방법은 무엇이며 왜


9

나는 Magento에 대해 많은 경험을 가지고 있지만 모델을로드하는 방법이 올바른 방법과 이유를 이해하지 못한다는 것을 깨달았습니다. 나는 주제에 관해 내가 할 수있는 모든 것을 읽었지만 이것과 같은 것을 설명하는 사람들은 실제로 설명하기에 충분히 깊이 들어 가지 않습니다. 왜이 특정 방법을 다른 방법 대신 사용합니까? 로드하려는 모델에 대한 리포지토리가 없다고 가정 해 봅시다.

지금까지는 항상 생성자에서 모델을 사용한 다음 간단히로드했습니다.

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

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

그리고 그것은 항상 의도 한대로 작동했습니다. 나는 또한 그것이 코어에서 일반적으로 사용되었거나 적어도 일반적으로 사용되었다고 확신합니다.

하지만 동료 중 한 명이

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

예를 들어, 새 제품을 생성하려는 경우 팩토리가 새 엔티티를 작성하는 데 사용되는 것으로 이해하면 팩토리를 작성하고 데이터로 채운 후 저장할 수 있습니다. 그러나 다시 주제를 연구하기 시작했고 Fabian Schmengler ( Magento 2의 리포지토리 및 팩토리를 사용해야하는시기? )의 사례를 보았습니다. t 왜 그것이 서비스 계약의 일부가 아니라고 말하는 것 외에는 설명하지 마십시오. 리포지토리가 서비스 계약의 일부라는 것을 이해하는 한 리포지토리를 통해 사용할 수없는 모델을로드 할 때 여기에 연결이 표시되지 않습니다.

혼란을 더하기 위해 생성 된 modelFactory에서 resourceModel을 가져 와서 모델을로드하는 방법을 찾았습니다 .Vinai Kopp ( Magento 2에서 사용자 정의 모듈에 대한 서비스 계약을 구현하는 방법? ) 가 제시했습니다. 리소스 모델을 직접 사용해서는 안된다는 것을 항상 읽었으므로 완전히 사라졌습니다.

예, 누군가 올바른 방법과 다른 방법 대신 사용해야하는 이유를 말해 줄 수 있습니까?


문자 그대로 혼란스러운 예제를 포함 하여이 스레드를 연결하고 있습니다. 내 게시물을 읽었습니까?
czs

1
좋은 질문입니다. 나중에 자세히 답변 할 시간을 찾도록하겠습니다. 나는 이미 많은 것을 말해 줄 수 있습니다 : 자신의 모델 (Vinai의 예) 또는 코어 또는 타사 모듈의 모델 (내 대답)을로드하는 경우는 다릅니다. 또한 생성자를 통해 모델을 주입하면 매번 동일한 인스턴스가 제공되므로 원하지 않는 부작용이 발생할 수 있습니다.
Fabian Schmengler

답변:


12

문제의 모델을 확인해야 할 첫 번째 단계는 다음과 같습니다. 리포지토리 서비스 계약이 있습니까? 그렇다면 서비스 계약은 시맨틱 버전 관리에 묶여 있고 Magento 3.x가 나올 때까지 계속 작동 할 것이므로이를 사용하십시오. 말할 필요도없이, 지속성을 필요로하는 모델로 자신의 모듈을 만들 때는 해당 저장소도 작성해야합니다.

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

저장소가 없으면 자원 모델을 사용하십시오 . 자원 모델에는 상태가 포함되어 있지 않습니다. '일반'모델에 지속성을 사용하고 있습니다. 따라서 공장을 사용하여 포함시킬 필요는 없습니다.

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

"자원 모델에 비해 서비스 계약 / 리포지토리가 제공하는 이점은 무엇입니까?" 당신은 요청할 수 있습니다. 이론적으로 자원 모델데이터 모델 의 지속성에 대해서만 책임을 져야하는 반면, 저장소 는 엔티티 저장과 관련된 추가 작업도 고려합니다. 색인 업데이트, 다른 엔티티와의 관계 작성 등을 고려하십시오. 실제 상황에서는 이러한 선이 상당히 희미 해지는 경향이 있지만 이론입니다. 그러나 이것을 명심하는 것이 좋습니다.

당신은 모델 '직접 사용 save(), load()등 -methods을. 의미 상 올바르지 않기 때문에 더 이상 사용되지 않습니다. SOLID 방식으로 생각해보십시오.

  • (데이터) 모델은 데이터를 포함해야합니다.
  • 자원 모델은 그러한 데이터의 지속성을 책임 져야합니다.
  • 저장소는 지속성 조치를 위해 모듈 내부 및 외부 의 통신을 담당해야합니다 .

이상적인에, 다른 모듈과 통신 할 때 세계 하나를해야합니다 그리고 그것은 차이를 만드는 마지막 지점입니다 결코 , 그 모듈의 내부 지속적 논리에 의존 할 필요가 없습니다 (또는 그 중 하나가 그 문제에 대한 공공 방법을하지만 그것은 또 다른 논의의) 모듈의 서비스 계약 에서 제공하는 기능 만 사용하십시오 .

결론적으로

귀하의 질문에 대답하려면 : 선호하는 순서대로. 모델을로드하는 올바른 방법은 다음과 같습니다.

  • 리포지토리가있는 경우 리포지토리를 사용하여로드하십시오.
  • 리포지토리가없는 경우에만 리소스 모델 (공장과 함께 사용)을 사용하십시오.

1
좋아, 그래서 올바르게 따라 가면-새로운 데이터를 수정 / 추가하고 데이터베이스에 저장하려면 Resource Model을 사용해야하고 데이터를 메모리에로드하고 싶다면 Factory를 사용해야합니까? 그래서 생성자에서 Model 클래스를 사용하는 것처럼 일반 Model을 직접 사용해야하는 상황이 있습니까?
czs

@czs 당신은 맞습니다. 같은 모델 로딩에 대해 더 설명적인 예제를 추가했습니다.
Milind Singh

2
  • Models 데이터 인터페이스는 객체의 데이터 만 보유하는 데 사용됩니다. setget행에 대한 데이터를.
  • ResourceModels이러한 데이터의 지속성을 담당하는 메커니즘입니다. 즉, 실제로는 SQL 쿼리를 실행 save하거나 객체에 load데이터를 저장 Model합니다.

올바른 방법 loadsave만들어되어야 저장소 또는 리소스에서 로딩을 다음과 같이

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

여기서는 Model에 \MyVendor\MyModule\Api\Data\QueueInterface의해 암시됩니다 Queue.

따라서 배후에서 실제로 Model객체를 만든 다음 객체 loading별로 ResourceModel객체를 만듭니다. 이것이로드하거나 저장하는 올바른 방법입니다.

        $queue = $this->modelFactory->create();
        $this->resource->load($queue, $id);
        return $queue;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.