API Magento 2 REST menggunakan modul sederhana sebagai contoh

Saya menyambut Anda, Habravite tersayang! Karena saya telah mengembangkan pada platform e-commerce Magento sejak 2013, setelah mengumpulkan keberanian dan percaya bahwa di bidang ini saya dapat menyebut diri saya, setidaknya, seorang pengembang yang percaya diri, saya memutuskan untuk menulis artikel pertama saya di hub tentang sistem ini. Dan saya akan mulai dengan implementasi REST API di Magento 2. Di sini, di luar kotak ada fungsi untuk memproses permintaan dan saya akan mencoba untuk mendemonstrasikannya menggunakan contoh modul sederhana. Artikel ini lebih ditujukan untuk mereka yang telah bekerja dengan Magenta. Jadi, yang tertarik, tolong, di bawah kucing.

Dasi


Imajinasi saya sangat buruk, jadi saya menghasilkan contoh berikut: bayangkan bahwa kita perlu mengimplementasikan blog, hanya pengguna dari panel admin yang dapat menulis artikel. Dari waktu ke waktu beberapa CRM mengetuk kami dan mengunggah artikel-artikel ini ke dirinya sendiri (mengapa tidak jelas, tapi itulah cara kami akan membenarkan menggunakan REST API). Untuk menyederhanakan modul, saya secara khusus menghilangkan implementasi menampilkan artikel di frontend dan di panel admin (Anda dapat mengimplementasikannya sendiri, saya sarankan artikel yang bagus di grid). Hanya fungsionalitas pemrosesan permintaan yang akan terpengaruh di sini.

Pengembangan aksi


Pertama, buat struktur modul, sebut saja AlexPoletaev_Blog (kurangnya imajinasi belum hilang). Kami menempatkan modul di direktori aplikasi / kode .

AlexPoletaev / Blog / etc / module.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="AlexPoletaev_Blog" setup_version="1.0.0"/> </config> 


AlexPoletaev / Blog / registration.php
 <?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'AlexPoletaev_Blog', __DIR__ ); 


Kedua file ini adalah minimum yang diperlukan untuk modul.

Jika semuanya dilakukan dalam Feng Shui, maka kita perlu membuat kontrak layanan (apa itu di dalam Magenta dan cara kerjanya, Anda dapat membaca di sini dan di sini ), yang akan kita lakukan:

AlexPoletaev / Blog / Api / Data / PostInterface.php
 <?php namespace AlexPoletaev\Blog\Api\Data; /** * Interface PostInterface * @package AlexPoletaev\Api\Data * @api */ interface PostInterface { /**#@+ * Constants * @var string */ const ID = 'id'; const AUTHOR_ID = 'author_id'; const TITLE = 'title'; const CONTENT = 'content'; const CREATED_AT = 'created_at'; const UPDATED_AT = 'updated_at'; /**#@-*/ /** * @return int */ public function getId(); /** * @param int $id * @return $this */ public function setId($id); /** * @return int */ public function getAuthorId(); /** * @param int $authorId * @return $this */ public function setAuthorId($authorId); /** * @return string */ public function getTitle(); /** * @param string $title * @return $this */ public function setTitle(string $title); /** * @return string */ public function getContent(); /** * @param string $content * @return $this */ public function setContent(string $content); /** * @return string */ public function getCreatedAt(); /** * @param string $createdAt * @return $this */ public function setCreatedAt(string $createdAt); /** * @return string */ public function getUpdatedAt(); /** * @param string $updatedAt * @return $this */ public function setUpdatedAt(string $updatedAt); } 


AlexPoletaev / Blog / Api / PostRepositoryInterface.php
 <?php namespace AlexPoletaev\Blog\Api; use AlexPoletaev\Blog\Api\Data\PostInterface; use Magento\Framework\Api\SearchCriteriaInterface; /** * Interface PostRepositoryInterface * @package AlexPoletaev\Api * @api */ interface PostRepositoryInterface { /** * @param int $id * @return \AlexPoletaev\Blog\Api\Data\PostInterface */ public function get(int $id); /** * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @return \AlexPoletaev\Blog\Api\Data\PostSearchResultInterface */ public function getList(SearchCriteriaInterface $searchCriteria); /** * @param \AlexPoletaev\Blog\Api\Data\PostInterface $post * @return \AlexPoletaev\Blog\Api\Data\PostInterface */ public function save(PostInterface $post); /** * @param \AlexPoletaev\Blog\Api\Data\PostInterface $post * @return bool */ public function delete(PostInterface $post); /** * @param int $id * @return bool */ public function deleteById(int $id); } 


Mari kita menganalisis dua antarmuka ini lebih terinci. Antarmuka PostInterface menampilkan tabel dengan artikel dari blog kami. Buat tabel di bawah ini. Setiap kolom dari database harus memiliki pengambil dan penyetel sendiri di antarmuka ini, kami akan mencari tahu mengapa ini penting nanti. Antarmuka PostRepositoryInterface menyediakan seperangkat metode standar untuk berinteraksi dengan database dan menyimpan entitas yang dimuat dalam cache. Metode yang sama digunakan untuk API. Catatan penting lainnya, keberadaan PHPDocs yang benar di antarmuka ini diperlukan , karena Magenta, saat memproses permintaan REST, menggunakan refleksi untuk menentukan parameter input dan mengembalikan nilai dalam metode.

Dengan menggunakan skrip instal, buat tabel tempat posting dari blog akan disimpan:

AlexPoletaev / Blog / Setup / InstallSchema.php
 <?php namespace AlexPoletaev\Blog\Setup; use AlexPoletaev\Blog\Api\Data\PostInterface; use AlexPoletaev\Blog\Model\ResourceModel\Post as PostResource; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Ddl\Table; use Magento\Framework\Setup\InstallSchemaInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\SchemaSetupInterface; use Magento\Security\Setup\InstallSchema as SecurityInstallSchema; /** * Class InstallSchema * @package AlexPoletaev\Blog\Setup */ class InstallSchema implements InstallSchemaInterface { /** * Installs DB schema for a module * * @param SchemaSetupInterface $setup * @param ModuleContextInterface $context * @return void */ public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) { $setup->startSetup(); $table = $setup->getConnection() ->newTable( $setup->getTable(PostResource::TABLE_NAME) ) ->addColumn( PostInterface::ID, Table::TYPE_INTEGER, null, ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], 'Post ID' ) ->addColumn( PostInterface::AUTHOR_ID, Table::TYPE_INTEGER, null, ['unsigned' => true, 'nullable' => true,], 'Author ID' ) ->addColumn( PostInterface::TITLE, Table::TYPE_TEXT, 255, [], 'Title' ) ->addColumn( PostInterface::CONTENT, Table::TYPE_TEXT, null, [], 'Content' ) ->addColumn( 'created_at', Table::TYPE_TIMESTAMP, null, ['nullable' => false, 'default' => Table::TIMESTAMP_INIT], 'Creation Time' ) ->addColumn( 'updated_at', Table::TYPE_TIMESTAMP, null, ['nullable' => false, 'default' => Table::TIMESTAMP_INIT_UPDATE], 'Update Time' ) ->addForeignKey( $setup->getFkName( PostResource::TABLE_NAME, PostInterface::AUTHOR_ID, SecurityInstallSchema::ADMIN_USER_DB_TABLE_NAME, 'user_id' ), PostInterface::AUTHOR_ID, $setup->getTable(SecurityInstallSchema::ADMIN_USER_DB_TABLE_NAME), 'user_id', Table::ACTION_SET_NULL ) ->addIndex( $setup->getIdxName( PostResource::TABLE_NAME, [PostInterface::AUTHOR_ID], AdapterInterface::INDEX_TYPE_INDEX ), [PostInterface::AUTHOR_ID], ['type' => AdapterInterface::INDEX_TYPE_INDEX] ) ->setComment('Posts') ; $setup->getConnection()->createTable($table); $setup->endSetup(); } } 


Tabel akan memiliki kolom berikut (jangan lupa, kami memiliki semuanya sesederhana mungkin):

  • peningkatan id - otomatis
  • author_id - pengidentifikasi pengguna admin (kunci asing pada bidang user_id dari tabel admin_user)
  • judul - judul
  • konten - teks artikel
  • Created_at - tanggal pembuatan
  • updated_at - edit tanggal

Sekarang Anda perlu membuat set standar kelas Model Magenta, ResourceModel dan Koleksi . Mengapa saya tidak akan melukis kelas-kelas ini, topik ini luas dan melampaui ruang lingkup artikel ini, yang tertarik, dapat google sendiri. Singkatnya, kelas-kelas ini diperlukan untuk memanipulasi entitas (artikel) dari database. Saya menyarankan Anda untuk membaca tentang Model Domain, Repositori dan pola-pola Lapisan Layanan.

AlexPoletaev / Blog / Model / Post.php
 <?php namespace AlexPoletaev\Blog\Model; use AlexPoletaev\Blog\Api\Data\PostInterface; use AlexPoletaev\Blog\Model\ResourceModel\Post as PostResource; use Magento\Framework\Model\AbstractModel; /** * Class Post * @package AlexPoletaev\Blog\Model */ class Post extends AbstractModel implements PostInterface { /** * @var string */ protected $_idFieldName = PostInterface::ID; //@codingStandardsIgnoreLine /** * @inheritdoc */ protected function _construct() //@codingStandardsIgnoreLine { $this->_init(PostResource::class); } /** * @return int */ public function getAuthorId() { return $this->getData(PostInterface::AUTHOR_ID); } /** * @param int $authorId * @return $this */ public function setAuthorId($authorId) { $this->setData(PostInterface::AUTHOR_ID, $authorId); return $this; } /** * @return string */ public function getTitle() { return $this->getData(PostInterface::TITLE); } /** * @param string $title * @return $this */ public function setTitle(string $title) { $this->setData(PostInterface::TITLE, $title); return $this; } /** * @return string */ public function getContent() { return $this->getData(PostInterface::CONTENT); } /** * @param string $content * @return $this */ public function setContent(string $content) { $this->setData(PostInterface::CONTENT, $content); return $this; } /** * @return string */ public function getCreatedAt() { return $this->getData(PostInterface::CREATED_AT); } /** * @param string $createdAt * @return $this */ public function setCreatedAt(string $createdAt) { $this->setData(PostInterface::CREATED_AT, $createdAt); return $this; } /** * @return string */ public function getUpdatedAt() { return $this->getData(PostInterface::UPDATED_AT); } /** * @param string $updatedAt * @return $this */ public function setUpdatedAt(string $updatedAt) { $this->setData(PostInterface::UPDATED_AT, $updatedAt); return $this; } } 


AlexPoletaev / Blog / Model / ResourceModel / Post.php
 <?php namespace AlexPoletaev\Blog\Model\ResourceModel; use AlexPoletaev\Blog\Api\Data\PostInterface; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; /** * Class Post * @package AlexPoletaev\Blog\Model\ResourceModel */ class Post extends AbstractDb { /** * @var string */ const TABLE_NAME = 'alex_poletaev_blog_post'; /** * Resource initialization * * @return void */ protected function _construct() //@codingStandardsIgnoreLine { $this->_init(self::TABLE_NAME, PostInterface::ID); } } 


AlexPoletaev / Blog / Model / ResourceModel / Post / Collection.php
 <?php namespace AlexPoletaev\Blog\Model\ResourceModel\Post; use AlexPoletaev\Blog\Model\Post; use AlexPoletaev\Blog\Model\ResourceModel\Post as PostResource; use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; /** * Class Collection * @package AlexPoletaev\Blog\Model\ResourceModel\Post */ class Collection extends AbstractCollection { /** * @inheritdoc */ protected function _construct() //@codingStandardsIgnoreLine { $this->_init(Post::class, PostResource::class); } } 


Pembaca yang penuh perhatian akan melihat bahwa model kami mengimplementasikan antarmuka yang dibuat sebelumnya dan semua getter dan setternya.

Pada saat yang sama, kami menerapkan repositori dan metode-metodenya:

AlexPoletaev / Blog / Model / PostRepository.php
 <?php namespace AlexPoletaev\Blog\Model; use AlexPoletaev\Blog\Api\Data\PostInterface; use AlexPoletaev\Blog\Api\Data\PostSearchResultInterface; use AlexPoletaev\Blog\Api\Data\PostSearchResultInterfaceFactory; use AlexPoletaev\Blog\Api\PostRepositoryInterface; use AlexPoletaev\Blog\Model\ResourceModel\Post as PostResource; use AlexPoletaev\Blog\Model\ResourceModel\Post\Collection as PostCollection; use AlexPoletaev\Blog\Model\ResourceModel\Post\CollectionFactory as PostCollectionFactory; use AlexPoletaev\Blog\Model\PostFactory; use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\StateException; /** * Class PostRepository * @package AlexPoletaev\Blog\Model */ class PostRepository implements PostRepositoryInterface { /** * @var array */ private $registry = []; /** * @var PostResource */ private $postResource; /** * @var PostFactory */ private $postFactory; /** * @var PostCollectionFactory */ private $postCollectionFactory; /** * @var PostSearchResultInterfaceFactory */ private $postSearchResultFactory; /** * @param PostResource $postResource * @param PostFactory $postFactory * @param PostCollectionFactory $postCollectionFactory * @param PostSearchResultInterfaceFactory $postSearchResultFactory */ public function __construct( PostResource $postResource, PostFactory $postFactory, PostCollectionFactory $postCollectionFactory, PostSearchResultInterfaceFactory $postSearchResultFactory ) { $this->postResource = $postResource; $this->postFactory = $postFactory; $this->postCollectionFactory = $postCollectionFactory; $this->postSearchResultFactory = $postSearchResultFactory; } /** * @param int $id * @return PostInterface * @throws NoSuchEntityException */ public function get(int $id) { if (!array_key_exists($id, $this->registry)) { $post = $this->postFactory->create(); $this->postResource->load($post, $id); if (!$post->getId()) { throw new NoSuchEntityException(__('Requested post does not exist')); } $this->registry[$id] = $post; } return $this->registry[$id]; } /** * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @return \AlexPoletaev\Blog\Api\Data\PostSearchResultInterface */ public function getList(SearchCriteriaInterface $searchCriteria) { /** @var PostCollection $collection */ $collection = $this->postCollectionFactory->create(); foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } /** @var PostSearchResultInterface $searchResult */ $searchResult = $this->postSearchResultFactory->create(); $searchResult->setSearchCriteria($searchCriteria); $searchResult->setItems($collection->getItems()); $searchResult->setTotalCount($collection->getSize()); return $searchResult; } /** * @param \AlexPoletaev\Blog\Api\Data\PostInterface $post * @return PostInterface * @throws StateException */ public function save(PostInterface $post) { try { /** @var Post $post */ $this->postResource->save($post); $this->registry[$post->getId()] = $this->get($post->getId()); } catch (\Exception $exception) { throw new StateException(__('Unable to save post #%1', $post->getId())); } return $this->registry[$post->getId()]; } /** * @param \AlexPoletaev\Blog\Api\Data\PostInterface $post * @return bool * @throws StateException */ public function delete(PostInterface $post) { try { /** @var Post $post */ $this->postResource->delete($post); unset($this->registry[$post->getId()]); } catch (\Exception $e) { throw new StateException(__('Unable to remove post #%1', $post->getId())); } return true; } /** * @param int $id * @return bool */ public function deleteById(int $id) { return $this->delete($this->get($id)); } } 


Metode \AlexPoletaev\Blog\Model\PostRepository::getList() harus mengembalikan data dalam format tertentu, jadi kita juga memerlukan antarmuka ini:

AlexPoletaev / Blog / Api / Data / PostSearchResultInterface.php
 <?php namespace AlexPoletaev\Blog\Api\Data; use Magento\Framework\Api\SearchResultsInterface; /** * Interface PostSearchResultInterface * @package AlexPoletaev\Blog\Api\Data */ interface PostSearchResultInterface extends SearchResultsInterface { /** * @return \AlexPoletaev\Blog\Api\Data\PostInterface[] */ public function getItems(); /** * @param \AlexPoletaev\Blog\Api\Data\PostInterface[] $items * @return $this */ public function setItems(array $items); } 


Untuk membuatnya lebih mudah untuk menguji modul kami, kami akan membuat dua skrip konsol yang menambah dan menghapus data uji dari tabel:

AlexPoletaev / Blog / Console / Command / DeploySampleDataCommand.php
 <?php namespace AlexPoletaev\Blog\Console\Command; use AlexPoletaev\Blog\Api\PostRepositoryInterface; use AlexPoletaev\Blog\Model\Post; use AlexPoletaev\Blog\Model\PostFactory; use Magento\User\Api\Data\UserInterface; use Magento\User\Model\User; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Class DeploySampleDataCommand * @package AlexPoletaev\Blog\Console\Command */ class DeploySampleDataCommand extends Command { /**#@+ * @var string */ const ARGUMENT_USERNAME = 'username'; const ARGUMENT_NUMBER_OF_RECORDS = 'number_of_records'; /**#@-*/ /** * @var PostFactory */ private $postFactory; /** * @var PostRepositoryInterface */ private $postRepository; /** * @var UserInterface */ private $user; /** * @param PostFactory $postFactory * @param PostRepositoryInterface $postRepository * @param UserInterface $user */ public function __construct( PostFactory $postFactory, PostRepositoryInterface $postRepository, UserInterface $user ) { parent::__construct(); $this->postFactory = $postFactory; $this->postRepository = $postRepository; $this->user = $user; } /** * @inheritdoc */ protected function configure() { $this->setName('alex_poletaev:blog:deploy_sample_data') ->setDescription('Blog: deploy sample data') ->setDefinition([ new InputArgument( self::ARGUMENT_USERNAME, InputArgument::REQUIRED, 'Username' ), new InputArgument( self::ARGUMENT_NUMBER_OF_RECORDS, InputArgument::OPTIONAL, 'Number of test records' ), ]) ; parent::configure(); } /** * @inheritdoc */ protected function execute(InputInterface $input, OutputInterface $output) { $username = $input->getArgument(self::ARGUMENT_USERNAME); /** @var User $user */ $user = $this->user->loadByUsername($username); if (!$user->getId() && $output->getVerbosity() > 1) { $output->writeln('<error>User is not found</error>'); return null; } $records = $input->getArgument(self::ARGUMENT_NUMBER_OF_RECORDS) ?: 3; for ($i = 1; $i <= (int)$records; $i++) { /** @var Post $post */ $post = $this->postFactory->create(); $post->setAuthorId($user->getId()); $post->setTitle('test title ' . $i); $post->setContent('test content ' . $i); $this->postRepository->save($post); if ($output->getVerbosity() > 1) { $output->writeln('<info>Post with the ID #' . $post->getId() . ' has been created.</info>'); } } } } 


AlexPoletaev / Blog / Console / Command / RemoveSampleDataCommand.php
 <?php namespace AlexPoletaev\Blog\Console\Command; use AlexPoletaev\Blog\Model\ResourceModel\Post as PostResource; use Magento\Framework\App\ResourceConnection; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Class RemoveSampleDataCommand * @package AlexPoletaev\Blog\Console\Command */ class RemoveSampleDataCommand extends Command { /** * @var ResourceConnection */ private $resourceConnection; /** * @param ResourceConnection $resourceConnection */ public function __construct( ResourceConnection $resourceConnection ) { parent::__construct(); $this->resourceConnection = $resourceConnection; } /** * @inheritdoc */ protected function configure() { $this->setName('alex_poletaev:blog:remove_sample_data') ->setDescription('Blog: remove sample data') ; parent::configure(); } /** * @inheritdoc */ protected function execute(InputInterface $input, OutputInterface $output) { $connection = $this->resourceConnection->getConnection(); $connection->truncateTable($connection->getTableName(PostResource::TABLE_NAME)); if ($output->getVerbosity() > 1) { $output->writeln('<info>Sample data has been successfully removed.</info>'); } } } 


Fitur utama Magento 2 adalah penggunaan yang luas dari penerapan Dependency Injection sendiri . Agar Magenta tahu antarmuka mana yang sesuai dengan implementasi, kita perlu menentukan dependensi ini dalam file di.xml. Pada saat yang sama, kami akan mendaftarkan skrip konsol yang baru dibuat dalam file ini:

AlexPoletaev / Blog / 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="AlexPoletaev\Blog\Api\Data\PostInterface" type="AlexPoletaev\Blog\Model\Post"/> <preference for="AlexPoletaev\Blog\Api\PostRepositoryInterface" type="AlexPoletaev\Blog\Model\PostRepository"/> <preference for="AlexPoletaev\Blog\Api\Data\PostSearchResultInterface" type="Magento\Framework\Api\SearchResults" /> <type name="Magento\Framework\Console\CommandList"> <arguments> <argument name="commands" xsi:type="array"> <item name="deploy_sample_data" xsi:type="object">AlexPoletaev\Blog\Console\Command\DeploySampleDataCommand</item> <item name="remove_sample_data" xsi:type="object">AlexPoletaev\Blog\Console\Command\RemoveSampleDataCommand</item> </argument> </arguments> </type> </config> 


Sekarang daftarkan rute untuk REST API, ini dilakukan di file webapi.xml:

AlexPoletaev / Blog / 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 url="/V1/blog/posts" method="POST"> <service class="AlexPoletaev\Blog\Api\PostRepositoryInterface" method="save"/> <resources> <resource ref="anonymous"/> </resources> </route> <route url="/V1/blog/posts/:id" method="DELETE"> <service class="AlexPoletaev\Blog\Api\PostRepositoryInterface" method="deleteById"/> <resources> <resource ref="anonymous"/> </resources> </route> <route url="/V1/blog/posts/:id" method="GET"> <service class="AlexPoletaev\Blog\Api\PostRepositoryInterface" method="get"/> <resources> <resource ref="anonymous"/> </resources> </route> <route url="/V1/blog/posts" method="GET"> <service class="AlexPoletaev\Blog\Api\PostRepositoryInterface" method="getList"/> <resources> <resource ref="anonymous"/> </resources> </route> </routes> 


Di sini kami memberi tahu Magente antarmuka mana dan metode mana dari antarmuka ini yang digunakan ketika meminta URL tertentu dan dengan metode http tertentu (POST, GET, dll.). Juga, untuk menyederhanakan, sumber daya anonymous digunakan, yang memungkinkan siapa pun untuk mengetuk API kami, jika tidak, Anda perlu mengonfigurasi hak akses (ACL).

Klimaks


Semua langkah selanjutnya mengasumsikan bahwa Anda telah mengaktifkan mode pengembang. Ini menghindari manipulasi yang tidak perlu dengan penyebaran statika konten dan kompilasi DI.

Daftarkan modul baru kami, jalankan perintah: php bin/magento setup:upgrade .

Periksa bahwa tabel alex_poletaev_blog_post baru telah dibuat .

Selanjutnya, muat data uji menggunakan skrip khusus kami:

 php bin/magento -v alex_poletaev:blog:deploy_sample_data admin 

Parameter admin dalam skrip ini adalah nama pengguna dari tabel admin_user (mungkin berbeda untuk Anda), dengan kata lain, pengguna dari panel admin, yang akan ditulis dalam kolom author_id.

Sekarang Anda dapat memulai pengujian. Untuk tes, saya menggunakan Magento 2.2.4, domain http://m224ce.local/ .

Salah satu cara untuk menguji REST API adalah dengan membuka http://m224ce.local/swagger dan menggunakan fungsi getList , tetapi ingat bahwa metode getList tidak berfungsi dengan benar. Saya juga menguji semua metode dengan curl, contoh:

Dapatkan artikel dengan id = 2

 curl -X GET -H "Accept: application/json" "http://m224ce.local/rest/all/V1/blog/posts/2" 

Jawabannya adalah:

 {"id":2,"author_id":1,"title":"test title 2","content":"test content 2","created_at":"2018-06-06 21:35:54","updated_at":"2018-06-06 21:35:54"} 

Dapatkan daftar artikel dengan author_id = 2

 curl -g -X GET -H "Accept: application/json" "http://m224ce.local/rest/all/V1/blog/posts?searchCriteria[filterGroups][0][filters][0][field]=author_id&searchCriteria[filterGroups][0][filters][0][value]=1&searchCriteria[filterGroups][0][filters][0][conditionType]=eq" 

Jawabannya adalah:

 {"items":[{"id":1,"author_id":1,"title":"test title 1","content":"test content 1","created_at":"2018-06-06 21:35:54","updated_at":"2018-06-06 21:35:54"},{"id":2,"author_id":1,"title":"test title 2","content":"test content 2","created_at":"2018-06-06 21:35:54","updated_at":"2018-06-06 21:35:54"},{"id":3,"author_id":1,"title":"test title 3","content":"test content 3","created_at":"2018-06-06 21:35:54","updated_at":"2018-06-06 21:35:54"}],"search_criteria":{"filter_groups":[{"filters":[{"field":"author_id","value":"1","condition_type":"eq"}]}]},"total_count":3} 

Hapus artikel dengan id = 3

 curl -X DELETE -H "Accept: application/json" "http://m224ce.local/rest/all/V1/blog/posts/3" 

Jawabannya adalah:

 true 

Simpan artikel baru

 curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d '{"post": {"author_id": 1, "title": "test title 4", "content": "test content 4"}}' "http://m224ce.local/rest/all/V1/blog/posts" 

Jawabannya adalah:

 {"id":4,"author_id":1,"title":"test title 4","content":"test content 4","created_at":"2018-06-06 21:44:24","updated_at":"2018-06-06 21:44:24"} 

Harap dicatat bahwa untuk permintaan dengan metode http POST, Anda harus melewati kunci posting , yang sebenarnya sesuai dengan parameter input ($ post) untuk metode tersebut

 \AlexPoletaev\Blog\Api\PostRepositoryInterface::save() 

Denouement


Bagi mereka yang tertarik dengan apa yang terjadi selama permintaan dan bagaimana Magenta memprosesnya, di bawah ini saya akan memberikan beberapa tautan ke metode dengan komentar saya. Jika sesuatu tidak berhasil, maka metode ini harus didebitkan terlebih dahulu.

Pengontrol yang bertanggung jawab untuk memproses permintaan
\ Magento \ Webapi \ Controller \ Rest :: dispatch ()

Selanjutnya dipanggil
\ Magento \ Webapi \ Controller \ Rest :: processApiRequest ()

Banyak metode lain disebut di dalam processApiRequest , tetapi yang terpenting berikutnya
\ Magento \ Webapi \ Controller \ Rest \ InputParamsResolver :: resol ()

\ Magento \ Webapi \ Controller \ Rest \ Router :: match () - rute tertentu ditentukan (di dalam, melalui metode \Magento\Webapi\Model\Rest\Config::getRestRoutes() , semua rute yang sesuai ditarik dari permintaan dari permintaan). Objek rute berisi semua data yang diperlukan untuk memproses permintaan - kelas, metode, hak akses, dll.

\ Magento \ Framework \ Webapi \ ServiceInputProcessor :: process ()
- \Magento\Framework\Reflection\MethodsMap::getMethodParams() , di mana parameter metode ditarik melalui refleksi

\ Magento \ Framework \ Webapi \ ServiceInputProcessor :: convertValue () - beberapa opsi untuk mengubah array menjadi DataObject atau menjadi array dari DataObject

\ Magento \ Framework \ Webapi \ ServiceInputProcessor :: _ createFromArray () - konversi langsung, di mana melalui refleksi keberadaan getter dan setter diperiksa (ingat, saya katakan di atas bahwa kami akan kembali kepada mereka?) Dan bahwa mereka memiliki ruang lingkup publik. Selanjutnya, objek diisi dengan data melalui setter.

Pada akhirnya, dalam metode ini
\ Magento \ Webapi \ Controller \ Rest :: processApiRequest () , melalui call_user_func_array metode objek repositori dipanggil.

Epilog


Repositori modul Github

Ada dua cara untuk menginstal:

1) Melalui komposer. Untuk melakukan ini, tambahkan objek berikut ke array repositories di file composer.json

 { "type": "git", "url": "https://github.com/alexpoletaev/magento2-blog-demo" } 

Kemudian ketikkan perintah berikut di terminal:

 composer require alexpoletaev/magento2-blog-demo:dev-master 

2) Unduh file modul dan salin secara manual ke direktori app/code/AlexPoletaev/Blog

Apa pun metode yang Anda pilih, pada akhirnya Anda harus menjalankan pemutakhiran:

 php bin/magento setup:upgrade 

Semoga artikel ini bermanfaat bagi seseorang. Jika Anda memiliki komentar, saran atau pertanyaan, maka selamat datang untuk berkomentar. Terima kasih atas perhatian anda

Source: https://habr.com/ru/post/id413463/


All Articles