Tôi muốn cung cấp thêm một chút chi tiết bên cạnh câu trả lời xuất sắc của @ryanF.
Tôi muốn tổng hợp các lý do để thêm kho lưu trữ cho các thực thể tùy chỉnh, đưa ra ví dụ về cách thực hiện và cũng giải thích cách hiển thị các phương thức lưu trữ đó như một phần của API Web.
Tuyên bố miễn trừ trách nhiệm: Tôi chỉ mô tả một cách tiếp cận thực tế về cách thực hiện điều này cho các mô-đun của bên thứ ba - các nhóm cốt lõi có các tiêu chuẩn riêng mà họ tuân theo (hoặc không).
Nói chung, mục đích của một kho lưu trữ là để ẩn logic liên quan đến lưu trữ.
Một khách hàng của kho lưu trữ không nên quan tâm liệu thực thể được trả về có được giữ trong bộ nhớ trong một mảng hay không, được truy xuất từ cơ sở dữ liệu MySQL, được tìm nạp từ API từ xa hoặc từ tệp.
Tôi cho rằng nhóm nòng cốt Magento đã làm điều này để họ có thể thay đổi hoặc thay thế ORM trong tương lai. Trong Magento, ORM hiện bao gồm các Mô hình, Mô hình tài nguyên và Bộ sưu tập.
Nếu một mô-đun bên thứ ba chỉ sử dụng các kho lưu trữ, Magento có thể thay đổi cách thức và nơi lưu trữ dữ liệu và mô-đun sẽ tiếp tục hoạt động, bất chấp những thay đổi sâu sắc này.
Kho thường có các phương pháp như findById()
, findByName()
, put()
hoặc remove()
.
Trong Magento những thường được gọi là getbyId()
, save()
và delete()
, thậm chí không giả vờ họ đang làm bất cứ điều gì khác ngoài hoạt động CRUD DB.
Các phương thức kho lưu trữ Magento 2 có thể dễ dàng được hiển thị dưới dạng tài nguyên API, làm cho chúng có giá trị để tích hợp với các hệ thống bên thứ ba hoặc các phiên bản Magento không đầu.
"Tôi có nên thêm một kho lưu trữ cho thực thể tùy chỉnh của mình không?".
Như mọi khi, câu trả lời là
"Nó phụ thuộc".
Để làm cho một câu chuyện dài ngắn, nếu các thực thể của bạn sẽ được sử dụng bởi các mô-đun khác, thì có, bạn có thể muốn thêm một kho lưu trữ.
Có một yếu tố khác được tính đến ở đây: trong Magento 2, các kho lưu trữ có thể dễ dàng được hiển thị dưới dạng API Web - đó là REST và SOAP - tài nguyên.
Nếu điều đó thú vị với bạn vì tích hợp hệ thống của bên thứ ba hoặc thiết lập Magento không đầu, thì một lần nữa, vâng, có lẽ bạn muốn thêm một kho lưu trữ cho thực thể của mình.
Làm cách nào để thêm kho lưu trữ cho thực thể tùy chỉnh của tôi?
Giả sử bạn muốn trưng bày thực thể của mình như một phần của API REST. Nếu điều đó không đúng, bạn có thể bỏ qua phần sắp tới để tạo giao diện và đi thẳng đến "Tạo kho lưu trữ và triển khai mô hình dữ liệu" bên dưới.
Tạo kho lưu trữ và giao diện mô hình dữ liệu
Tạo các thư mục Api/Data/
trong mô-đun của bạn. Đây chỉ là quy ước, bạn có thể sử dụng một vị trí khác, nhưng bạn không nên.
Các kho lưu trữ đi vào Api/
thư mục. Thư Data/
mục con là để sau.
Trong Api/
, tạo một giao diện PHP với các phương thức bạn muốn trưng ra. Theo quy ước Magento 2, tất cả các tên giao diện đều kết thúc bằng hậu tố Interface
.
Ví dụ, đối với một Hamburger
thực thể, tôi sẽ tạo giao diện Api/HamburgerRepositoryInterface
.
Tạo giao diện kho lưu trữ
Kho lưu trữ Magento 2 là một phần của logic miền của mô-đun. Điều đó có nghĩa là, không có bộ phương thức cố định nào mà kho lưu trữ phải thực hiện.
Nó phụ thuộc hoàn toàn vào mục đích của mô-đun.
Tuy nhiên, trong thực tế tất cả các kho lưu trữ đều khá giống nhau. Chúng là các hàm bao cho chức năng CRUD.
Hầu hết có những phương pháp getById
, save
, delete
và getList
.
Có thể có nhiều hơn, ví dụ như CustomerRepository
có một phương thức get
, tìm nạp khách hàng qua email, theo đó getById
được sử dụng để truy xuất một khách hàng bằng ID thực thể.
Dưới đây là một giao diện kho lưu trữ ví dụ cho một thực thể hamburger:
<?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);
}
Quan trọng! Đây là khoảng thời gian!
Có một vài vấn đề khó giải quyết ở đây nếu bạn hiểu sai:
- KHÔNG sử dụng các kiểu đối số vô hướng PHP7 hoặc các kiểu trả về nếu bạn muốn nối cái này vào API REST!
- Thêm các chú thích PHPDoc cho tất cả các đối số và kiểu trả về cho tất cả các phương thức!
- Sử dụng Tên lớp đủ điều kiện trong khối PHPDoc!
Các chú thích được phân tích cú pháp bởi Khung Magento để xác định cách chuyển đổi dữ liệu sang và từ JSON hoặc XML. Nhập khẩu lớp (có nghĩa là, use
báo cáo) không được áp dụng!
Mọi phương thức phải có một chú thích với bất kỳ kiểu đối số và kiểu trả về. Ngay cả khi một phương thức không có đối số và không trả về gì, thì nó phải có chú thích:
/**
* @return void
*/
Loại vô hướng ( string
, int
, float
và bool
) cũng phải được chỉ định, cả hai cho các đối số và như là một giá trị trả về.
Lưu ý rằng trong ví dụ trên, các chú thích cho các phương thức trả về các đối tượng cũng được chỉ định làm giao diện.
Các giao diện loại trả về là tất cả trong Api\Data
không gian tên / thư mục.
Điều này là để chỉ ra rằng chúng không chứa bất kỳ logic kinh doanh nào. Chúng chỉ đơn giản là túi dữ liệu.
Chúng ta phải tạo ra các giao diện tiếp theo.
Tạo giao diện DTO
Tôi nghĩ Magento gọi các giao diện này là "mô hình dữ liệu", một cái tên tôi không thích chút nào.
Loại lớp này thường được gọi là Đối tượng truyền dữ liệu hoặc DTO .
Các lớp DTO này chỉ có getters và setters cho tất cả các thuộc tính của chúng.
Lý do tôi thích sử dụng DTO hơn mô hình dữ liệu là vì nó ít dễ nhầm lẫn với các mô hình dữ liệu ORM, mô hình tài nguyên hoặc mô hình xem ... quá nhiều thứ đã là mô hình trong Magento.
Các hạn chế tương tự liên quan đến việc gõ PHP7 áp dụng cho các kho lưu trữ cũng áp dụng cho các DTO.
Ngoài ra, mọi phương thức đều phải có chú thích với tất cả các kiểu đối số và kiểu trả về.
<?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);
}
Nếu một phương thức truy xuất hoặc trả về một mảng, loại các mục trong mảng phải được chỉ định trong chú thích PHPDoc, theo sau là một dấu ngoặc vuông mở và đóng []
.
Điều này đúng cho cả các giá trị vô hướng (ví dụ int[]
) cũng như các đối tượng (ví dụ IngredientInterface[]
).
Lưu ý rằng tôi đang sử dụng Api\Data\IngredientInterface
làm ví dụ cho một phương thức trả về một mảng các đối tượng, tôi sẽ không thêm mã thành phần vào bài đăng này.
ExtensibleDataInterface?
Trong ví dụ trên, phần HamburgerInterface
mở rộng ExtensibleDataInterface
.
Về mặt kỹ thuật, điều này chỉ được yêu cầu nếu bạn muốn các mô-đun khác có thể thêm thuộc tính vào thực thể của mình.
Nếu vậy, bạn cũng cần thêm một cặp getter / setter khác, theo quy ước được gọi getExtensionAttributes()
và setExtensionAttributes()
.
Việc đặt tên kiểu trả về của phương thức này rất quan trọng!
Khung công tác Magento 2 sẽ tạo ra giao diện, cách triển khai và nhà máy để thực hiện nếu bạn đặt tên cho chúng vừa phải. Các chi tiết của các cơ chế này nằm ngoài phạm vi của bài này mặc dù.
Chỉ cần biết, nếu giao diện của đối tượng bạn muốn mở rộng được gọi \VinaiKopp\Kitchen\Api\Data\HamburgerInterface
, thì loại thuộc tính mở rộng phải có \VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface
. Vì vậy, từ Extension
phải được chèn sau tên thực thể, ngay trước Interface
hậu tố.
Nếu bạn không muốn thực thể của mình có thể mở rộng, thì giao diện DTO không phải mở rộng bất kỳ giao diện nào khác và các phương thức getExtensionAttributes()
và setExtensionAttributes()
có thể được bỏ qua.
Bây giờ đủ về giao diện DTO, đã đến lúc quay lại giao diện kho lưu trữ.
Kiểu trả về getList () SearchResults
Phương thức kho lưu trữ getList
trả về một kiểu khác, đó là một SearchResultsInterface
thể hiện.
Phương thức getList
tất nhiên có thể chỉ trả về một mảng các đối tượng khớp với chỉ định SearchCriteria
, nhưng trả về một SearchResults
thể hiện cho phép thêm một số dữ liệu meta hữu ích vào các giá trị được trả về.
Bạn có thể thấy cách hoạt động bên dưới trong getList()
triển khai phương thức kho lưu trữ .
Dưới đây là ví dụ về giao diện kết quả tìm kiếm hamburger:
<?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);
}
Tất cả giao diện này làm là ghi đè các loại cho hai phương thức getItems()
và setItems()
giao diện cha.
Tóm tắt các giao diện
Bây giờ chúng ta có các giao diện sau:
\VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface
\VinaiKopp\Kitchen\Api\Data\HamburgerInterface
\VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface
Kho kéo dài không có gì,
các HamburgerInterface
mở rộng \Magento\Framework\Api\ExtensibleDataInterface
,
và HamburgerSearchResultInterface
mở rộng \Magento\Framework\Api\SearchResultsInterface
.
Tạo kho lưu trữ và triển khai mô hình dữ liệu
Bước tiếp theo là tạo ra các triển khai của ba giao diện.
Kho lưu trữ
Về bản chất, kho lưu trữ sử dụng ORM để thực hiện công việc của nó.
Các getById()
, save()
và delete()
phương pháp là khá thẳng về phía trước.
Nó HamburgerFactory
được đưa vào kho lưu trữ dưới dạng đối số của hàm tạo, như có thể thấy thêm một chút bên dưới.
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);
}
Bây giờ đến phần thú vị nhất của một kho lưu trữ, getList()
phương thức.
Các getList()
phương pháp có để dịch các SerachCriteria
điều kiện vào các cuộc gọi phương pháp trên bộ sưu tập.
Phần khó khăn của điều đó là làm cho các điều kiện AND
và OR
điều kiện cho các bộ lọc trở nên đúng, đặc biệt vì cú pháp đặt các điều kiện trên bộ sưu tập là khác nhau tùy thuộc vào việc đó là EAV hay thực thể bảng phẳng.
Trong hầu hết các trường hợp, getList()
có thể được thực hiện như được minh họa trong ví dụ dưới đây.
<?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;
}
}
Các bộ lọc trong một FilterGroup
phải được kết hợp bằng toán tử OR .
Các nhóm bộ lọc riêng biệt được kết hợp bằng toán tử AND logic .
Phew
Đây là phần lớn nhất của công việc. Các triển khai giao diện khác đơn giản hơn.
DTO
Magento ban đầu dự định các nhà phát triển triển khai DTO dưới dạng các lớp riêng biệt, khác biệt với mô hình thực thể.
Nhóm nòng cốt chỉ làm điều này cho mô đun khách hàng mặc dù ( \Magento\Customer\Api\Data\CustomerInterface
được thực hiện bởi \Magento\Customer\Model\Data\Customer
, không phải \Magento\Customer\Model\Customer
).
Trong tất cả các trường hợp khác, mô hình thực thể thực hiện giao diện DTO (ví dụ \Magento\Catalog\Api\Data\ProductInterface
được triển khai bởi \Magento\Catalog\Model\Product
).
Tôi đã hỏi các thành viên của nhóm nòng cốt về vấn đề này tại các hội nghị, nhưng tôi không nhận được phản hồi rõ ràng về những gì được coi là thực hành tốt.
Ấn tượng của tôi là khuyến nghị này đã bị bỏ rơi. Nó sẽ là tốt đẹp để có được một tuyên bố chính thức về điều này mặc dù.
Hiện tại tôi đã đưa ra quyết định thực tế khi sử dụng mô hình làm triển khai giao diện DTO. Nếu bạn cảm thấy sạch hơn khi sử dụng một mô hình dữ liệu riêng biệt, hãy thoải mái làm điều đó. Cả hai phương pháp đều hoạt động tốt trong thực tế.
Nếu phần tử DTO mở rộng Magento\Framework\Api\ExtensibleDataInterface
, mô hình phải mở rộng Magento\Framework\Model\AbstractExtensibleModel
.
Nếu bạn không quan tâm đến khả năng mở rộng, mô hình có thể chỉ cần tiếp tục mở rộng lớp cơ sở mô hình ORM Magento\Framework\Model\AbstractModel
.
Vì ví dụ HamburgerInterface
mở rộng ExtensibleDataInterface
mô hình bánh hamburger mở rộng AbstractExtensibleModel
, như có thể thấy ở đây:
<?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);
}
}
Trích xuất tên tài sản vào hằng số cho phép giữ chúng ở một nơi. Chúng có thể được sử dụng bởi cặp getter / setter và cũng bởi tập lệnh Setup tạo bảng cơ sở dữ liệu. Mặt khác, không có lợi ích trong việc trích xuất chúng vào hằng số.
SearchResult
Đây SearchResultsInterface
là cách đơn giản nhất trong ba giao diện để thực hiện, vì nó có thể kế thừa tất cả các chức năng của nó từ một lớp khung.
<?php
namespace VinaiKopp\Kitchen\Model;
use Magento\Framework\Api\SearchResults;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface;
class HamburgerSearchResult extends SearchResults implements HamburgerSearchResultInterface
{
}
Định cấu hình tùy chọn ObjectManager
Mặc dù việc triển khai đã hoàn tất, chúng ta vẫn không thể sử dụng các giao diện làm phụ thuộc của các lớp khác, vì trình quản lý đối tượng Magento Framework không biết nên sử dụng các triển khai nào. Chúng ta cần thêm một etc/di.xml
cấu hình cho các tùy chọn.
<?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>
Làm thế nào để kho lưu trữ được hiển thị dưới dạng tài nguyên API?
Phần này thực sự đơn giản, đó là phần thưởng cho việc hoàn thành tất cả các công việc tạo ra các giao diện, việc triển khai và kết nối chúng lại với nhau.
Tất cả chúng ta cần làm là tạo một etc/webapi.xml
tập tin.
<?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>
Lưu ý rằng cấu hình này không chỉ cho phép sử dụng kho lưu trữ làm điểm cuối REST, nó còn hiển thị các phương thức như một phần của API SOAP.
Trong tuyến ví dụ đầu tiên <route method="GET" url="/V1/vinaikopp_hamburgers/:id">
, trình giữ chỗ :id
phải khớp tên của đối số với phương thức được ánh xạ , public function getById($id)
.
Hai tên phải khớp nhau, ví dụ /V1/vinaikopp_hamburgers/:hamburgerId
sẽ không hoạt động, vì tên biến đối số phương thức là $id
.
Trong ví dụ này, tôi đã đặt khả năng truy cập <resource ref="anonymous"/>
. Điều này có nghĩa là tài nguyên được phơi bày công khai mà không có bất kỳ hạn chế nào!
Để làm cho một tài nguyên chỉ có sẵn cho một khách hàng đã đăng nhập, sử dụng <resource ref="self"/>
. Trong trường hợp này, từ đặc biệt me
trong URL điểm cuối tài nguyên sẽ được sử dụng để điền một biến đối số $id
với ID của khách hàng hiện đang đăng nhập.
Hãy nhìn vào Khách hàng Magento etc/webapi.xml
và CustomerRepositoryInterface
nếu bạn cần điều đó.
Cuối cùng, <resources>
cũng có thể được sử dụng để hạn chế quyền truy cập vào tài nguyên đối với tài khoản người dùng quản trị viên. Để làm điều này, đặt <resource>
ref cho một định danh được xác định trong một etc/acl.xml
tệp.
Ví dụ: <resource ref="Magento_Customer::manage"/>
sẽ hạn chế quyền truy cập vào bất kỳ tài khoản quản trị viên nào có đặc quyền quản lý khách hàng.
Một truy vấn API ví dụ sử dụng curl có thể trông như thế này:
$ curl -X GET http://example.com/rest/V1/vinaikopp_hamburgers/123
Lưu ý: viết bài này bắt đầu như một câu trả lời cho https://github.com/astorm/pestle/issues/195
Kiểm tra chày , mua Commercebug và trở thành một patreon của @alanstorm