Ich möchte zusätzlich zu der hervorragenden Antwort von @ryanF noch ein bisschen mehr ins Detail gehen.
Ich möchte die Gründe für das Hinzufügen eines Repositorys für benutzerdefinierte Entitäten zusammenfassen, Beispiele dafür geben und auch erläutern, wie diese Repository-Methoden als Teil der Web-API verfügbar gemacht werden.
Haftungsausschluss: Ich beschreibe nur einen pragmatischen Ansatz, wie dies für Module von Drittanbietern durchgeführt wird - die Kernteams haben ihre eigenen Standards, denen sie folgen (oder nicht).
Im Allgemeinen besteht der Zweck eines Repository darin, die speicherbezogene Logik auszublenden.
Ein Client eines Repositorys sollte sich nicht darum kümmern, ob sich die zurückgegebene Entität in einem Array im Speicher befindet, aus einer MySQL-Datenbank abgerufen, von einer Remote-API oder aus einer Datei abgerufen wird.
Ich gehe davon aus, dass das Magento-Kernteam dies getan hat, um das ORM in Zukunft ändern oder ersetzen zu können. In Magento besteht der ORM derzeit aus den Modellen, Ressourcenmodellen und Sammlungen.
Wenn ein Modul eines Drittanbieters nur die Repositorys verwendet, kann Magento ändern, wie und wo Daten gespeichert werden, und das Modul funktioniert trotz dieser tiefgreifenden Änderungen weiterhin.
Repositorys hat in der Regel Methoden wie findById()
, findByName()
, put()
oder remove()
.
In Magento werden diese häufig genannt getbyId()
, save()
und delete()
, auch nicht vorgeben , sie tun etwas anderes als CRUD DB - Operationen.
Magento 2-Repository-Methoden können leicht als API-Ressourcen verfügbar gemacht werden, was sie für die Integration in Systeme von Drittanbietern oder kopflose Magento-Instanzen wertvoll macht.
Msgstr "Soll ich ein Repository für meine benutzerdefinierte Entität hinzufügen?"
Wie immer lautet die Antwort
"Es hängt davon ab, ob".
Um es kurz zu machen: Wenn Ihre Entitäten von anderen Modulen verwendet werden, möchten Sie wahrscheinlich ein Repository hinzufügen.
Ein weiterer Faktor spielt hier eine Rolle: In Magento 2 können Repositorys problemlos als Web-API-Ressourcen (REST- und SOAP-Ressourcen) verfügbar gemacht werden.
Wenn dies für Sie aufgrund von Systemintegrationen von Drittanbietern oder eines Headless-Magento-Setups interessant ist, möchten Sie wahrscheinlich ein Repository für Ihre Entität hinzufügen.
Wie füge ich ein Repository für meine benutzerdefinierte Entität hinzu?
Nehmen wir an, Sie möchten Ihre Entität als Teil der REST-API verfügbar machen. Wenn dies nicht der Fall ist, können Sie den nächsten Teil zum Erstellen der Schnittstellen überspringen und unten direkt mit "Repository- und Datenmodellimplementierung erstellen" fortfahren.
Erstellen Sie die Repository- und Datenmodellschnittstellen
Erstellen Sie die Ordner Api/Data/
in Ihrem Modul. Dies ist nur eine Konvention, Sie könnten einen anderen Ort verwenden, aber Sie sollten nicht.
Das Repository wird in den Api/
Ordner verschoben. Das Data/
Unterverzeichnis ist für später.
In Api/
erstellen belichten eine PHP - Schnittstelle mit den Methoden , die Sie wollen. Gemäß den Konventionen von Magento 2 enden alle Schnittstellennamen mit dem Suffix Interface
.
Beispielsweise Hamburger
würde ich für eine Entität die Schnittstelle erstellen Api/HamburgerRepositoryInterface
.
Erstellen Sie die Repository-Schnittstelle
Magento 2-Repositorys sind Teil der Domänenlogik eines Moduls. Das heißt, es gibt keine festen Methoden, die ein Repository implementieren muss.
Es hängt ganz vom Zweck des Moduls ab.
In der Praxis sind jedoch alle Repositories sehr ähnlich. Sie sind Wrapper für die CRUD-Funktionalität.
Die meisten haben die Methoden getById
, save
, delete
und getList
.
Es kann mehr geben, zum Beispiel CustomerRepository
hat die eine Methode get
, die einen Kunden per E-Mail getById
abruft , wodurch ein Kunde nach Entitäts-ID abgerufen wird.
Hier ist ein Beispiel für eine Repository-Schnittstelle für eine Hamburger-Entität:
<?php
namespace VinaiKopp\Kitchen\Api;
use Magento\Framework\Api\SearchCriteriaInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerInterface;
interface HamburgerRepositoryInterface
{
/**
* @param int $id
* @return \VinaiKopp\Kitchen\Api\Data\HamburgerInterface
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getById($id);
/**
* @param \VinaiKopp\Kitchen\Api\Data\HamburgerInterface $hamburger
* @return \VinaiKopp\Kitchen\Api\Data\HamburgerInterface
*/
public function save(HamburgerInterface $hamburger);
/**
* @param \VinaiKopp\Kitchen\Api\Data\HamburgerInterface $hamburger
* @return void
*/
public function delete(HamburgerInterface $hamburger);
/**
* @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
* @return \VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface
*/
public function getList(SearchCriteriaInterface $searchCriteria);
}
Wichtig! Hier seid timesinks!
Es gibt ein paar Fallstricke, die schwer zu debuggen sind, wenn Sie sie falsch verstehen:
- DO NOT verwenden PHP7 Skalar Argumenttypen oder Rückgabetypen , wenn Sie diese in die REST - API Haken wollen!
- Fügen Sie allen Methoden PHPDoc-Annotationen für alle Argumente und den Rückgabetyp hinzu!
- Verwenden Sie im PHPDoc-Block vollständig qualifizierte Klassennamen!
Die Anmerkungen werden vom Magento Framework analysiert, um zu bestimmen, wie Daten in und aus JSON oder XML konvertiert werden. Klassenimporte (also use
Anweisungen) werden nicht angewendet!
Jede Methode muss eine Annotation mit Argumenttypen und dem Rückgabetyp haben. Auch wenn eine Methode keine Argumente akzeptiert und nichts zurückgibt, muss sie die folgende Anmerkung haben:
/**
* @return void
*/
Skalar - Typen ( string
, int
, float
und bool
) haben auch festgelegt werden, sowohl für Argumente und als Rückgabewert.
Beachten Sie, dass im obigen Beispiel die Annotationen für Methoden, die Objekte zurückgeben, auch als Schnittstellen angegeben werden.
Die Rückgabetyp-Schnittstellen befinden sich alle im Api\Data
Namespace / Verzeichnis.
Dies soll darauf hinweisen, dass sie keine Geschäftslogik enthalten. Sie sind einfach Datenmengen.
Als nächstes müssen wir diese Schnittstellen erstellen.
Erstellen Sie die DTO-Schnittstelle
Ich denke, Magento nennt diese Schnittstellen "Datenmodelle", einen Namen, den ich überhaupt nicht mag.
Diese Art von Klasse wird allgemein als Datenübertragungsobjekt oder DTO bezeichnet .
Diese DTO-Klassen haben nur Getter und Setter für alle ihre Eigenschaften.
Der Grund, warum ich DTO lieber als Datenmodell verwende, ist, dass es weniger leicht ist, mit den ORM-Datenmodellen, Ressourcenmodellen oder Ansichtsmodellen zu verwechseln. Zu viele Dinge sind bereits Modelle in Magento.
Die gleichen Einschränkungen in Bezug auf die PHP7-Typisierung, die für Repositorys gelten, gelten auch für DTOs.
Außerdem muss jede Methode eine Annotation mit allen Argumenttypen und dem Rückgabetyp haben.
<?php
namespace VinaiKopp\Kitchen\Api\Data;
use Magento\Framework\Api\ExtensibleDataInterface;
interface HamburgerInterface extends ExtensibleDataInterface
{
/**
* @return int
*/
public function getId();
/**
* @param int $id
* @return void
*/
public function setId($id);
/**
* @return string
*/
public function getName();
/**
* @param string $name
* @return void
*/
public function setName($name);
/**
* @return \VinaiKopp\Kitchen\Api\Data\IngredientInterface[]
*/
public function getIngredients();
/**
* @param \VinaiKopp\Kitchen\Api\Data\IngredientInterface[] $ingredients
* @return void
*/
public function setIngredients(array $ingredients);
/**
* @return string[]
*/
public function getImageUrls();
/**
* @param string[] $urls
* @return void
*/
public function setImageUrls(array $urls);
/**
* @return \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface|null
*/
public function getExtensionAttributes();
/**
* @param \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface $extensionAttributes
* @return void
*/
public function setExtensionAttributes(HamburgerExtensionInterface $extensionAttributes);
}
Wenn eine Methode ein Array abruft oder zurückgibt, muss der Typ der Elemente im Array in der PHPDoc-Annotation angegeben werden, gefolgt von einer öffnenden und schließenden eckigen Klammer []
.
Dies gilt sowohl für skalare Werte (zB int[]
) als auch für Objekte (zB IngredientInterface[]
).
Beachten Sie, dass ich a Api\Data\IngredientInterface
als Beispiel für eine Methode verwende, die ein Array von Objekten zurückgibt. Ich werde den Code der Zutaten nicht zu diesem Beitrag hinzufügen.
ExtensibleDataInterface?
Im obigen Beispiel HamburgerInterface
erweitert das ExtensibleDataInterface
.
Technisch ist dies nur erforderlich, wenn andere Module Ihrer Entität Attribute hinzufügen können sollen.
In diesem Fall müssen Sie auch ein weiteres Getter / Setter-Paar hinzufügen, das gemäß der Konvention mit getExtensionAttributes()
und bezeichnet wird setExtensionAttributes()
.
Die Benennung des Rückgabetyps dieser Methode ist sehr wichtig!
Das Magento 2-Framework generiert die Schnittstelle, die Implementierung und die Factory für die Implementierung, wenn Sie sie genau richtig benennen. Die Details dieser Mechanik sind jedoch nicht Gegenstand dieses Beitrags.
Wissen Sie nur, wenn die Schnittstelle des Objekts, das Sie erweiterbar machen möchten, aufgerufen wird \VinaiKopp\Kitchen\Api\Data\HamburgerInterface
, muss der Typ der Erweiterungsattribute sein \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface
. Das Wort Extension
muss also nach dem Entitätsnamen, direkt vor dem Interface
Suffix , eingefügt werden .
Wenn Sie nicht möchten, dass Ihre Entität erweiterbar ist, muss die DTO-Schnittstelle keine andere Schnittstelle erweitern, und die Methoden getExtensionAttributes()
und setExtensionAttributes()
können weggelassen werden.
Genug von der DTO-Schnittstelle, Zeit, um zur Repository-Schnittstelle zurückzukehren.
Der getList () -Rückgabetyp SearchResults
Die Repository-Methode getList
gibt einen weiteren Typ zurück, dh eine SearchResultsInterface
Instanz.
Die Methode getList
könnte natürlich nur ein Array von Objekten zurückgeben, die mit dem angegebenen übereinstimmen SearchCriteria
, aber das Zurückgeben einer SearchResults
Instanz ermöglicht das Hinzufügen einiger nützlicher Metadaten zu den zurückgegebenen Werten.
Wie das funktioniert, sehen Sie weiter unten in der getList()
Implementierung der Repository- Methode.
Hier ist das Beispiel für eine Hamburger-Suchergebnisoberfläche:
<?php
namespace VinaiKopp\Kitchen\Api\Data;
use Magento\Framework\Api\SearchResultsInterface;
interface HamburgerSearchResultInterface extends SearchResultsInterface
{
/**
* @return \VinaiKopp\Kitchen\Api\Data\HamburgerInterface[]
*/
public function getItems();
/**
* @param \VinaiKopp\Kitchen\Api\Data\HamburgerInterface[] $items
* @return void
*/
public function setItems(array $items);
}
Diese Schnittstelle überschreibt lediglich die Typen der beiden Methoden getItems()
und setItems()
der übergeordneten Schnittstelle.
Zusammenfassung der Schnittstellen
Wir haben jetzt die folgenden Schnittstellen:
\VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface
\VinaiKopp\Kitchen\Api\Data\HamburgerInterface
\VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface
Das Repository erstreckt sich nichts,
die HamburgerInterface
sich die \Magento\Framework\Api\ExtensibleDataInterface
,
und das HamburgerSearchResultInterface
erstreckt sich das \Magento\Framework\Api\SearchResultsInterface
.
Erstellen Sie die Repository- und Datenmodellimplementierungen
Der nächste Schritt besteht darin, die Implementierungen der drei Schnittstellen zu erstellen.
Das Repository
Im Wesentlichen verwendet das Repository das ORM, um seine Arbeit zu erledigen.
Die getById()
, save()
und delete()
Methoden sind ziemlich geradlinig.
Das HamburgerFactory
wird als Konstruktorargument in das Repository injiziert, wie weiter unten zu sehen ist.
public function getById($id)
{
$hamburger = $this->hamburgerFactory->create();
$hamburger->getResource()->load($hamburger, $id);
if (! $hamburger->getId()) {
throw new NoSuchEntityException(__('Unable to find hamburger with ID "%1"', $id));
}
return $hamburger;
}
public function save(HamburgerInterface $hamburger)
{
$hamburger->getResource()->save($hamburger);
return $hamburger;
}
public function delete(HamburgerInterface $hamburger)
{
$hamburger->getResource()->delete($hamburger);
}
Nun zum interessantesten Teil eines Repositorys, der getList()
Methode.
Die getList()
Methode muss die SerachCriteria
Bedingungen in Methodenaufrufe für die Sammlung übersetzen.
Der schwierige Teil davon wird die immer AND
und OR
Bedingungen für die Filter rechts, vor allem , da die Syntax für die Bedingungen für die Gewinnung unterschiedlich ist , je nachdem ob es sich um eine EAV oder eine flache Tischeinheit.
In den meisten Fällen getList()
kann wie im folgenden Beispiel dargestellt implementiert werden.
<?php
namespace VinaiKopp\Kitchen\Model;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\Api\SortOrder;
use Magento\Framework\Exception\NoSuchEntityException;
use VinaiKopp\Kitchen\Api\Data\HamburgerInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterfaceFactory;
use VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface;
use VinaiKopp\Kitchen\Model\ResourceModel\Hamburger\CollectionFactory as HamburgerCollectionFactory;
use VinaiKopp\Kitchen\Model\ResourceModel\Hamburger\Collection;
class HamburgerRepository implements HamburgerRepositoryInterface
{
/**
* @var HamburgerFactory
*/
private $hamburgerFactory;
/**
* @var HamburgerCollectionFactory
*/
private $hamburgerCollectionFactory;
/**
* @var HamburgerSearchResultInterfaceFactory
*/
private $searchResultFactory;
public function __construct(
HamburgerFactory $hamburgerFactory,
HamburgerCollectionFactory $hamburgerCollectionFactory,
HamburgerSearchResultInterfaceFactory $hamburgerSearchResultInterfaceFactory
) {
$this->hamburgerFactory = $hamburgerFactory;
$this->hamburgerCollectionFactory = $hamburgerCollectionFactory;
$this->searchResultFactory = $hamburgerSearchResultInterfaceFactory;
}
// ... getById, save and delete methods listed above ...
public function getList(SearchCriteriaInterface $searchCriteria)
{
$collection = $this->collectionFactory->create();
$this->addFiltersToCollection($searchCriteria, $collection);
$this->addSortOrdersToCollection($searchCriteria, $collection);
$this->addPagingToCollection($searchCriteria, $collection);
$collection->load();
return $this->buildSearchResult($searchCriteria, $collection);
}
private function addFiltersToCollection(SearchCriteriaInterface $searchCriteria, Collection $collection)
{
foreach ($searchCriteria->getFilterGroups() as $filterGroup) {
$fields = $conditions = [];
foreach ($filterGroup->getFilters() as $filter) {
$fields[] = $filter->getField();
$conditions[] = [$filter->getConditionType() => $filter->getValue()];
}
$collection->addFieldToFilter($fields, $conditions);
}
}
private function addSortOrdersToCollection(SearchCriteriaInterface $searchCriteria, Collection $collection)
{
foreach ((array) $searchCriteria->getSortOrders() as $sortOrder) {
$direction = $sortOrder->getDirection() == SortOrder::SORT_ASC ? 'asc' : 'desc';
$collection->addOrder($sortOrder->getField(), $direction);
}
}
private function addPagingToCollection(SearchCriteriaInterface $searchCriteria, Collection $collection)
{
$collection->setPageSize($searchCriteria->getPageSize());
$collection->setCurPage($searchCriteria->getCurrentPage());
}
private function buildSearchResult(SearchCriteriaInterface $searchCriteria, Collection $collection)
{
$searchResults = $this->searchResultFactory->create();
$searchResults->setSearchCriteria($searchCriteria);
$searchResults->setItems($collection->getItems());
$searchResults->setTotalCount($collection->getSize());
return $searchResults;
}
}
Filter innerhalb eines FilterGroup
müssen mit einem OR- Operator kombiniert werden .
Separate Filtergruppen werden mit dem logischen AND- Operator kombiniert .
Puh
Das war die größte Arbeit. Die anderen Schnittstellenimplementierungen sind einfacher.
Das DTO
Magento hatte ursprünglich die Absicht, das DTO als separate Klassen zu implementieren, die sich vom Entitätsmodell unterscheiden.
Das Kernteam hat dies jedoch nur für das Kundenmodul getan ( \Magento\Customer\Api\Data\CustomerInterface
wird von implementiert \Magento\Customer\Model\Data\Customer
, nicht \Magento\Customer\Model\Customer
).
In allen anderen Fällen implementiert das Entitätsmodell die DTO-Schnittstelle (z. B. \Magento\Catalog\Api\Data\ProductInterface
implementiert von \Magento\Catalog\Model\Product
).
Ich habe Mitglieder des Kernteams auf Konferenzen dazu befragt, aber ich habe keine klare Antwort erhalten, was als gute Praxis anzusehen ist.
Mein Eindruck ist, dass diese Empfehlung aufgegeben wurde. Es wäre jedoch schön, eine offizielle Stellungnahme dazu zu erhalten.
Im Moment habe ich die pragmatische Entscheidung getroffen, das Modell als Implementierung der DTO-Schnittstelle zu verwenden. Wenn Sie der Meinung sind, dass die Verwendung eines separaten Datenmodells sauberer ist, können Sie dies tun. Beide Ansätze funktionieren in der Praxis gut.
Wenn die DTO-Schnittstelle die erweitert Magento\Framework\Api\ExtensibleDataInterface
, muss das Modell erweitert werden Magento\Framework\Model\AbstractExtensibleModel
.
Wenn Sie sich nicht für die Erweiterbarkeit interessieren, kann das Modell die ORM-Modellbasisklasse einfach weiter erweitern Magento\Framework\Model\AbstractModel
.
Da das Beispiel das HamburgerInterface
erweitert, erweitert das ExtensibleDataInterface
Hamburger Modell das AbstractExtensibleModel
, wie hier zu sehen ist:
<?php
namespace VinaiKopp\Kitchen\Model;
use Magento\Framework\Model\AbstractExtensibleModel;
use VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface;
use VinaiKopp\Kitchen\Api\Data\HamburgerInterface;
class Hamburger extends AbstractExtensibleModel implements HamburgerInterface
{
const NAME = 'name';
const INGREDIENTS = 'ingredients';
const IMAGE_URLS = 'image_urls';
protected function _construct()
{
$this->_init(ResourceModel\Hamburger::class);
}
public function getName()
{
return $this->_getData(self::NAME);
}
public function setName($name)
{
$this->setData(self::NAME, $name);
}
public function getIngredients()
{
return $this->_getData(self::INGREDIENTS);
}
public function setIngredients(array $ingredients)
{
$this->setData(self::INGREDIENTS, $ingredients);
}
public function getImageUrls()
{
$this->_getData(self::IMAGE_URLS);
}
public function setImageUrls(array $urls)
{
$this->setData(self::IMAGE_URLS, $urls);
}
public function getExtensionAttributes()
{
return $this->_getExtensionAttributes();
}
public function setExtensionAttributes(HamburgerExtensionInterface $extensionAttributes)
{
$this->_setExtensionAttributes($extensionAttributes);
}
}
Durch Extrahieren der Eigenschaftsnamen in Konstanten können Sie diese an einem Ort aufbewahren. Sie können sowohl vom Getter / Setter-Paar als auch vom Setup-Skript verwendet werden, das die Datenbanktabelle erstellt. Andernfalls hat es keinen Vorteil, sie in Konstanten zu extrahieren.
Das SearchResult
Dies SearchResultsInterface
ist die einfachste der drei zu implementierenden Schnittstellen, da sie die gesamte Funktionalität einer Framework-Klasse erben kann.
<?php
namespace VinaiKopp\Kitchen\Model;
use Magento\Framework\Api\SearchResults;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface;
class HamburgerSearchResult extends SearchResults implements HamburgerSearchResultInterface
{
}
Konfigurieren Sie die ObjectManager-Einstellungen
Obwohl die Implementierungen vollständig sind, können wir die Schnittstellen nicht als Abhängigkeiten anderer Klassen verwenden, da der Magento Framework-Objektmanager nicht weiß, welche Implementierungen verwendet werden sollen. Wir müssen eine etc/di.xml
Konfiguration für mit den Einstellungen hinzufügen .
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" type="VinaiKopp\Kitchen\Model\HamburgerRepository"/>
<preference for="VinaiKopp\Kitchen\Api\Data\HamburgerInterface" type="VinaiKopp\Kitchen\Model\Hamburger"/>
<preference for="VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface" type="VinaiKopp\Kitchen\Model\HamburgerSearchResult"/>
</config>
Wie kann das Repository als API-Ressource verfügbar gemacht werden?
Dieser Teil ist wirklich einfach, es ist die Belohnung für die Arbeit, die Schnittstellen, die Implementierungen und die Verkabelung zu erstellen.
Alles was wir tun müssen, ist eine etc/webapi.xml
Datei zu erstellen .
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route method="GET" url="/V1/vinaikopp_hamburgers/:id">
<service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="getById"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="GET" url="/V1/vinaikopp_hamburgers">
<service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="getList"/>
<resources>
<resource ref="anonymouns"/>
</resources>
</route>
<route method="POST" url="/V1/vinaikopp_hamburgers">
<service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="save"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="PUT" url="/V1/vinaikopp_hamburgers">
<service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="save"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="DELETE" url="/V1/vinaikopp_hamburgers">
<service class="VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface" method="delete"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
</routes>
Beachten Sie, dass diese Konfiguration nicht nur die Verwendung des Repositorys als REST-Endpunkt ermöglicht, sondern auch die Methoden als Teil der SOAP-API verfügbar macht.
In der ersten Beispielroute <route method="GET" url="/V1/vinaikopp_hamburgers/:id">
muss der Platzhalter :id
den Namen des Arguments mit der zugeordneten Methode abgleichen public function getById($id)
.
Die beiden Namen müssen übereinstimmen, /V1/vinaikopp_hamburgers/:hamburgerId
würden beispielsweise nicht funktionieren, da das Methodenargument Variablenname lautet $id
.
Für dieses Beispiel habe ich die Erreichbarkeit auf eingestellt <resource ref="anonymous"/>
. Dies bedeutet, dass die Ressource ohne Einschränkung öffentlich verfügbar ist!
Verwenden Sie, um eine Ressource nur einem angemeldeten Kunden zur Verfügung zu stellen <resource ref="self"/>
. In diesem Fall wird das spezielle Wort me
in der URL des Ressourcenendpunkts verwendet, um eine Argumentvariable $id
mit der ID des aktuell angemeldeten Kunden zu füllen.
Schauen Sie sich den Magento-Kunden an etc/webapi.xml
und CustomerRepositoryInterface
wenn Sie das brauchen.
Schließlich <resources>
kann das auch verwendet werden, um den Zugriff auf eine Ressource auf ein Administratorkonto zu beschränken. Setzen Sie dazu den <resource>
Verweis auf eine in einer etc/acl.xml
Datei definierte Kennung .
Zum Beispiel <resource ref="Magento_Customer::manage"/>
würde Zugriff auf all Admin - Konto beschränken , die privilegiert ist es, Kunden zu verwalten.
Eine Beispiel-API-Abfrage mit curl könnte folgendermaßen aussehen:
$ curl -X GET http://example.com/rest/V1/vinaikopp_hamburgers/123
Hinweis: Das Schreiben dieser als Antwort auf gestartet https://github.com/astorm/pestle/issues/195
Check out Stößel , kaufen Commercebug und zu einem Patreon von @alanstorm
@Raphael bei Digital Pianism:
Bitte beachten Sie die folgende Beispielmodulstruktur:
Erstellen Sie eine Repository-Schnittstelle (Servicevertrag)
Namespace/Custom/Api/CustomRepositoryInterface.php
: http://codepad.org/WognSKnHErstellen Sie SearchResultsInterface
Namespace/Custom/Api/Data/CustomSearchResultsInterface.php
: http://codepad.org/zcbi8X4ZErstellen Sie CustomInterface (Datencontainer)
Namespace/Custom/Api/Data/CustomInterface.php
: http://codepad.org/Ze53eT4oErstellen Sie ein CustomRepository (Concrete Repository)
Namespace/Custom/Model/CustomRepository.php
: http://codepad.org/KNt5QAGZHier geschieht die "Magie". Über Konstruktor DI übergeben Sie das Ressourcenmodell / die Auflistungsfactory für Ihr benutzerdefiniertes Modul. Das Speichern CRUD Methode in diesem Repository, aufgrund Ihrer CustomRepositoryInterface Bezüglich Sie müssen in einem Parameter von Custom passieren. In der Datei di.xml Ihres Moduls wird eine Schnittstelle dieses Typs vorzugsweise durch ein Entitätsmodell ersetzt. Das Entitätsmodell wird an das Ressourcenmodell übergeben und gespeichert.
Set Präferenz
Namespace/Custom/etc/di.xml
: http://codepad.org/KmcoOUeVEntitätsmodell zur Implementierung der benutzerdefinierten Schnittstelle (Datencontainer)
Namespace/Custom/Model/Custom.php
: http://codepad.org/xQiBU7p7 .Ressourcenmodell
Namespace/Custom/Model/ResourceModel/Custom.php
: http://codepad.org/IOsxm9qWEin paar Dinge zu beachten:
Haftungsausschluss!!! Ich habe „Namespace“ anstelle der benutzerdefinierten Herstellernamen, Agenturname, etc ... , was Namen Sie Ihre Module zusammen verwenden , um Gruppe ... die tatsächliche Verwendung der „Namespace“ ist vollständig nicht in Php gültig ... so Know dass ich dies der Einfachheit halber getan habe und dass ich nicht denke, dass dies funktionieren wird , und auch nicht, dass ich es in irgendeiner Weise vorschlage.
@ Ryan Street hat mir das beigebracht ... also möchte ich nicht den ganzen Kredit in Anspruch nehmen
Ändern Sie die Implementierung des Repositorys ganz nach Ihren Bedürfnissen
Sie implementieren die Interaktion mit Ihren benutzerdefinierten Entitätsmodellen / Ressourcenmodellen / Sammlungen im konkreten Repository ...
Ich weiß, dass ich nicht alle Methoden angesprochen habe, die Sie in Ihrer Frage aufgeführt haben, aber dies ist ein guter Anfang und sollte die Lücke zwischen den Dokumenten und der tatsächlichen Implementierung schließen.
quelle
komplette Dateien der Nutzung von Serviceverträgen
Benutzerdefiniert / Modul / registration.php
../etc/module.xml
../Setup/InstallSchema.php
../etc/di.xml
../etc/webapi.xml
../Api/ModelRepositoryInterface.php
../Api/Data/ModelInterface.php
..Api / Data / ModelSearchResultsInterface.php
../Model/Model.php
../Model/ResourceModel/Model.php
../Model/ResourceModel/Model/Collection.php
../Model/ModelRepository.php
../Model/ModelSearchResults.php
../Controller/Index/Save.php
../Controller/Index/Getlist.php
../Controller/Index/Getbyid.php
../Controller/Index/Deletebyid.php
../Controller/Index/Del.php
quelle