마 젠토 2 헬퍼 인스턴스


11

Magento 2에서 DI 시스템을 둘러싼 머리를 감은 것으로 생각되면 무언가가 나오고 포장이 풀립니다.
핵심 코드에서 도우미에 액세스하는 다른 방법을 봅니다.
예를 들어 다음과 Magento\Catalog\Controller\Category::_initCategory같습니다.

if (!$this->_objectManager->get('Magento\Catalog\Helper\Category')->canShow($category)) {
    return false;
}

그러나 Magento\Catalog\Block\Category\View도우미에는 생성자가 주입됩니다.

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Category $catalogLayer,
    \Magento\Framework\Registry $registry,
    \Magento\Catalog\Helper\Category $categoryHelper,
    array $data = array()
) {
    $this->_categoryHelper = $categoryHelper;
    $this->_catalogLayer = $catalogLayer;
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

이것은 도우미와 컨트롤러 및 블록 (및 모델)에서 도우미에 다르게 액세스해야한다고 생각하게했지만 생성자에 도우미가 삽입 된 컨트롤러를 찾았습니다 Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute.

나를 위해 안개를 제거하십시오.
DI는 언제 사용해야하며 언제 사용해야 objectManager합니까? 그리고 왜?
이 질문을 읽었습니다 . Magento 2에서 도우미 인스턴스화 . 이것은 그에 대한 후속 질문입니다.

답변:


10

개체 관리자를 사용하는 것이 이미 미터법에 위배되므로 DI를 선호합니다. 객체 관리자를 사용할 때 이러한 종속성은 메소드 로직에 숨겨져 있습니다.


네. 나는 동의한다. DI를 사용 하겠지만 이것이 왜 코어에서 수행되는지 궁금합니다. 어쩌면 누군가 내가 언급 한 클래스를 리팩토링하지 않았을 수도 있습니다.
Marius

Afaik은 여전히 ​​많은 리팩토링을하고 있으며이 장소에도 영향을 미치기를 바랍니다. 그러나 어떤 시점에서 실제로 릴리스하려면 우선 순위를 알아야합니다. 따라서 일부 새로운 기능이나 다른 나쁜 방법이 먼저 수정 될 수 있습니다.
Tobias

10 개의 기능 클래스가 있고 1 개의 기능 만 특정 모델이 필요한 경우 어떻게해야합니까? 하나의 단일 함수 내에서만 객체 관리자를 사용하여로드 할 수 있지만 10 개의 각 함수에 대해 생성자 주입을 통해 모델을로드하는 데 (성능보기에서) 중복되지 않습니까?
JohnyFree

6

나는 너무 많이 마 젠토 구현에 대한 모르겠지만는 것 같습니다 ObjectManagerA는 서비스 로케이터 .

일반적으로 서비스 로케이터를 사용하여 객체의 종속성에 액세스하는 것은 상당히 나쁩니다 . 이 기사를 확인하십시오 .

생성자를 통해 명시 적으로 종속성을 정의하는 것이 훨씬 더 나은 방법입니다. 서비스가 정의되지 않은 단위 테스트 및 런타임 문제를 지원합니다.

객체 관리자를 클래스에 주입하는 것은 기본적으로 모든 응용 프로그램 서비스에 액세스 할 수있는 레지스트리를 클래스에 주입하는 것입니다.

ZF2 를 공정하게 사용 하며 일반적으로 서비스, 컨트롤러 및 종속성이 필요한 클래스에 대한 작은 팩토리 클래스를 정의합니다. 이 팩토리 클래스는 Service Locator에 액세스하고 오브젝트가 의존하는 모든 서비스를 가져 와서 생성자를 통해 주입합니다. 팩토리 클래스에서 서비스 로케이터를 사용하면 코드를 버릴 수 있습니다 . 예를 들면 다음과 같습니다 .

이 공장들은 여전히 테스트 하기 쉽다 .

IMO, 가능하면 생성자 주입을 사용하십시오. 다시 말하지만, Magento의 구현에 대해 너무 많이 알지 못하며 팩토리 개념이있는 경우 간략하게 보면 클래스를 지원하는 것처럼 보이지만 클래스를 명시 적으로 정의하고 서비스 로케이터를 사용하여 팩토리 클래스에서 빌드하는 것은 훨씬 더 깨끗한 접근법.

이것은 위에서 언급 한 후두둑에 대한 노출이 제한적인 사람의 것이므로이 문제에 대한 다른 사람들의 생각 / 경험을 듣고 싶습니다!

더 많은 독서


좋은 설명 감사합니다. 내 질문은 "핵심에서 도우미에 액세스하는 두 가지 방법이있는 이유는 무엇입니까?" 그래서 이것은 약간의 주제가 아니지만 내가 가지고있는 다른 의심을 없 ed습니다. :) 감사.
Marius

아마 그것이 리팩토링되지 않은 것일뿐입니다. 그 중 하나이거나 사용하기 쉬울 수도 있습니다. 소비자가 컨트롤러에 모든 종속성을 항상 주입하도록 요구하는 것은 특히 RAD를 수행 할 때 비생산적인 것으로 보일 수 있습니다. 소비자에게 종속성에 액세스하는 두 가지 방법을 제공하면 RAD 접근은 허용되지만 다른 사람들이 원하는 경우 종속성을 명시 적으로 정의 할 수 있습니다.
Aydin Hassan

5

도우미를 사용하는 다른 방법 (템플릿에서)은 다음과 같습니다.

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]')->getMethodName();

아직 몰랐다면 도움이 되길 바랍니다.


이것은 개체 관리자를 사용하는 것과 다소 비슷합니다. 그것이 최선의 아이디어인지 확실하지 않습니다.
Marius

1
위의 방법은 내가 아는 한 템플릿에만 적용됩니다. 객체 관리자는 컨트롤러, 블록, 모델 등에 사용됩니다.
rbncha

1
템플릿에 대한 코드 의존성이 없기 때문에 코드와 같은 구장에 없습니다. 템플릿은 소비자 일 뿐이며 캡슐화가 깨진 클라이언트를 오염시키지 않습니다.
demonkoryu

데몬 코류가 무슨 말을하는지 모르겠습니다. 그러나 모든 모듈의 도우미를 호출하는 가장 좋은 방법은 이것입니다. 마 젠토입니다. 그들이 말했듯이 모든 블록 / 섹션 코드는 코어를 건드리지 않고 호출 / 수정 가능하도록 설계되었습니다. 따라서 모든 것이 상호 관련되어 있거나 종속성이 있습니다.
rbncha

2

이 오래된 질문이지만, 내가 있는지 확실하지 않다 마리우스 의 대답을 얻었다. 마리우스 가 더 잘 대답 할 수 있다고 믿습니다 . 간단히 대답하고 싶습니다. Magento 2가 도우미 대신 DI를 사용하도록 제안하는 이유는 무엇입니까?

  • 단위 테스트에서 분리 가능 / 쉬움
  • 클래스의 종속성을 명시 적으로 정의
  • 우수한 설계 촉진 (예 : 단일 책임 원칙 (SRP))
  • 모듈에서 DI를 사용하면 Magento가 해당 인터페이스의 기본 구현을 변경할 때 비 호환성 버그의 위험이 줄어 듭니다. 이것은 확장 개발자에게 이해해야 할 중요한 개념입니다.

M2 코어가 DI를 사용하지 않는 이유는 무엇입니까?

  • 수업 수 감소
  • 불필요한 인터페이스를 만들지 않음
  • 비 호환성 버그 위험 없음

코어 카탈로그 모듈이 도우미로 사용되었지만 DI를 광범위하게 사용했습니다. 필자의 연구에서 Magento 2는 서비스 계약에 적합하지 않은 Core Catalog 도우미 파일에서 기능을 거의 사용하지 않는 것으로 나타났습니다.

Magento 정의 클래스 (예 : \ Magento \ Catalog \ Model \ Product)를 명시 적으로 사용해야하는 경우 서비스 계약 인터페이스 대신 구체적인 구현에 따라 암시 적 종속성을 명시 적으로 지정하십시오.

의심 할 여지없이 확장 개발자는 Helper와 같은 Magento1 대신 DI를 사용해야합니다. Magento 2의 지침에 따라 구현할 때, 낙진이 제한됩니다. 권장 사항을 위반하면 문제가 발생합니다.


네, 그동안 답변을 받았습니다. 하지만 시간을내어 답변 해 주셔서 감사합니다. 온라인으로 검색하는 사람들에게 유용한 정보입니다.
Marius
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.