Quero adicionar ação de condição no formulário de administração do módulo personalizado. Como posso conseguir isso?
Consulte o link para Magento 1.9
Substituição do link acima para Magento 2.
Quero adicionar ação de condição no formulário de administração do módulo personalizado. Como posso conseguir isso?
Consulte o link para Magento 1.9
Substituição do link acima para Magento 2.
Respostas:
Para adicionar um campo condicional ao modelo padrão (e utilizá-lo ainda mais para fins de validação), você precisará criar um novo modelo (ou modificar o existente) que contém esses campos.
app / code / Vendor / Rules / 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();
}
}
Agora, temos uma tabela com a descrição do modelo e precisamos concluir o próprio modelo e incluir nele o modelo e a coleção de recursos apropriados.
O modelo será chamado de 'Regra':
app / code / Vendor / Rules / Model / 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;
}
}
Como você pode ver, nosso modelo é herdado do Magento\Rule\Model\AbstractModel
modelo que já possui todos os métodos necessários.
No Construtor, adicionaremos fábricas de condições que nos permitem trabalhar com eles e criar vários métodos. Isso deve nos dar a compreensão de como o modelo funciona.
Observe que estamos usando os modelos de condição padrão do \Magento\SalesRule\Model\Rule\Condition
módulo Magento SalesRule ( ). Se você precisar expandir as condições, poderá adicionar suas próprias classes e / ou reescrevê-las completamente ou herdar das classes disponíveis básicas. In pode ser útil quando você deseja adicionar uma condição especial que não está incluída nas condições padrão. Por exemplo, subtotal com desconto .
....
Em seguida, vamos mudar para a interface no painel de administração. Precisamos do Controller com um conjunto de ações (como Salvar, Adicionar, Editar, Exibição em grade, Recarregar condições) e um layout com blocos.
Vamos começar com o próprio controlador. Primeiro, declare o controlador comum:
app / code / Vendor / Rules / Controller / Adminhtml / Example / 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');
}
}
Aqui, precisamos chamar a fábrica de nossos modelos no Constructor. Isso é feito para disponibilizá-las publicamente (e algumas classes auxiliares, como um registro e um criador de logs).
O _initRule
método é responsável pela inicialização da regra atual ou pela criação de uma nova e vazia, com a capacidade de adicioná-la ao registro. O _initAction()
método carrega um layout e disponibiliza o menu dos módulos para ações (além de adicionar trilhas). O _isAllowed()
método verifica se o administrador atual tem acesso ao Controlador.
Na próxima etapa, adicionaremos as ações padrão:
....
Edição:
app / code / Vendor / Rules / Controller / Adminhtml / Example / 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();
}
}
Eis como adicionar novas condições:
app / code / Vendor / Rules / Controller / Adminhtml / Example / 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);
}
}
Essa classe é responsável por carregar as condições que foram escolhidas na interface (todas as condições não podem ser carregadas de uma só vez).
....
Em seguida, precisamos criar todos os blocos e layout necessários.
Agora, vamos começar a criar e editar novas regras. Vamos criar o bloco de contêiner principal para edição:
app / code / Vendor / Rules / Block / Adminhtml / Example / 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');
}
}
}
Quando terminar, devemos adicionar o título dos controladores e os botões save
e edit current model
no Construtor. Além disso, aqui você deve adicionar o texto principal do bloco.
Este é um formulário em si:
app / code / Vendor / Rules / Block / Adminhtml / Example / Rule / Edit / 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();
}
}
e guias:
app / code / Vendor / Rules / Block / Adminhtml / Example / Rule / Edit / 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'));
}
}
Teremos as duas guias: informações e condições do modelo Ceneral.
app / code / Vendor / Rules / Block / Adminhtml / Example / 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();
}
}
Condições:
app / code / Vendor / Rules / Block / Adminhtml / Example / 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();
}
}
Para ver mais detalhes, siga este link .
Usando o componente UI para Magento2.1
<nome do conjunto de campos = "condições"> <nome do argumento = "data" xsi: type = "array"> <nome do item = "config" xsi: type = "array"> <item name = "label" xsi: type = "string" translate = "true"> Condições </item> <item name = "recolhível" xsi: type = "boolean"> true </item> <item name = "sortOrder" xsi: type = "number"> 20 </item> </item> </argument> <nome do contêiner = "conditions_apply_to"> <nome do argumento = "data" xsi: type = "array"> <nome do item = "config" xsi: type = "array"> <item name = "sortOrder" xsi: type = "number"> 10 </item> </item> </argument> <htmlContent name = "html_content"> <argument name = "block" xsi: type = "object"> Magento \ SalesRule \ Block \ Adminhtml \ Promo \ Quote \ Edit \ Tab \ Conditions </argument> </htmlContent> </container> </fieldset>