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->variablewstrzykiwane 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 CustomModelRepositoryInterfaceobiekt do konstruktora i używamy go w naszej getCustomModel()metodzie.
W klasie Api\CustomModelRepositoryInterfacenie 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 getdeklaracja 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 CustomModelRepositoryInterfaceklasa jest interfejsem usługi. Wdrażając go, będziesz musiał zaimplementować również interfejsy danych (przynajmniej Vendor\Module\Api\Data\CustomModelInterfacei Vendor\Module\Api\Data\CustomModelSearchResultsInterface). Twój model będzie musiał zaimplementować Vendor\Module\Api\Data\CustomModelInterfacei dodać <preference ... />linie dla każdego interfejsu. Wreszcie, w każdej chwili, gdy korzystasz z umowy serwisowej, nie myśl mySomethingInterfacejuż więcej mySomething: pozwól magento skorzystać z di.xmlmechanizmu preferencji.
Ok, co będzie dalej? Gdy wprowadzamy CustomModelRepositoryInterfacekonstruktor bloku, otrzymujemy CustomModelRepositoryobiekt. CustomModelRepositorymusi 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 CustomModelobiekt dzięki fabryce. Następnie ładujemy dane za CustomModelpomocą metody modelu obciążenia. Następnie zwracamy a, NoSuchEntityExceptionjeśli nie udało się załadować CustomModelidentyfikatora 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 loadmetoda 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;
}