أرحب بكم يا حبيبي الحب! نظرًا لأنني أقوم بالتطوير على منصة Magento للتجارة الإلكترونية منذ عام 2013 ، بعد أن جمعت شجاعتي واعتقدت أنه في هذا المجال يمكنني أن أسمي نفسي ، على الأقل ، مطورًا واثقًا ، قررت كتابة مقالتي الأولى على المحور حول هذا النظام. وسأبدأ بتنفيذ واجهة برمجة التطبيقات REST API في Magento 2. هنا ، من خارج الصندوق هناك وظائف لمعالجة الطلبات وسأحاول شرحها باستخدام مثال على وحدة بسيطة. هذه المقالة مخصصة أكثر لأولئك الذين عملوا بالفعل مع Magenta. وهكذا ، من المهتمين ، من فضلك ، تحت القط.
تعادل
مخيلتي سيئة للغاية ، لذلك توصلت إلى المثال التالي: تخيل أننا بحاجة إلى تنفيذ مدونة ، يمكن فقط للمستخدمين من لوحة المشرف كتابة المقالات. من وقت لآخر ، يدق علينا نوع من إدارة علاقات العملاء ويحمل هذه المقالات على نفسه (لماذا لا يكون واضحًا ، ولكن هذه هي الطريقة التي سنبرر بها استخدام REST API). لتبسيط الوحدة ، حذفت على وجه التحديد تنفيذ عرض المقالات على الواجهة الأمامية وفي لوحة المشرف (يمكنك تنفيذها بنفسك ، أوصي
بمقالة جيدة عن الشبكات). سوف تتأثر فقط وظيفة معالجة الاستعلام هنا.
تطوير العمل
أولاً ، قم بإنشاء
بنية الوحدة النمطية ، دعنا نسميها
AlexPoletaev_Blog (لم
يزول نقص الخيال). نضع الوحدة في دليل
التطبيق / الرمز .
AlexPoletaev / مدونة / 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 / مدونة / register.php <?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'AlexPoletaev_Blog', __DIR__ );
هذان الملفان هما الحد الأدنى المطلوب للوحدة النمطية.
إذا تم كل شيء في Feng Shui ، فنحن بحاجة إلى إنشاء عقود خدمة (ما هو داخل Magenta وكيف يعمل ، يمكنك القراءة
هنا وهنا ) ، والذي سنفعله:
AlexPoletaev / المدونة / Api / Data / PostInterface.php <?php namespace AlexPoletaev\Blog\Api\Data; interface PostInterface { const ID = 'id'; const AUTHOR_ID = 'author_id'; const TITLE = 'title'; const CONTENT = 'content'; const CREATED_AT = 'created_at'; const UPDATED_AT = 'updated_at'; public function getId(); public function setId($id); public function getAuthorId(); public function setAuthorId($authorId); public function getTitle(); public function setTitle(string $title); public function getContent(); public function setContent(string $content); public function getCreatedAt(); public function setCreatedAt(string $createdAt); public function getUpdatedAt(); public function setUpdatedAt(string $updatedAt); }
AlexPoletaev / المدونة / Api / PostRepositoryInterface.php <?php namespace AlexPoletaev\Blog\Api; use AlexPoletaev\Blog\Api\Data\PostInterface; use Magento\Framework\Api\SearchCriteriaInterface; interface PostRepositoryInterface { public function get(int $id); public function getList(SearchCriteriaInterface $searchCriteria); public function save(PostInterface $post); public function delete(PostInterface $post); public function deleteById(int $id); }
دعونا نحلل هاتين الواجهتين بمزيد من التفصيل. تعرض واجهة
PostInterface جدولًا بمقالات من مدونتنا. قم بإنشاء جدول أدناه. يجب أن يكون لكل عمود من قاعدة البيانات مُحضر ومُحضر خاص به في هذه الواجهة ، وسنكتشف سبب أهمية ذلك لاحقًا. توفر واجهة
PostRepositoryInterface مجموعة قياسية من الطرق للتفاعل مع قاعدة البيانات وتخزين الكيانات المحملة في ذاكرة التخزين المؤقت. يتم استخدام نفس الأساليب لواجهة برمجة التطبيقات. ملاحظة مهمة أخرى ، يلزم وجود PHPDocs الصحيح في هذه الواجهات ، لأن Magenta ، عند معالجة طلب REST ، تستخدم الانعكاس لتحديد معلمات الإدخال وقيم الإرجاع في الأساليب.
باستخدام برنامج
التثبيت النصي ، أنشئ جدولًا حيث سيتم تخزين المشاركات من المدونة:
AlexPoletaev / المدونة / الإعداد / 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 implements InstallSchemaInterface { 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(); } }
سيحتوي الجدول على الأعمدة التالية (لا تنس ، لدينا كل شيء بسيط قدر الإمكان):
- id - زيادة تلقائية
- author_id - معرف مستخدم المشرف (مفتاح خارجي في حقل user_id من جدول admin_user)
- العنوان - العنوان
- المحتوى - نص المقالة
- create_at - تاريخ الانشاء
- updated_at - تعديل التاريخ
تحتاج الآن إلى إنشاء مجموعة قياسية من فئات Magenta
Model و
ResourceModel و
Collection . لماذا لن أرسم هذه الفئات ، هذا الموضوع واسع ويتجاوز نطاق هذه المقالة ، المهتمين ، يمكنه البحث عن Google بمفرده. باختصار ، هذه الفئات مطلوبة للتعامل مع الكيانات (المقالات) من قاعدة البيانات. أنصحك بالقراءة عن أنماط نموذج المستودع وأنماط طبقة الخدمة.
AlexPoletaev / مدونة / نموذج / 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 extends AbstractModel implements PostInterface { protected $_idFieldName = PostInterface::ID;
AlexPoletaev / مدونة / نموذج / ResourceModel / Post.php <?php namespace AlexPoletaev\Blog\Model\ResourceModel; use AlexPoletaev\Blog\Api\Data\PostInterface; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; class Post extends AbstractDb { const TABLE_NAME = 'alex_poletaev_blog_post'; protected function _construct() //@codingStandardsIgnoreLine { $this->_init(self::TABLE_NAME, PostInterface::ID); } }
AlexPoletaev / مدونة / نموذج / 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 extends AbstractCollection { protected function _construct() //@codingStandardsIgnoreLine { $this->_init(Post::class, PostResource::class); } }
سيلاحظ القارئ اليقظ أن نموذجنا يطبق الواجهة التي تم إنشاؤها سابقًا وجميع المراسلات والمستوطنين.
في نفس الوقت ننفذ المستودع وطرقه:
AlexPoletaev / مدونة / نموذج / 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 implements PostRepositoryInterface { private $registry = []; private $postResource; private $postFactory; private $postCollectionFactory; private $postSearchResultFactory; public function __construct( PostResource $postResource, PostFactory $postFactory, PostCollectionFactory $postCollectionFactory, PostSearchResultInterfaceFactory $postSearchResultFactory ) { $this->postResource = $postResource; $this->postFactory = $postFactory; $this->postCollectionFactory = $postCollectionFactory; $this->postSearchResultFactory = $postSearchResultFactory; } 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]; } public function getList(SearchCriteriaInterface $searchCriteria) { $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()]); } } $searchResult = $this->postSearchResultFactory->create(); $searchResult->setSearchCriteria($searchCriteria); $searchResult->setItems($collection->getItems()); $searchResult->setTotalCount($collection->getSize()); return $searchResult; } public function save(PostInterface $post) { try { $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()]; } public function delete(PostInterface $post) { try { $this->postResource->delete($post); unset($this->registry[$post->getId()]); } catch (\Exception $e) { throw new StateException(__('Unable to remove post #%1', $post->getId())); } return true; } public function deleteById(int $id) { return $this->delete($this->get($id)); } }
يجب أن تُرجع الطريقة
\AlexPoletaev\Blog\Model\PostRepository::getList()
بيانات بتنسيق معين ، لذلك سنحتاج أيضًا إلى هذه الواجهة:
AlexPoletaev / المدونة / Api / Data / PostSearchResultInterface.php <?php namespace AlexPoletaev\Blog\Api\Data; use Magento\Framework\Api\SearchResultsInterface; interface PostSearchResultInterface extends SearchResultsInterface { public function getItems(); public function setItems(array $items); }
لتسهيل اختبار وحدتنا ، سننشئ نصين لوحدة تحكم يضيفان بيانات الاختبار ويزيلانها من الجدول:
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 extends Command { const ARGUMENT_USERNAME = 'username'; const ARGUMENT_NUMBER_OF_RECORDS = 'number_of_records'; private $postFactory; private $postRepository; private $user; public function __construct( PostFactory $postFactory, PostRepositoryInterface $postRepository, UserInterface $user ) { parent::__construct(); $this->postFactory = $postFactory; $this->postRepository = $postRepository; $this->user = $user; } 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(); } protected function execute(InputInterface $input, OutputInterface $output) { $username = $input->getArgument(self::ARGUMENT_USERNAME); $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++) { $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 extends Command { private $resourceConnection; public function __construct( ResourceConnection $resourceConnection ) { parent::__construct(); $this->resourceConnection = $resourceConnection; } protected function configure() { $this->setName('alex_poletaev:blog:remove_sample_data') ->setDescription('Blog: remove sample data') ; parent::configure(); } 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>'); } } }
السمة الرئيسية لـ Magento 2 هي الاستخدام الواسع النطاق لتطبيقها الخاص
لحقن التبعية . لكي تعرف Magenta الواجهة التي يطابقها التنفيذ ، نحتاج إلى تحديد هذه التبعيات في ملف di.xml. في الوقت نفسه ، سنقوم بتسجيل البرامج النصية لوحدة التحكم التي تم إنشاؤها حديثًا في هذا الملف:
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>
الآن قم بتسجيل المسارات لواجهة برمجة تطبيقات REST ، ويتم ذلك في ملف webapi.xml:
AlexPoletaev / مدونة / 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>
هنا نخبر Magente عن أي واجهة وأي طريقة من هذه الواجهة لاستخدامها عند طلب عنوان URL معين وبطريقة http محددة (POST ، GET ، إلخ.). أيضًا ، من أجل التبسيط ، يتم استخدام مورد
anonymous
، مما يسمح لأي شخص بالطرق على واجهة برمجة التطبيقات الخاصة بنا ، وإلا فإنك تحتاج إلى تكوين حقوق الوصول (ACLs).
ذروة
تفترض جميع الخطوات الإضافية أنك مكّنت وضع المطور. هذا يتجنب التلاعبات غير الضرورية مع نشر إحصائيات المحتوى وتجميع DI.
سجل وحدتنا الجديدة ، قم بتشغيل الأمر: إعداد
php bin/magento setup:upgrade
.
تحقق من أنه تم
إنشاء جدول
alex_poletaev_blog_post جديد.
بعد ذلك ، قم بتحميل بيانات الاختبار باستخدام برنامجنا النصي المخصص:
php bin/magento -v alex_poletaev:blog:deploy_sample_data admin
معلمة
المشرف في هذا البرنامج النصي هي
اسم المستخدم من جدول
admin_user (قد يختلف بالنسبة لك) ، في كلمة واحدة ، المستخدم من لوحة المشرف ، والتي ستتم كتابتها في عمود author_id.
الآن يمكنك البدء في الاختبار. للاختبارات ، استخدمت Magento 2.2.4 ، المجال
http://m224ce.local/
.
تتمثل إحدى طرق اختبار REST API في فتح
http://m224ce.local/swagger
واستخدام وظيفة
getList
، ولكن تذكر أن طريقة
getList
لا تعمل هناك بشكل صحيح. لقد اختبرت أيضًا جميع الطرق باستخدام حليقة ، أمثلة:
احصل على مقال
بالمعرف = 2 curl -X GET -H "Accept: application/json" "http://m224ce.local/rest/all/V1/blog/posts/2"
الجواب:
{"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"}
احصل على قائمة بالمقالات مع
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"
الجواب:
{"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}
حذف مقال
بالمعرف = 3 curl -X DELETE -H "Accept: application/json" "http://m224ce.local/rest/all/V1/blog/posts/3"
الجواب:
true
احفظ المقال الجديد
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"
الجواب:
{"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"}
يرجى ملاحظة أنه بالنسبة لطلب بأسلوب http POST ، يجب عليك تمرير مفتاح
البريد ، والذي يتوافق فعليًا مع معلمة الإدخال ($ post) للطريقة
\AlexPoletaev\Blog\Api\PostRepositoryInterface::save()
الخاتمة
بالنسبة لأولئك المهتمين بما يحدث أثناء الطلب وكيف تعالجه Magenta ، سأقدم أدناه بعض الروابط إلى الأساليب مع تعليقاتي. إذا لم ينجح شيء ما ، فيجب خصم هذه الطرق أولاً.
المراقب المسؤول عن معالجة الطلب
\ Magento \ Webapi \ Controller \ Rest :: dispatch ()دعا المقبل
\ Magento \ Webapi \ Controller \ Rest :: processApiRequest ()تسمى العديد من الطرق الأخرى داخل
processApiRequest
، ولكن الطريقة التالية هي الأهم
\ Magento \ Webapi \ Controller \ Rest \ InputParamsResolver :: Resolution ()\ Magento \ Webapi \ Controller \ Rest \ Router :: match () - يتم تحديد مسار معين (من خلال طريقة
\Magento\Webapi\Model\Rest\Config::getRestRoutes()
، يتم سحب جميع المسارات المناسبة من الطلب من الطلب). يحتوي كائن المسار على جميع البيانات اللازمة لمعالجة الطلب - الفئة ، الطريقة ، حقوق الوصول ، إلخ.
\ Magento \ Framework \ Webapi \ ServiceInputProcessor :: process ()- يستخدم
\Magento\Framework\Reflection\MethodsMap::getMethodParams()
، حيث يتم سحب معلمات الطريقة من خلال الانعكاس
\ Magento \ Framework \ Webapi \ ServiceInputProcessor :: convertValue () - العديد من الخيارات لتحويل صفيف إلى DataObject أو إلى صفيف من DataObject
\ Magento \ Framework \ Webapi \ ServiceInputProcessor :: _ createFromArray () - التحويل المباشر ، حيث يتم التحقق من وجود انعكاس وجود
الرسائل والمستوطنين ( تذكر ، قلت أعلاه أننا سنعود إليهم؟) وأن لديهم نطاقًا عامًا. بعد ذلك ، يمتلئ الكائن بالبيانات من خلال المستوطنين.
في النهاية ، في الطريقة
\ Magento \ Webapi \ Controller \ Rest :: processApiRequest () ، من خلال
call_user_func_array
أسلوب كائن المستودع.
الخاتمة
مستودع وحدة جيثبهناك طريقتان للتثبيت:
1) عبر الملحن. للقيام بذلك ، قم باضافة العنصر التالي الى مصفوفة
repositories
في ملف composer.json
{ "type": "git", "url": "https://github.com/alexpoletaev/magento2-blog-demo" }
ثم اكتب الأمر التالي في النهاية الطرفية:
composer require alexpoletaev/magento2-blog-demo:dev-master
2) قم بتنزيل ملفات الوحدة النمطية ونسخها يدويًا إلى دليل
app/code/AlexPoletaev/Blog
بغض النظر عن الطريقة التي تختارها ، في النهاية تحتاج إلى تشغيل الترقية:
php bin/magento setup:upgrade
آمل أن تكون هذه المقالة مفيدة لشخص ما. إذا كان لديك أي تعليقات أو اقتراحات أو أسئلة ، فمرحبًا بالتعليق. شكرا لكم على اهتمامكم.