Je veux ajouter une action de condition dans le formulaire d'administration du module personnalisé. Comment puis-je atteindre cet objectif?
Lien de référence pour Magento 1.9
Remplacement du lien ci-dessus pour Magento 2.
Je veux ajouter une action de condition dans le formulaire d'administration du module personnalisé. Comment puis-je atteindre cet objectif?
Lien de référence pour Magento 1.9
Remplacement du lien ci-dessus pour Magento 2.
Réponses:
Pour ajouter un champ conditionnel au modèle par défaut (et l'utiliser davantage à des fins de validation), vous devrez créer un nouveau modèle (ou modifier le modèle existant) qui contient ces champs.
app / code / Fournisseur / Règles / Configuration / 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();
}
}
Maintenant, nous avons un tableau avec la description du modèle et nous devons compléter le modèle lui-même et y inclure le modèle de ressource et la collection appropriés.
Le modèle sera appelé «Règle»:
application / code / fournisseur / règles / modèle / 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;
}
}
Comme vous pouvez le voir, notre modèle hérite du Magento\Rule\Model\AbstractModel
modèle qui possède déjà toutes les méthodes requises.
Dans le constructeur, nous ajouterons des usines de conditions qui nous permettront de travailler avec elles et de créer plusieurs méthodes. Cela devrait nous permettre de comprendre le fonctionnement du modèle.
Notez que nous utilisons les modèles de condition par défaut du \Magento\SalesRule\Model\Rule\Condition
module Magento SalesRule ( ). Si vous devez étendre les conditions, vous pouvez ajouter vos propres classes et / ou les réécrire complètement ou hériter des classes disponibles de base. Dans peut être utile lorsque vous souhaitez ajouter une condition spéciale qui n'est pas incluse dans les conditions par défaut. Par exemple, sous - total avec remise .
....
Ensuite, passons à l'interface dans le panneau d'administration. Nous avons besoin du contrôleur avec un ensemble d'actions (telles que Enregistrer, Ajouter, Modifier, Affichage de la grille, Recharger les conditions) et une mise en page avec des blocs.
Commençons par le contrôleur lui-même. Tout d'abord, déclarez le contrôleur commun:
app / code / Vendeur / Règles / Contrôleur / Adminhtml / Exemple / 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');
}
}
Ici, nous devons appeler l'usine de nos modèles dans le constructeur. Cela est fait pour les rendre disponibles (et certaines classes auxiliaires, comme un registre et un enregistreur).
La _initRule
méthode est responsable de l'initialisation de la règle actuelle ou de la création d'une nouvelle et vide avec la possibilité de l'ajouter au registre. La _initAction()
méthode charge une mise en page et rend le menu des modules disponible pour les actions (également, il ajoute des chapelures). La _isAllowed()
méthode vérifie si l'administrateur actuel a un accès au contrôleur.
À l'étape suivante, nous allons ajouter les actions par défaut:
....
Montage:
app / code / Vendeur / Règles / Contrôleur / Adminhtml / Exemple / Règle / 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();
}
}
Voici comment ajouter de nouvelles conditions:
app / code / Vendeur / Règles / Contrôleur / Adminhtml / Exemple / Règle / 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);
}
}
Cette classe est responsable du chargement des conditions qui ont été choisies dans l'interface (toutes les conditions ne peuvent pas être chargées en même temps).
....
Ensuite, nous devons créer tous les blocs et la mise en page requis.
Maintenant, passons à la création et à la modification de nouvelles règles. Créons le bloc conteneur principal pour l'édition:
app / code / Vendeur / 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');
}
}
}
Une fois terminé, nous devrions ajouter le titre des contrôleurs et les boutons save
et edit current model
dans le constructeur. Ici aussi, vous devez ajouter le texte principal du bloc.
C'est un formulaire lui-même:
app / code / Vendeur / Règles / Bloquer / Adminhtml / Exemple / Règle / Modifier / 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();
}
}
et onglets:
application / code / Fournisseur / Règles / Bloquer / Adminhtml / Exemple / Règle / Modifier / 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'));
}
}
Nous aurons les deux onglets: Informations et conditions du modèle général.
application / code / Fournisseur / Règles / Bloquer / Adminhtml / Exemple / Règle / Modifier / 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();
}
}
Conditions:
app / code / Fournisseur / Règles / Bloquer / Adminhtml / Exemple / Règle / Modifier / 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();
}
}
Pour voir plus de détails, veuillez suivre ce lien .
Utilisation du composant d'interface utilisateur pour Magento2.1
<fieldset name = "conditions"> <nom d'argument = "données" xsi: type = "tableau"> <item name = "config" xsi: type = "array"> <item name = "label" xsi: type = "string" translate = "true"> Conditions </item> <item name = "pliable" xsi: type = "boolean"> true </item> <item name = "sortOrder" xsi: type = "number"> 20 </item> </item> </argument> <nom du conteneur = "conditions_apply_to"> <nom d'argument = "données" xsi: type = "tableau"> <item name = "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>