ฉันต้องการให้รายละเอียดเพิ่มเติมนอกเหนือจากคำตอบที่ยอดเยี่ยมของ @ryanF
ฉันต้องการสรุปเหตุผลในการเพิ่มที่เก็บสำหรับเอนทิตีที่กำหนดเองยกตัวอย่างวิธีการทำเช่นนั้นและอธิบายวิธีเปิดเผยวิธีการเก็บข้อมูลเหล่านั้นเป็นส่วนหนึ่งของ Web API
ข้อจำกัดความรับผิดชอบ: ฉันแค่อธิบายวิธีปฏิบัติอย่างจริงจังว่าจะทำอย่างไรสำหรับโมดูลบุคคลที่สาม - ทีมหลักมีมาตรฐานของตัวเองซึ่งพวกเขาปฏิบัติตาม (หรือไม่)
โดยทั่วไปวัตถุประสงค์ของที่เก็บคือการซ่อนตรรกะที่เกี่ยวข้องกับการจัดเก็บ
ไคลเอ็นต์ของที่เก็บไม่ควรสนใจว่าเอนทิตีที่ส่งคืนถูกเก็บไว้ในหน่วยความจำในอาร์เรย์หรือไม่ถูกดึงจากฐานข้อมูล MySQL เรียกจาก API ระยะไกลหรือจากไฟล์
ฉันคิดว่าทีมหลักของ Magento ทำสิ่งนี้เพื่อให้พวกเขาสามารถเปลี่ยนหรือเปลี่ยน ORM ในอนาคต ใน Magento ปัจจุบัน ORM ประกอบด้วยโมเดล, โมเดลทรัพยากรและคอลเล็กชัน
หากโมดูลของบุคคลที่สามใช้ที่เก็บข้อมูลเท่านั้นวีโอไอพีสามารถเปลี่ยนวิธีการจัดเก็บข้อมูลและสถานที่และโมดูลจะยังคงทำงานต่อไปแม้จะมีการเปลี่ยนแปลงในเชิงลึก
ที่เก็บโดยทั่วไปมีวิธีการเช่นfindById()
, findByName()
, หรือput()
ในวีโอไอพีเหล่านี้โดยทั่วไปจะเรียกว่า, และไม่ได้แกล้งพวกเขากำลังทำอะไรอย่างอื่น แต่การดำเนินงาน CRUD DB remove()
getbyId()
save()
delete()
วิธีการเก็บข้อมูล Magento 2 สามารถเปิดเผยเป็นทรัพยากร API ได้อย่างง่ายดายทำให้มีคุณค่าสำหรับการผสานรวมกับระบบของบุคคลที่สามหรืออินสแตนซ์ Magento ที่ไม่มีหัว
"ฉันควรเพิ่มที่เก็บสำหรับเอนทิตีที่กำหนดเองของฉัน".
เช่นเคยคำตอบคือ
"มันขึ้นอยู่กับ".
หากต้องการสรุปสั้น ๆ หากโมดูลอื่น ๆ ของคุณจะถูกใช้โดยใช่คุณอาจต้องการเพิ่มพื้นที่เก็บข้อมูล
มีอีกปัจจัยหนึ่งที่มานับที่นี่: ใน Magento 2 ที่เก็บสามารถเปิดเผยได้อย่างง่ายดายเหมือน Web API - นั่นคือ REST และ SOAP - แหล่งข้อมูล
หากนั่นเป็นสิ่งที่น่าสนใจสำหรับคุณเนื่องจากการรวมระบบของบุคคลที่สามหรือการตั้งค่า Magento ที่ไม่มีส่วนหัวดังนั้นคุณอาจต้องการเพิ่มที่เก็บสำหรับเอนทิตีของคุณอีกครั้ง
ฉันจะเพิ่มที่เก็บสำหรับเอนทิตีที่กำหนดเองได้อย่างไร
สมมติว่าคุณต้องการเปิดเผยเอนทิตีของคุณเป็นส่วนหนึ่งของ REST API หากไม่เป็นเช่นนั้นคุณสามารถข้ามส่วนที่กำลังจะมาถึงในการสร้างอินเทอร์เฟซและตรงไปที่ "สร้างที่เก็บและการใช้โมเดลข้อมูล" ด้านล่าง
สร้างที่เก็บข้อมูลและอินเตอร์เฟสโมเดลข้อมูล
สร้างโฟลเดอร์Api/Data/
ในโมดูลของคุณ นี่เป็นเพียงการประชุมคุณสามารถใช้สถานที่อื่นได้ แต่ไม่ควรทำ
พื้นที่เก็บข้อมูลจะเข้าไปในApi/
โฟลเดอร์ Data/
ไดเรกทอรีย่อยสำหรับในภายหลัง
ในApi/
สร้างอินเทอร์เฟซ PHP ด้วยวิธีการที่คุณต้องการเปิดเผย ตามระเบียบของวีโอไอพี 2 ชื่ออินเตอร์เฟสทั้งหมดจะลงท้ายInterface
ด้วยคำต่อท้าย
ตัวอย่างเช่นสำหรับนิติบุคคลที่ผมจะสร้างอินเตอร์เฟซ Hamburger
Api/HamburgerRepositoryInterface
สร้างอินเตอร์เฟสที่เก็บ
Magento 2 repositories เป็นส่วนหนึ่งของตรรกะโดเมนของโมดูล ซึ่งหมายความว่าไม่มีชุดวิธีการแก้ไขที่เก็บต้องดำเนินการ
ขึ้นอยู่กับวัตถุประสงค์ของโมดูล
อย่างไรก็ตามในทางปฏิบัติที่เก็บข้อมูลทั้งหมดนั้นค่อนข้างคล้ายกัน พวกเขาเป็นเครื่องห่อสำหรับฟังก์ชั่น CRUD
ส่วนใหญ่จะมีวิธีการgetById
, save
, และdelete
อาจมีมากกว่านั้นตัวอย่างเช่นมีวิธีที่ดึงลูกค้าทางอีเมลโดยที่จะใช้เพื่อดึงข้อมูลลูกค้าตามรหัสเอนทิตี getList
CustomerRepository
get
getById
นี่คืออินเทอร์เฟซที่เก็บตัวอย่างสำหรับเอนทิตีแฮมเบอร์เกอร์:
<?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);
}
สิ่งสำคัญ! ที่นี่เป็น timesinks!
มี gotchas อยู่สองสามที่นี่ซึ่งยากที่จะทำการดีบั๊กถ้าคุณทำผิด:
- อย่าใช้ประเภทอาร์กิวเมนต์สเกลาร์PHP7หรือประเภทส่งคืนหากคุณต้องการเชื่อมต่อกับ REST API!
- เพิ่มคำอธิบายประกอบ PHPDoc สำหรับข้อโต้แย้งทั้งหมดและประเภทกลับไปที่วิธีการทั้งหมด!
- ใช้ชื่อคลาสที่ผ่านการรับรองอย่างสมบูรณ์ในบล็อก PHPDoc!
หมายเหตุประกอบจะถูกวิเคราะห์โดย Magento Framework เพื่อกำหนดวิธีการแปลงข้อมูลไปและกลับจาก JSON หรือ XML การอิมพอร์ตคลาส (นั่นคือuse
ข้อความสั่ง) จะไม่ถูกนำไปใช้!
ทุกวิธีจะต้องมีคำอธิบายประกอบที่มีประเภทอาร์กิวเมนต์ใด ๆ และประเภทส่งคืน แม้ว่าเมธอดจะไม่มีอาร์กิวเมนต์และไม่ส่งคืนสิ่งใดมันก็จะต้องมีหมายเหตุประกอบ:
/**
* @return void
*/
ประเภทเกลา ( string
, int
, float
และbool
) นอกจากนี้ยังจะต้องมีการระบุทั้งข้อโต้แย้งและเป็นค่าตอบแทน
โปรดทราบว่าในตัวอย่างข้างต้นคำอธิบายประกอบสำหรับวิธีการที่ส่งคืนวัตถุจะถูกระบุเป็นอินเตอร์เฟสเช่นกัน
อินเตอร์เฟสชนิดคืนค่าทั้งหมดในApi\Data
เนมสเปซ / ไดเร็กทอรี
นี่เป็นการระบุว่าพวกเขาไม่มีตรรกะทางธุรกิจใด ๆ มันเป็นเพียงข้อมูล
เราต้องสร้างอินเตอร์เฟสเหล่านี้ต่อไป
สร้างอินเทอร์เฟซ DTO
ฉันคิดว่า Magento เรียกอินเทอร์เฟซ "data models" ซึ่งเป็นชื่อที่ฉันไม่ชอบเลย
ประเภทของชั้นนี้เป็นที่รู้จักกันทั่วไปว่าเป็นวัตถุการถ่ายโอนข้อมูลหรือDTO
คลาส DTO เหล่านี้มี getters และ setters สำหรับคุณสมบัติทั้งหมดเท่านั้น
เหตุผลที่ฉันชอบใช้ DTO มากกว่า data model เพราะมันสับสนน้อยกว่ากับโมเดลข้อมูล ORM, model resource หรือดู model ... หลาย ๆ สิ่งนั้นเป็น model ใน Magento อยู่แล้ว
ข้อ จำกัด เดียวกันกับการพิมพ์ PHP7 ที่ใช้กับที่เก็บยังนำไปใช้กับ DTO ด้วย
นอกจากนี้ทุกวิธีจะต้องมีคำอธิบายประกอบที่มีประเภทอาร์กิวเมนต์ทั้งหมดและประเภทส่งคืน
<?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);
}
หากวิธีการดึงหรือผลตอบแทนอาร์เรย์ประเภทของรายการในอาร์เรย์จะต้องมีการระบุไว้ในคำอธิบายประกอบ PHPDoc []
ตามด้วยการเปิดและปิดวงเล็บเหลี่ยม
สิ่งนี้เป็นจริงสำหรับทั้งค่าสเกลาร์ (เช่นint[]
) และวัตถุ (เช่นIngredientInterface[]
)
โปรดทราบว่าฉันใช้Api\Data\IngredientInterface
เป็นตัวอย่างสำหรับวิธีการคืนค่าอาร์เรย์ของวัตถุฉันจะไม่เพิ่มรหัสของส่วนผสมลงในบทความนี้
ExtensibleDataInterface?
ในตัวอย่างข้างต้นขยายHamburgerInterface
ในทางเทคนิคสิ่งนี้จำเป็นเฉพาะถ้าคุณต้องการให้โมดูลอื่นสามารถเพิ่มคุณสมบัติให้กับเอนทิตีของคุณ
ถ้าเป็นเช่นนั้นคุณยังต้องเพิ่มคู่ getter / หมาอีกโดยการประชุมที่เรียกว่าและ ExtensibleDataInterface
getExtensionAttributes()
setExtensionAttributes()
การตั้งชื่อประเภทการคืนสินค้าของวิธีนี้มีความสำคัญมาก!
เฟรมเวิร์ก Magento 2 จะสร้างส่วนต่อประสานการนำไปปฏิบัติและโรงงานสำหรับการนำไปใช้หากคุณตั้งชื่อให้ถูกต้อง รายละเอียดของกลไกเหล่านี้อยู่นอกขอบเขตของบทความนี้
เพียงแค่รู้ว่าถ้าอินเตอร์เฟซของวัตถุที่คุณต้องการที่จะทำให้การขยายที่เรียกว่าแล้วขยายแอตทริบิวต์ประเภทจะต้องมี\VinaiKopp\Kitchen\Api\Data\HamburgerInterface
\VinaiKopp\Kitchen\Api\Data\HamburgerExtensionInterface
ดังนั้นคำว่าExtension
จะต้องถูกแทรกหลังชื่อเอนทิตีก่อนหน้าInterface
คำต่อท้าย
หากคุณไม่ต้องการที่นิติบุคคลของคุณจะขยายแล้วอินเตอร์เฟซ DTO ไม่ได้มีการขยายการอินเตอร์เฟซที่อื่น ๆ และgetExtensionAttributes()
และsetExtensionAttributes()
วิธีการสามารถละเว้น
พอเกี่ยวกับอินเทอร์เฟซ DTO ในขณะนี้ถึงเวลาที่จะกลับไปที่อินเทอร์เฟซที่เก็บข้อมูล
getList () ประเภทส่งคืน SearchResults
วิธีการเก็บข้อมูลgetList
กลับมาอีกประเภทหนึ่งนั่นคือSearchResultsInterface
อินสแตนซ์
getList
แน่นอนว่าวิธีการนั้นอาจส่งคืนอาร์เรย์ของวัตถุที่ตรงกับที่ระบุSearchCriteria
แต่การส่งคืนSearchResults
อินสแตนซ์ช่วยให้สามารถเพิ่มข้อมูลเมตาที่มีประโยชน์บางอย่างให้กับค่าที่ส่งคืน
คุณสามารถดูวิธีการทำงานด้านล่างในgetList()
การใช้วิธีการเก็บข้อมูล
นี่คืออินเทอร์เฟซผลการค้นหาแฮมเบอร์เกอร์ตัวอย่าง:
<?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);
}
อินเทอร์เฟซทั้งหมดนี้จะมีการแทนที่ชนิดของวิธีการสองวิธีgetItems()
และsetItems()
ของอินเทอร์เฟซหลัก
สรุปอินเทอร์เฟซ
ตอนนี้เรามีอินเทอร์เฟซต่อไปนี้:
\VinaiKopp\Kitchen\Api\HamburgerRepositoryInterface
\VinaiKopp\Kitchen\Api\Data\HamburgerInterface
\VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface
พื้นที่เก็บข้อมูลขยายอะไรขยาย,
และขยาย
HamburgerInterface
\Magento\Framework\Api\ExtensibleDataInterface
HamburgerSearchResultInterface
\Magento\Framework\Api\SearchResultsInterface
สร้างการนำไปใช้ที่เก็บและโมเดลข้อมูล
ขั้นตอนต่อไปคือการสร้างการใช้งานของสามอินเตอร์เฟส
พื้นที่เก็บข้อมูล
ในสาระสำคัญที่เก็บใช้ ORM ที่จะทำงานมัน
getById()
, save()
และdelete()
วิธีการที่ค่อนข้างตรงไปตรงมา ถูกฉีดเข้าไปในพื้นที่เก็บข้อมูลเป็นอาร์กิวเมนต์นวกรรมิกที่สามารถมองเห็นบิตดังต่อไปนี้
HamburgerFactory
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);
}
ตอนนี้เป็นส่วนที่น่าสนใจที่สุดของพื้นที่เก็บข้อมูลgetList()
วิธีการ วิธีการที่มีการแปลสภาพลงในโทรวิธีการในการเก็บรวบรวม
getList()
SerachCriteria
ส่วนที่ยุ่งยากของการรับAND
และOR
เงื่อนไขสำหรับตัวกรองถูกต้องโดยเฉพาะอย่างยิ่งเนื่องจากไวยากรณ์สำหรับการตั้งค่าเงื่อนไขในคอลเลกชันจะแตกต่างกันขึ้นอยู่กับว่ามันเป็น EAV หรือเอนทิตีตารางแบน
ในกรณีส่วนใหญ่getList()
สามารถใช้งานได้ตามตัวอย่างด้านล่าง
<?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;
}
}
ตัวกรองภายในFilterGroup
ต้องรวมกันโดยใช้ตัวดำเนินการOR
กลุ่มกรองเฉพาะกิจการจะรวมกันโดยใช้ตรรกะและผู้ประกอบการ
ว้า
นี่เป็นงานที่ใหญ่ที่สุด การใช้อินเตอร์เฟสอื่น ๆ นั้นง่ายกว่า
DTO
Magento เดิมทีตั้งใจให้นักพัฒนาใช้ DTO เป็นคลาสแยกต่างหากซึ่งแตกต่างจากเอนทิตีโมเดล
ทีมหลักทำสิ่งนี้เฉพาะกับโมดูลของลูกค้าเท่านั้น ( \Magento\Customer\Api\Data\CustomerInterface
ดำเนินการโดย\Magento\Customer\Model\Data\Customer
ไม่ใช่\Magento\Customer\Model\Customer
)
ในกรณีอื่นทั้งหมดโมเดลเอนทิตีใช้อินเทอร์เฟซ DTO (ตัวอย่างเช่น\Magento\Catalog\Api\Data\ProductInterface
นำมาใช้โดย\Magento\Catalog\Model\Product
)
ฉันถามสมาชิกของทีมหลักเกี่ยวกับเรื่องนี้ในการประชุม แต่ฉันไม่ได้รับการตอบสนองที่ชัดเจนว่าอะไรคือสิ่งที่ควรพิจารณาในการฝึกฝนที่ดี
ความประทับใจของฉันคือการแนะนำนี้ถูกทอดทิ้ง มันคงจะดีถ้าได้รับแถลงการณ์อย่างเป็นทางการในเรื่องนี้
สำหรับตอนนี้ฉันได้ทำการตัดสินใจอย่างจริงจังเพื่อใช้โมเดลเป็นการนำอินเตอร์เฟส DTO ไปใช้งาน หากคุณรู้สึกว่าการใช้โมเดลข้อมูลแยกต่างหากนั้นสะอาดกว่า วิธีการทั้งสองทำงานได้ดีในทางปฏิบัติ
หาก inteface DTO จะขยายรูปแบบที่มีการขยายMagento\Framework\Api\ExtensibleDataInterface
หากคุณไม่สนใจเกี่ยวกับความสามารถในการขยายโมเดลก็สามารถขยายคลาสพื้นฐานของโมเดล ORM ต่อไปได้ Magento\Framework\Model\AbstractExtensibleModel
Magento\Framework\Model\AbstractModel
เนื่องจากตัวอย่างHamburgerInterface
ขยายExtensibleDataInterface
รูปแบบแฮมเบอร์เกอร์ที่ขยายAbstractExtensibleModel
ดังที่สามารถเห็นได้ที่นี่:
<?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);
}
}
การแยกชื่อคุณสมบัติเป็นค่าคงที่อนุญาตให้เก็บไว้ในที่เดียว สามารถใช้ได้โดยคู่ getter / setter และโดยสคริปต์การตั้งค่าที่สร้างตารางฐานข้อมูล มิฉะนั้นจะไม่มีประโยชน์ในการแยกมันออกเป็นค่าคงที่
SearchResult
นี่SearchResultsInterface
เป็นอินเทอร์เฟซสามตัวที่ง่ายที่สุดที่จะใช้เนื่องจากมันสามารถสืบทอดฟังก์ชันการทำงานทั้งหมดได้จากคลาสเฟรมเวิร์ก
<?php
namespace VinaiKopp\Kitchen\Model;
use Magento\Framework\Api\SearchResults;
use VinaiKopp\Kitchen\Api\Data\HamburgerSearchResultInterface;
class HamburgerSearchResult extends SearchResults implements HamburgerSearchResultInterface
{
}
กำหนดค่าการกำหนดค่าตามความชอบ ObjectManager
แม้ว่าการใช้งานจะเสร็จสมบูรณ์เรายังคงไม่สามารถใช้อินเทอร์เฟซเป็นการพึ่งพาของคลาสอื่น ๆ ได้เนื่องจากตัวจัดการวัตถุ Magento Framework ไม่ทราบว่าการประยุกต์ใช้งานแบบใด เราจำเป็นต้องเพิ่มการetc/di.xml
กำหนดค่าสำหรับด้วยการตั้งค่า
<?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>
ที่เก็บสามารถแสดงเป็นทรัพยากร API ได้อย่างไร
ส่วนนี้ง่ายมากมันเป็นรางวัลสำหรับการทำงานทั้งหมดที่สร้างอินเทอร์เฟซการใช้งานและการเชื่อมต่อเข้าด้วยกัน
สิ่งที่เราต้องทำคือสร้างetc/webapi.xml
ไฟล์
<?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>
โปรดทราบว่าการกำหนดค่านี้ไม่เพียง แต่ช่วยให้การใช้พื้นที่เก็บข้อมูลเป็นปลายทาง REST แต่ยังเปิดเผยวิธีการที่เป็นส่วนหนึ่งของ SOAP API
ในเส้นทางตัวอย่างแรก<route method="GET" url="/V1/vinaikopp_hamburgers/:id">
ตัวยึดมีให้ตรงกับชื่อของการโต้แย้งเป็นวิธีแมป:id
สองชื่อต้องตรงกับตัวอย่างเช่นจะไม่ทำงานเนื่องจากชื่อวิธีตัวแปรอาร์กิวเมนต์เป็น public function getById($id)
/V1/vinaikopp_hamburgers/:hamburgerId
$id
สำหรับตัวอย่างนี้ผมได้ตั้ง accessability <resource ref="anonymous"/>
ไป ซึ่งหมายความว่าทรัพยากรถูกเปิดเผยสู่สาธารณะโดยไม่มีข้อ จำกัด ! เพื่อให้เป็นแหล่งข้อมูลที่สามารถใช้ได้เฉพาะกับลูกค้าเข้าสู่ระบบในการใช้งาน
<resource ref="self"/>
ในกรณีนี้คำพิเศษme
ใน URL ปลายทางของทรัพยากรจะถูกใช้เพื่อเติมตัวแปรอาร์กิวเมนต์$id
ด้วย ID ของลูกค้าที่เข้าสู่ระบบในปัจจุบัน
ลองดูที่ Magento Customer etc/webapi.xml
และCustomerRepositoryInterface
หากคุณต้องการสิ่งนั้น
ในที่สุด<resources>
สามารถใช้เพื่อ จำกัด การเข้าถึงทรัพยากรไปยังบัญชีผู้ใช้ของผู้ดูแลระบบ เมื่อต้องการทำสิ่งนี้ให้ตั้งค่าการ<resource>
อ้างอิงเป็นตัวระบุที่กำหนดไว้ในetc/acl.xml
ไฟล์
ตัวอย่างเช่น<resource ref="Magento_Customer::manage"/>
จะ จำกัด การเข้าถึงบัญชีผู้ดูแลระบบที่มีสิทธิ์จัดการลูกค้า
ตัวอย่างแบบสอบถาม API ที่ใช้ curl อาจมีลักษณะเช่นนี้:
$ curl -X GET http://example.com/rest/V1/vinaikopp_hamburgers/123
หมายเหตุ: การเขียนสิ่งนี้เริ่มต้นเป็นคำตอบไปที่https://github.com/astorm/pestle/issues/195
ตรวจสอบสาก , ซื้อCommercebugและกลายเป็นpatreonของ @alanstorm