Ponieważ trudno mi było znaleźć właściwą drogę, poniżej możesz znaleźć najlepszą praktykę, którą zastosowałem. Ciesz się, popraw mój angielski w razie potrzeby i powiedz mi, że się mylę, jeśli tak jest. :)
Edycja: ... i odkryłem, że się myliłem w niektórych aspektach. Zaktualizowałem więc oryginalny post, gdy odpowiedzi Raphaela pomogły mi zrozumieć więcej. Dzięki mu!
Zastosowana poniżej koncepcja :
Łatwiej będzie ci zrozumieć poniższe kody i objaśnienia, jeśli nie masz nic przeciwko tym pojęciom:
- Zależność wtrysku (ponieważ
$this->variable
wstrzykiwane są wszystkie zmienne w kodach) - Umowa serwisowa i repozytorium
- Fabryka
Kontekst :
Aby mieć więcej kontekstu, wyobraź sobie, że mamy poprawnie skonstruowany moduł z:
- klasa blokowa CustomBlock zawierająca metodę
getCustomModel($id)
, - ta metoda zwraca obiekt CustomModel na podstawie identyfikatora przekazanego w param,
- Typ CustomModel odpowiada modelowi w
\Vendor\Module\Model\CustomModel
- Ten model jest dostarczany z modelem zasobów (w
\Vendor\Module\Model\ResourceModel\CustomModel
) - oraz z jego repozytorium (in
\Vendor\Module\Model\CustomModelRepository
).
Pytanie :
- Jaka jest najlepsza praktyka pozwalająca wszystkim ładować obiekt CustomModel?
Nie możesz użyć load()
obiektu CustomModel, ponieważ ta metoda jest przestarzała.
Dobra praktyka mówi, że musisz skorzystać z umowy serwisowej CustomModel. Kontrakty serwisowe to interfejsy danych (np. CustomModelInterface) i interfejsy serwisowe (np. CustomModelRepositoryInterface). Mój blok wygląda tak:
/ ** @var SlideRepositoryInterface * / chroniony $ slideRepository; / ** * Konstruktor CustomBlock * ... * @param CustomModelRepositoryInterface $ customModelRepository * ... * / funkcja publiczna __construct ( ... CustomModelRepositoryInterface $ customModelRepository ... ) { $ this-> customModelRepository = $ customModelRepository; } funkcja publiczna getCustomModel ($ id) { return $ this-> customModelRepository-> get ($ id); }
Przede wszystkim wstrzykiwamy CustomModelRepositoryInterface
obiekt do konstruktora i używamy go w naszej getCustomModel()
metodzie.
W klasie Api\CustomModelRepositoryInterface
nie ma dużo. Generalnie (ale nic nie przeszkodzi, aby zrobić inaczej) można zadeklarować podstawowe metody: get
, getList
, save
, delete
, deleteById
. Na potrzeby tego tematu poniżej znajduje się tylko get
deklaracja metody:
/**
* Get info by id
*
* @param int $id
* @return Data\CustomModelInterface
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function get($id);
Ok, ale jeśli mój interfejs CustomModel jest wywoływany przez wstrzyknięcie zależności w moim konstruktorze bloku, to gdzie jest kod? Aby odpowiedzieć na to pytanie, musisz wyjaśnić Magento, gdzie znajduje się klasa implementująca ten interfejs. W pliku etc / di.xml modułu musisz dodać:
<preference for="Vendor\Module\Api\CustomModelRepositoryInterface" type="Vendor\Module\Model\CustomModelRepository" />
Zatem CustomModelRepositoryInterface
klasa jest interfejsem usługi. Wdrażając go, będziesz musiał zaimplementować również interfejsy danych (przynajmniej Vendor\Module\Api\Data\CustomModelInterface
i Vendor\Module\Api\Data\CustomModelSearchResultsInterface
). Twój model będzie musiał zaimplementować Vendor\Module\Api\Data\CustomModelInterface
i dodać <preference ... />
linie dla każdego interfejsu. Wreszcie, w każdej chwili, gdy korzystasz z umowy serwisowej, nie myśl mySomethingInterface
już więcej mySomething
: pozwól magento skorzystać z di.xml
mechanizmu preferencji.
Ok, co będzie dalej? Gdy wprowadzamy CustomModelRepositoryInterface
konstruktor bloku, otrzymujemy CustomModelRepository
obiekt. CustomModelRepository
musi zaimplementować metodę deklarowania w CustomModelRepositoryInterface
. Mamy to w Vendor\Module\Model\CustomModelRepository
:
funkcja publiczna get ($ id) { $ customModel = $ this-> customModelFactory-> create (); $ customModel-> load ($ id); if (! $ customModel-> getId ()) { wyrzuć nowy wyjątek NoSuchEntityException (__ („CustomModel o identyfikatorze„% 1 ”nie istnieje.”, $ id)); } return $ customModel; }
Co robimy ? Tworzymy pusty CustomModel
obiekt dzięki fabryce. Następnie ładujemy dane za CustomModel
pomocą metody modelu obciążenia. Następnie zwracamy a, NoSuchEntityException
jeśli nie udało się załadować CustomModel
identyfikatora w params. Ale jeśli wszystko jest w porządku, zwracamy obiekt modelu i życie trwa.
Ale wow ...! W tym przykładzie co to jest?
$customModel->load($id);
Czy to nie jest ta sama przestarzała load
metoda niż na początku? Tak to jest. Myślę, że to wstyd, ale musisz go użyć, ponieważ w metodzie load () wywoływane są pewne zdarzenia i programista może ich słuchać (patrz odpowiedź Raphaela poniżej).
W przyszłości będziemy oszczędzać przez Entity Manager. To kolejna historia jako nowa koncepcja Magento 2, ale jeśli chcesz rzucić okiem, Entity Manager jest już zaimplementowany w modelu zasobów strony 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;
}