Magento 2에서 커스텀 모델을로드하는 가장 좋은 방법


15

올바른 방법을 찾기가 어려웠으므로 아래에서 내가 만든 모범 사례를 찾을 수 있습니다. 즐기고, 필요한 경우 영어를 교정하고 내가 틀렸다면 나에게 말하십시오. :)

편집 : ... 그리고 나는 어떤면에서 잘못되었다는 것을 알았습니다. 그래서 Raphael의 답변으로 더 많은 것을 이해 한 후에 원래 게시물을 업데이트했습니다. 그에게 감사합니다!

아래에 사용 된 개념 :

이러한 개념에 익숙하면 아래 코드와 설명을 이해하는 것이 더 쉬울 것입니다.

  • 주입 의존성 ( $this->variable코드의 모든 변수가 주입 될 때)
  • 서비스 계약 및 리포지토리
  • 공장

맥락 :

더 많은 컨텍스트를 갖기 위해 다음과 같이 모듈을 올바르게 구성했다고 가정하십시오.

  • 방법을 포함하는 블록 클래스 CustomBlock getCustomModel($id),
  • 이 메소드는 param에 전달 된 id를 기반으로 CustomModel 객체를 반환합니다.
  • CustomModel 유형은 모델에 해당합니다. \Vendor\Module\Model\CustomModel
  • 이 모델은 (그것의 자원 모델과 함께 제공 \Vendor\Module\Model\ResourceModel\CustomModel)
  • (와)의 저장소와 함께 \Vendor\Module\Model\CustomModelRepository.

질문 :

  • 모든 것이 CustomModel 객체를로드하도록하는 가장 좋은 방법은 무엇입니까?

load()이 메소드는 더 이상 사용되지 않으므로 CustomModel 객체를 사용할 수 없습니다 .

모범 사례에 따르면 CustomModel 서비스 계약을 사용해야합니다. 서비스 계약은 데이터 인터페이스 (예 : CustomModelInterface) 및 서비스 인터페이스 (예 : CustomModelRepositoryInterface)입니다. 그래서 내 블록은 다음과 같습니다

/ ** @var SlideRepositoryInterface * /
보호 된 $ slideRepository;

/ **
 * CustomBlock 생성자
 * ...
 * @param CustomModelRepositoryInterface $ customModelRepository
 * ...
 * /
공공 함수 __construct (
...
CustomModelRepository 인터페이스 $ customModelRepository
...
) {
    $ this-> customModelRepository = $ customModelRepository;
}

공용 함수 getCustomModel ($ id) {
    return $ this-> customModelRepository-> get ($ id);
}

먼저 CustomModelRepositoryInterface생성자에 객체를 삽입 하고 getCustomModel()메서드 에서 사용합니다 .

수업 Api\CustomModelRepositoryInterface에는 많지 않습니다. 일반적으로 당신은 기본적인 방법을 선언합니다 (그러나 아무것도 다르게 할 방지 없음) : get, getList, save, delete, deleteById. 이 주제의 목적을 위해 다음은 get메소드 선언입니다.

/**
 * Get info by id
 *
 * @param int $id
 * @return Data\CustomModelInterface
 * @throws \Magento\Framework\Exception\NoSuchEntityException
 */
public function get($id);

좋아, 그러나 내 CustomModel Interface가 블록 생성자에서 의존성 주입에 의해 호출되면 코드는 어디에 있습니까? 이 질문에 대한 답을 위해서는이 인터페이스를 구현하는 클래스를 찾는 Magento에 설명해야합니다. 모듈의 etc / di.xml 파일에서 다음을 추가해야합니다.

<preference for="Vendor\Module\Api\CustomModelRepositoryInterface" type="Vendor\Module\Model\CustomModelRepository" />

그래서 CustomModelRepositoryInterface클래스는 서비스 인터페이스입니다. 그것을 구현할 때 데이터 인터페이스 (적어도 Vendor\Module\Api\Data\CustomModelInterfaceVendor\Module\Api\Data\CustomModelSearchResultsInterface) 를 구현해야합니다 . 모델은 각 인터페이스마다 라인 을 구현 Vendor\Module\Api\Data\CustomModelInterface하고 추가 <preference ... />해야합니다. 마지막으로 서비스 계약을 사용할 때마다 mySomethingInterface더 이상 생각 하지 마십시오 mySomething: magento가 di.xml환경 설정 메커니즘을 사용하도록하십시오 .

좋아, 다음은 무엇입니까? CustomModelRepositoryInterface블록 생성자를 주입 하면 CustomModelRepository객체를 얻습니다 . CustomModelRepository에 선언 된 메소드를 구현해야합니다 CustomModelRepositoryInterface. 그래서 우리는 이것을 가지고 있습니다 Vendor\Module\Model\CustomModelRepository:

공공 함수 get ($ id) {
    $ customModel = $ this-> customModelFactory-> create ();
    $ customModel->로드 ($ id);
    if (! $ customModel-> getId ()) {
      새로운 NoSuchEntityException 던지기 (__ ( 'ID가 "% 1"인 CustomModel이 없습니다.', $ id));
    }
    $ customModel을 반환;
}

우리는 무엇을하고 있습니까? CustomModel공장 덕분에 빈 객체를 만듭니다 . 다음으로 CustomModel모델로드 방법을 사용하여 데이터를로드합니다 . 다음으로 id를 매개 변수 NoSuchEntityException로로드하지 못하면 a를 반환합니다 CustomModel. 그러나 모든 것이 정상이면 모델 객체를 반환하고 수명을 계속합니다.

와우 ...! 이 예에서 그것은 무엇입니까?

$customModel->load($id);

load처음 과 같은 더 이상 사용되지 않는 방법입니까? 그렇습니다. 그것은 부끄러운 일이라고 생각하지만이 load () 메서드에는 이벤트가 전달되어 개발자가들을 수 있기 때문에 사용해야합니다 (아래 Raphael의 답변 참조).

앞으로는 엔터티 관리자가 저장합니다. 이것은 새로운 Magento 2 개념으로서의 또 다른 이야기이지만, 살펴보고 싶다면 Entity Manager가 이미 CMS 페이지의 리소스 모델 (v2.1)에 구현되어 있습니다.

public function load(AbstractModel $object, $value, $field = null)
{
    $pageId = $this->getPageId($object, $value, $field);
    if ($pageId) {
        $this->entityManager->load($object, $pageId);
    }
    return $this;
}

답변:


16

모범 사례 : 서비스 계약을 통해

최선의 방법은 가능할 때마다 항상 서비스 계약을 사용하는 것입니다. 당신은 여기에 이유의 목록을 찾을 수 있습니다 젠토 2 : 서비스 계약을 사용할 때의 이점은 무엇입니까?

서비스 계약을 구현하는 방법에 대한 자세한 내용은이 주제를 확인하는 것이 좋습니다. Magento 2에서 사용자 정의 모듈에 대한 서비스 계약을 구현하는 방법은 무엇입니까?

서비스 계약이없는 경우

사용 가능한 서비스 계약이없는 경우 모델 리포지토리 get방법을 사용해야합니다 . 이 방법을 사용하면 CategoryRepository클래스 와 같은 마 젠토 캐싱 시스템의 이점을 얻을 수 있습니다 .

public function get($categoryId, $storeId = null)
{
    $cacheKey = null !== $storeId ? $storeId : 'all';
    if (!isset($this->instances[$categoryId][$cacheKey])) {
        /** @var Category $category */
        $category = $this->categoryFactory->create();
        if (null !== $storeId) {
            $category->setStoreId($storeId);
        }
        $category->load($categoryId);
        if (!$category->getId()) {
            throw NoSuchEntityException::singleField('id', $categoryId);
        }
        $this->instances[$categoryId][$cacheKey] = $category;
    }
    return $this->instances[$categoryId][$cacheKey];
}

더 이상 사용되지 않는 load()방법

Magento 2는 상속 시스템을 삭제하고 새로운 2.1 EntityManager를 사용하여 컴포지션을 통해 구현함으로써 표준 CRUD 시스템에서 천천히 멀어지고 있습니다. 여기에서 세부 정보를 찾을 수 있습니다. Magento 2.1 : 엔티티 관리자 사용

또한 더 이상 사용되지 않는 CRUD 메소드에 대한이 흥미로운 주제를 읽도록 제안합니다. 추상 모델에서 더 이상 사용되지 않는 저장 및로드 메소드

자원 모델로드를 사용하지 않는 이유

가장 큰 이유는 자원 모델이 사용하는 경우이다 load방법을, 당신은 모델에서 구현되는 로딩 시스템의 중요한 부분을 건너 뛸 load방법을 참조하십시오 Magento\Framework\Model\AbstractModel:

public function load($modelId, $field = null)
{
    $this->_beforeLoad($modelId, $field);
    $this->_getResource()->load($this, $modelId, $field);
    $this->_afterLoad();
    $this->setOrigData();
    $this->_hasDataChanges = false;
    $this->updateStoredData();
    return $this;
}

자원 모델 load메소드를 직접 호출하면 다음과 같은 영향이 있습니다.

  • _beforeLoad 호출되지 않음 : 따라서 이벤트가 전달되기 전에 모델로드
  • _afterLoad 호출되지 않음 : 따라서 이벤트가 전달되지 않은 후 모델로드
  • 저장된 데이터는 업데이트되지 않으므로 다양한 문제가 발생할 수 있습니다 (예 : prepareDataForUpdate에서 호출 하는 경우 Magento\Framework\Model\ResourceModel\Db\AbstractDb)

감사합니다 Raphael, 당신이 말하는 모든 것이 말이되고 내 지식을 완성합니다. 그러나 KAndy가 Marius가 자신의 사용자 정의 모듈 자원 모델의 load () 메소드를 사용할 수 있다고 설명하는 이유를 이해할 수 없습니다. [ magento.stackexchange.com/questions/114929/… 추상 모델의 저장 및로드 방법)에 있습니다. 어떤 아이디어?
Nicolas PERNOT

@NicolasPERNOT 기본적으로 KAndy는 목표는 모든 모듈에 대해 SL (Service Layer)을 갖는 것이며 엔터티를로드 할 때마다 사용해야하는 것이라고 설명합니다. 나는 그가 내 생각 젠토 Inc의 직원입니다 그가 당신을 계몽 할 수 있습니다 어쩌면 그를 언급에 의해 당신에게 의견을 제시
라파엘 디지털에서 Pianism

글쎄, 나는 마침내 내 원래 게시물을 업데이트했습니다. 도와 주셔서 감사합니다.
Nicolas PERNOT

적어도 Magento 2.2에서 중요한 중요한 것은 ResourceModel의로드에 포함되어 있으므로 ResourceModel 메소드를 직접 사용하는 것은 좋지 않습니다.
Jānis Elmeris

현재 Resource Model load()방법을 사용하여 Model을 안전하게로드 할 수 있습니다 . 자원 모델은 자신의 모델의 메소드 호출 load()방법 : $model->beforeLoad() { $this->_beforeLoad() }$model->afterLoad() { $this->_afterLoad() }
sergei.sss

-2

다음 진술은 현재 유효하지 않다고 생각합니다.

Why not using the resource model load

Magento\Framework\EntityManager\Observer모든 이벤트 폴더 를 찾을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.