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


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 데이터 인터페이스는 객체의 데이터 만 보유하는 데 사용됩니다. set 및 get행에 대한 데이터를.
  • ResourceModels이러한 데이터의 지속성을 담당하는 메커니즘입니다. 즉, 실제로는 SQL 쿼리를 실행 save하거나 객체에 load데이터를 저장 Model합니다.

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

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.