Я хочу добавить условие действия в пользовательской форме администратора модуля. Как мне этого добиться?
Замена вышеуказанной ссылки на Magento 2.
Я хочу добавить условие действия в пользовательской форме администратора модуля. Как мне этого добиться?
Замена вышеуказанной ссылки на Magento 2.
Ответы:
Чтобы добавить условное поле в модель по умолчанию (и в дальнейшем использовать его для проверки), вам нужно будет создать новую модель (или изменить существующую), содержащую эти поля.
Приложение / код / Vendor / Правила / Setup / InstallSchema.php
<?php
namespace Vendor\Rules\Setup;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class InstallSchema implements InstallSchemaInterface
{
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
$table = $installer->getConnection()->newTable(
$installer->getTable('vendor_rules')
)->addColumn(
'rule_id',
Table::TYPE_INTEGER,
null,
['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
'Rule Id'
)->addColumn(
'name',
Table::TYPE_TEXT,
255,
[],
'Name'
)->addColumn(
'description',
Table::TYPE_TEXT,
'64k',
[],
'Description'
)->addColumn(
'from_date',
Table::TYPE_DATE,
null,
['nullable' => true, 'default' => null],
'From'
)->addColumn(
'to_date',
Table::TYPE_DATE,
null,
['nullable' => true, 'default' => null],
'To'
)->addColumn(
'is_active',
Table::TYPE_SMALLINT,
null,
['nullable' => false, 'default' => '0'],
'Is Active'
)->addColumn(
'conditions_serialized',
Table::TYPE_TEXT,
'2M',
[],
'Conditions Serialized'
)->addColumn(
'sort_order',
Table::TYPE_INTEGER,
null,
['unsigned' => true, 'nullable' => false, 'default' => '0'],
'Sort Order (Priority)'
)->addIndex(
$installer->getIdxName('vendor_rules', ['sort_order', 'is_active', 'to_date', 'from_date']),
['sort_order', 'is_active', 'to_date', 'from_date']
)->setComment(
'Own Rules'
);
$installer->getConnection()->createTable($table);
$installer->endSetup();
}
}
Теперь у нас есть таблица с описанием модели, и нам нужно завершить саму модель и включить в нее соответствующую модель ресурсов и коллекцию.
Модель будет называться «Правило»:
Приложение / код / Vendor / Правила / Модель / Rule.php
<?php
namespace Vendor\Rules\Model;
use Magento\Quote\Model\Quote\Address;
use Magento\Rule\Model\AbstractModel;
/**
* Class Rule
* @package Vendor\Rules\Model
*
* @method int|null getRuleId()
* @method Rule setRuleId(int $id)
*/
class Rule extends AbstractModel
{
/**
* Prefix of model events names
*
* @var string
*/
protected $_eventPrefix = 'vendor_rules';
/**
* Parameter name in event
*
* In observe method you can use $observer->getEvent()->getRule() in this case
*
* @var string
*/
protected $_eventObject = 'rule';
/** @var \Magento\SalesRule\Model\Rule\Condition\CombineFactory */
protected $condCombineFactory;
/** @var \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory */
protected $condProdCombineF;
/**
* Store already validated addresses and validation results
*
* @var array
*/
protected $validatedAddresses = [];
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
* @param \Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory
* @param \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory,
\Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
) {
$this->condCombineFactory = $condCombineFactory;
$this->condProdCombineF = $condProdCombineF;
parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
}
/**
* Set resource model and Id field name
*
* @return void
*/
protected function _construct()
{
parent::_construct();
$this->_init('Vendor\Rules\Model\ResourceModel\Rule');
$this->setIdFieldName('rule_id');
}
/**
* Get rule condition combine model instance
*
* @return \Magento\SalesRule\Model\Rule\Condition\Combine
*/
public function getConditionsInstance()
{
return $this->condCombineFactory->create();
}
/**
* Get rule condition product combine model instance
*
* @return \Magento\SalesRule\Model\Rule\Condition\Product\Combine
*/
public function getActionsInstance()
{
return $this->condProdCombineF->create();
}
/**
* Check cached validation result for specific address
*
* @param Address $address
* @return bool
*/
public function hasIsValidForAddress($address)
{
$addressId = $this->_getAddressId($address);
return isset($this->validatedAddresses[$addressId]) ? true : false;
}
/**
* Set validation result for specific address to results cache
*
* @param Address $address
* @param bool $validationResult
* @return $this
*/
public function setIsValidForAddress($address, $validationResult)
{
$addressId = $this->_getAddressId($address);
$this->validatedAddresses[$addressId] = $validationResult;
return $this;
}
/**
* Get cached validation result for specific address
*
* @param Address $address
* @return bool
* @SuppressWarnings(PHPMD.BooleanGetMethodName)
*/
public function getIsValidForAddress($address)
{
$addressId = $this->_getAddressId($address);
return isset($this->validatedAddresses[$addressId]) ? $this->validatedAddresses[$addressId] : false;
}
/**
* Return id for address
*
* @param Address $address
* @return string
*/
private function _getAddressId($address)
{
if ($address instanceof Address) {
return $address->getId();
}
return $address;
}
}
Как видите, наша модель наследует от Magento\Rule\Model\AbstractModel
модели, в которой уже есть все необходимые методы.
Прямо в Конструкторе мы добавим фабрики условий, которые позволяют нам работать с ними и создавать несколько методов. Это должно дать нам понимание того, как работает модель.
Обратите внимание, что мы используем модели условий по умолчанию из \Magento\SalesRule\Model\Rule\Condition
модуля Magento SalesRule ( ). Если вам нужно расширить условия, вы можете добавить свои собственные предложения и / или полностью переписать их или наследовать от базовых доступных классов. Может быть полезно, если вы хотите добавить специальное условие, которое не включено в условия по умолчанию. Например, Итого со скидкой .
....
Далее давайте переключимся на интерфейс в админ-панели. Нам нужен контроллер с набором действий (например, Сохранить, Добавить, Изменить, Отображение сетки, Перезагрузка условий) и макет с блоками.
Давайте начнем с самого контроллера. Сначала объявите общий контроллер:
Приложение / код / Продавец / Правила / Controller / Adminhtml / Пример / Rule.php
<?php
namespace Vendor\Rules\Controller\Adminhtml\Example;
abstract class Rule extends \Magento\Backend\App\Action
{
/**
* Core registry
*
* @var \Magento\Framework\Registry
*/
protected $coreRegistry = null;
/**
* @var \Magento\Framework\App\Response\Http\FileFactory
*/
protected $fileFactory;
/**
* @var \Magento\Framework\Stdlib\DateTime\Filter\Date
*/
protected $dateFilter;
/**
* @var \Vendor\Rules\Model\RuleFactory
*/
protected $ruleFactory;
/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* @param \Magento\Backend\App\Action\Context $context
* @param \Magento\Framework\Registry $coreRegistry
* @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
* @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
* @param \Vendor\Rules\Model\RuleFactory $ruleFactory
* @param \Psr\Log\LoggerInterface $logger
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Registry $coreRegistry,
\Magento\Framework\App\Response\Http\FileFactory $fileFactory,
\Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
\Vendor\Rules\Model\RuleFactory $ruleFactory,
\Psr\Log\LoggerInterface $logger
) {
parent::__construct($context);
$this->coreRegistry = $coreRegistry;
$this->fileFactory = $fileFactory;
$this->dateFilter = $dateFilter;
$this->ruleFactory = $ruleFactory;
$this->logger = $logger;
}
/**
* Initiate rule
*
* @return void
*/
protected function _initRule()
{
$rule = $this->ruleFactory->create();
$this->coreRegistry->register(
'current_rule',
$rule
);
$id = (int)$this->getRequest()->getParam('id');
if (!$id && $this->getRequest()->getParam('rule_id')) {
$id = (int)$this->getRequest()->getParam('rule_id');
}
if ($id) {
$this->coreRegistry->registry('current_rule')->load($id);
}
}
/**
* Initiate action
*
* @return Rule
*/
protected function _initAction()
{
$this->_view->loadLayout();
$this->_setActiveMenu('Vendor_Rules::vendor_rules')
->_addBreadcrumb(__('Example Rules'), __('Example Rules'));
return $this;
}
/**
* Returns result of current user permission check on resource and privilege
*
* @return bool
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Vendor_Rules::rules');
}
}
Здесь нам нужно вызвать фабрику наших моделей в Конструкторе. Это сделано для того, чтобы сделать их (и некоторые вспомогательные классы, такие как регистр и регистратор) общедоступными.
_initRule
Метод отвечает за текущую инициализацию правил или создание нового и пустого , с возможностью добавления его в реестр. _initAction()
Метод загружает раскладку и делает меню модулей для действий (кроме того , он добавляет breadcumbs). В _isAllowed()
метод проверяет , является ли текущий администратор имеет доступ к контроллеру.
На следующем шаге мы собираемся добавить действия по умолчанию:
....
Редактирование:
Приложение / код / Продавец / Правила / Controller / Adminhtml / Пример / Rule / edit.php
<?php
namespace Vendor\Rules\Controller\Adminhtml\Example\Rule;
class Edit extends \Vendor\Rules\Controller\Adminhtml\Example\Rule
{
/**
* Rule edit action
*
* @return void
*/
public function execute()
{
$id = $this->getRequest()->getParam('id');
/** @var \Vendor\Rules\Model\Rule $model */
$model = $this->ruleFactory->create();
if ($id) {
$model->load($id);
if (!$model->getRuleId()) {
$this->messageManager->addErrorMessage(__('This rule no longer exists.'));
$this->_redirect('vendor_rules/*');
return;
}
}
// set entered data if was error when we do save
$data = $this->_session->getPageData(true);
if (!empty($data)) {
$model->addData($data);
}
$model->getConditions()->setJsFormObject('rule_conditions_fieldset');
$this->coreRegistry->register('current_rule', $model);
$this->_initAction();
$this->_view->getLayout()
->getBlock('example_rule_edit')
->setData('action', $this->getUrl('vendor_rules/*/save'));
$this->_addBreadcrumb($id ? __('Edit Rule') : __('New Rule'), $id ? __('Edit Rule') : __('New Rule'));
$this->_view->getPage()->getConfig()->getTitle()->prepend(
$model->getRuleId() ? $model->getName() : __('New Rule')
);
$this->_view->renderLayout();
}
}
Вот как добавить новые условия:
Приложение / код / Продавец / Правила / Controller / Adminhtml / Пример / Rule / NewConditionHtml.php
<?php
namespace Vendor\Rules\Controller\Adminhtml\Example\Rule;
class NewConditionHtml extends \Vendor\Rules\Controller\Adminhtml\Example\Rule
{
/**
* New condition html action
*
* @return void
*/
public function execute()
{
$id = $this->getRequest()->getParam('id');
$typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
$type = $typeArr[0];
$model = $this->_objectManager->create(
$type
)->setId(
$id
)->setType(
$type
)->setRule(
$this->ruleFactory->create()
)->setPrefix(
'conditions'
);
if (!empty($typeArr[1])) {
$model->setAttribute($typeArr[1]);
}
if ($model instanceof \Magento\Rule\Model\Condition\AbstractCondition) {
$model->setJsFormObject($this->getRequest()->getParam('form'));
$html = $model->asHtmlRecursive();
} else {
$html = '';
}
$this->getResponse()->setBody($html);
}
}
Этот класс отвечает за загрузку условий, которые были выбраны в интерфейсе (все условия не могут быть загружены одновременно).
....
Далее нам нужно создать все необходимые блоки и макет.
Теперь давайте приступим к созданию и редактированию новых правил. Давайте создадим основной контейнерный блок для редактирования:
Приложение / код / Продавец / Правила / Block / Adminhtml / Пример / Rule / edit.php
<?php
namespace Vendor\Rules\Block\Adminhtml\Example\Rule;
class Edit extends \Magento\Backend\Block\Widget\Form\Container
{
/**
* Core registry
*
* @var \Magento\Framework\Registry
*/
protected $coreRegistry = null;
/**
* @param \Magento\Backend\Block\Widget\Context $context
* @param \Magento\Framework\Registry $registry
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Widget\Context $context,
\Magento\Framework\Registry $registry,
array $data = []
) {
$this->coreRegistry = $registry;
parent::__construct($context, $data);
}
/**
* Initialize form
* Add standard buttons
* Add "Save and Continue" button
*
* @return void
*/
protected function _construct()
{
$this->_objectId = 'id';
$this->_controller = 'adminhtml_example_rule';
$this->_blockGroup = 'Vendor_Rules';
parent::_construct();
$this->buttonList->add(
'save_and_continue_edit',
[
'class' => 'save',
'label' => __('Save and Continue Edit'),
'data_attribute' => [
'mage-init' => ['button' => ['event' => 'saveAndContinueEdit', 'target' => '#edit_form']],
]
],
10
);
}
/**
* Getter for form header text
*
* @return \Magento\Framework\Phrase
*/
public function getHeaderText()
{
$rule = $this->coreRegistry->registry('current_rule');
if ($rule->getRuleId()) {
return __("Edit Rule '%1'", $this->escapeHtml($rule->getName()));
} else {
return __('New Rule');
}
}
}
Когда это сделано, мы должны добавить название контроллеров и save
и edit current model
кнопки в конструкторе. Также здесь вы должны добавить основной текст блока.
Это сама форма:
Приложение / код / Продавец / Правила / Block / Adminhtml / Пример / Rule / Редактировать / form.php
<?php
namespace Vendor\Rules\Block\Adminhtml\Example\Rule\Edit;
class Form extends \Magento\Backend\Block\Widget\Form\Generic
{
/**
* Constructor
*
* @return void
*/
protected function _construct()
{
parent::_construct();
$this->setId('example_rule_form');
$this->setTitle(__('Rule Information'));
}
/**
* Prepare form before rendering HTML
*
* @return \Magento\Backend\Block\Widget\Form\Generic
*/
protected function _prepareForm()
{
/** @var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create(
[
'data' => [
'id' => 'edit_form',
'action' => $this->getUrl('vendor_rules/example_rule/save'),
'method' => 'post',
],
]
);
$form->setUseContainer(true);
$this->setForm($form);
return parent::_prepareForm();
}
}
и вкладки:
Приложение / код / Продавец / Правила / Block / Adminhtml / Пример / Rule / Редактировать / Tabs.php
<?php
namespace Vendor\Rules\Block\Adminhtml\Example\Rule\Edit;
class Tabs extends \Magento\Backend\Block\Widget\Tabs
{
/**
* Constructor
*
* @return void
*/
protected function _construct()
{
parent::_construct();
$this->setId('rules_edit_tabs');
$this->setDestElementId('edit_form');
$this->setTitle(__('Rules'));
}
}
У нас будут две вкладки: Общая информация о модели и Условия.
Приложение / код / Продавец / Правила / Block / Adminhtml / Пример / Rule / Edit / Tab / main.php
<?php
namespace Vendor\Rules\Block\Adminhtml\Example\Rule\Edit\Tab;
use Magento\Backend\Block\Template\Context;
use Magento\Backend\Block\Widget\Form\Generic;
use Magento\Backend\Block\Widget\Tab\TabInterface;
use Magento\Framework\Data\FormFactory;
use Magento\Framework\Registry;
class Main extends Generic implements TabInterface
{
/**
* Constructor
*
* @param Context $context
* @param Registry $registry
* @param FormFactory $formFactory
* @param array $data
*/
public function __construct(
Context $context,
Registry $registry,
FormFactory $formFactory,
array $data = []
) {
parent::__construct($context, $registry, $formFactory, $data);
}
/**
* {@inheritdoc}
*/
public function getTabLabel()
{
return __('Rule Information');
}
/**
* {@inheritdoc}
*/
public function getTabTitle()
{
return __('Rule Information');
}
/**
* {@inheritdoc}
*/
public function canShowTab()
{
return true;
}
/**
* {@inheritdoc}
*/
public function isHidden()
{
return false;
}
/**
* Prepare form before rendering HTML
*
* @return Generic
*/
protected function _prepareForm()
{
$model = $this->_coreRegistry->registry('current_rule');
/** @var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create();
$form->setHtmlIdPrefix('rule_');
$fieldset = $form->addFieldset('base_fieldset', ['legend' => __('General Information')]);
if ($model->getId()) {
$fieldset->addField('rule_id', 'hidden', ['name' => 'rule_id']);
}
$fieldset->addField(
'name',
'text',
['name' => 'name', 'label' => __('Rule Name'), 'title' => __('Rule Name'), 'required' => true]
);
$fieldset->addField(
'description',
'textarea',
[
'name' => 'description',
'label' => __('Description'),
'title' => __('Description'),
'style' => 'height: 100px;'
]
);
$fieldset->addField(
'is_active',
'select',
[
'label' => __('Status'),
'title' => __('Status'),
'name' => 'is_active',
'required' => true,
'options' => ['1' => __('Active'), '0' => __('Inactive')]
]
);
if (!$model->getId()) {
$model->setData('is_active', '1');
}
$fieldset->addField('sort_order', 'text', ['name' => 'sort_order', 'label' => __('Priority')]);
$dateFormat = $this->_localeDate->getDateFormat(\IntlDateFormatter::SHORT);
$fieldset->addField(
'from_date',
'date',
[
'name' => 'from_date',
'label' => __('From'),
'title' => __('From'),
'input_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT,
'date_format' => $dateFormat
]
);
$fieldset->addField(
'to_date',
'date',
[
'name' => 'to_date',
'label' => __('To'),
'title' => __('To'),
'input_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT,
'date_format' => $dateFormat
]
);
$form->setValues($model->getData());
if ($model->isReadonly()) {
foreach ($fieldset->getElements() as $element) {
$element->setReadonly(true, true);
}
}
$this->setForm($form);
$this->_eventManager->dispatch('adminhtml_example_rule_edit_tab_main_prepare_form', ['form' => $form]);
return parent::_prepareForm();
}
}
условия:
Приложение / код / Продавец / Правила / Block / Adminhtml / Пример / Rule / Edit / Tab / Conditions.php
<?php
namespace Vendor\Rules\Block\Adminhtml\Example\Rule\Edit\Tab;
use Magento\Backend\Block\Widget\Form\Generic;
use Magento\Backend\Block\Widget\Tab\TabInterface;
class Conditions extends Generic implements TabInterface
{
/**
* Core registry
*
* @var \Magento\Backend\Block\Widget\Form\Renderer\Fieldset
*/
protected $rendererFieldset;
/**
* @var \Magento\Rule\Block\Conditions
*/
protected $conditions;
/**
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Rule\Block\Conditions $conditions
* @param \Magento\Backend\Block\Widget\Form\Renderer\Fieldset $rendererFieldset
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Rule\Block\Conditions $conditions,
\Magento\Backend\Block\Widget\Form\Renderer\Fieldset $rendererFieldset,
array $data = []
) {
$this->rendererFieldset = $rendererFieldset;
$this->conditions = $conditions;
parent::__construct($context, $registry, $formFactory, $data);
}
/**
* {@inheritdoc}
*/
public function getTabLabel()
{
return __('Conditions');
}
/**
* {@inheritdoc}
*/
public function getTabTitle()
{
return __('Conditions');
}
/**
* {@inheritdoc}
*/
public function canShowTab()
{
return true;
}
/**
* {@inheritdoc}
*/
public function isHidden()
{
return false;
}
/**
* Prepare form before rendering HTML
*
* @return Generic
*/
protected function _prepareForm()
{
$model = $this->_coreRegistry->registry('current_rule');
/** @var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create();
$form->setHtmlIdPrefix('rule_');
$renderer = $this->rendererFieldset->setTemplate(
'Magento_CatalogRule::promo/fieldset.phtml'
)->setNewChildUrl(
$this->getUrl('vendor_rules/example_rule/newConditionHtml/form/rule_conditions_fieldset')
);
$fieldset = $form->addFieldset(
'conditions_fieldset',
[
'legend' => __(
'Apply the rule only if the following conditions are met (leave blank for all products).'
)
]
)->setRenderer(
$renderer
);
$fieldset->addField(
'conditions',
'text',
['name' => 'conditions', 'label' => __('Conditions'), 'title' => __('Conditions')]
)->setRule(
$model
)->setRenderer(
$this->conditions
);
$form->setValues($model->getData());
$this->setForm($form);
return parent::_prepareForm();
}
}
Для просмотра более подробной информации, пожалуйста, перейдите по этой ссылке .
Использование компонента пользовательского интерфейса для Magento2.1
<fieldset name = "условия"> <аргумент name = "data" xsi: type = "array"> <item name = "config" xsi: type = "array"> <item name = "label" xsi: type = "string" translate = "true"> Условия </ item> <item name = "collapsible" xsi: type = "boolean"> true </ item> <item name = "sortOrder" xsi: type = "number"> 20 </ item> </ Элемент> </ Аргумент> <container name = "condition_apply_to"> <аргумент name = "data" xsi: type = "array"> <item name = "config" xsi: type = "array"> <item name = "sortOrder" xsi: type = "number"> 10 </ item> </ Элемент> </ Аргумент> <htmlContent name = "html_content"> <аргумент name = "блок" xsi: type = "object"> Magento \ SalesRule \ Block \ Adminhtml \ Promo \ Quote \ Edit \ Tab \ Condition </ аргумент> </ HtmlContent> </ Контейнер> </ FIELDSET>