Magento 2 - Як додати капчу до власної форми


28

Я розробляю спеціальний модуль, який містить подання форми. Я хотів би додати до нього капчу. І ми хочемо використовувати бібліотеку Captcha за замовчуванням Magento, щоб вона відповідала тій, що є в реєстраційній формі.

Відповіді:


35

Вам потрібно виконати деякий крок для використання капсули magento в спеціальному модулі.

Крок 1 : Vendor/Module/etc/config.xml

<? xml version = "1.0"?>
<config xmlns: xsi = "http://www.w3.org/2001/XMLSchema-in substance" xsi: noNamespaceSchemaLocation = "урна: magento: module: Magento_Store: etc / config.xsd">
    <за замовчуванням>
        <клієнт>
            <captcha>
                <shown_to_logged_in_user>
                    <custom_form> 1 </custom_form>
                </shown_to_logged_in_user>
                <завжди_для>
                    <custom_form> 1 </custom_form>
                </always_for>
            </captcha>
        </customer>
        <captcha translate = "label">
            <напередодні>
                <області>
                    <custom_form>
                        <label> Спеціальна форма </label>
                    </custom_form>
                </areas>
            </frontend>
        </captcha>
    </default>
</config>

Крок 2: Перейдіть на " Адміністратор -> Магазини -> Конфігурація -> Клієнт -> Конфігурація клієнта -> Captcha " та налаштуйте. Ви можете бачити значення нових форм "Спеціальна форма"

Крок 3: Створіть Vendor/Module/view/frontend/layout/yourroutid_index_index.xml

<? xml version = "1.0"?>
<page xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" layout = "1column" xsi: noNamespaceSchemaLocation = "urn: magento: Framework: View / Layout / etc / page_configuration.xsd">
    <head>
        <title> Спеціальна форма </title>
    </head>
    <ніхто>
        <referenceContainer name = "content">
            <block class = "Постачальник \ Модуль \ Блок \ CaptchaForm" name = "contactForm" template = "Vendor_Module :: captchaform.phtml">
                <ім'я контейнера = "form.additional.info" label = "Форма додаткової інформації">
                    <block class = "Magento \ Captcha \ Block \ Captcha" name = "captcha" after = "-" cacheable = "false">
                        <метод дії = "setFormId">
                            <argument name = "formId" xsi: type = "string"> custom_form </argument>
                        </action>
                        <метод дії = "setImgWidth">
                            <argument name = "width" xsi: type = "string"> 230 </argument>
                        </action>
                        <метод дії = "setImgHeight">
                            <argument name = "width" xsi: type = "string"> 50 </argument>
                        </action>
                    </block>
                </container>
            </block>
        </referenceContainer>
        <referenceBlock name = "head.components">
            <block class = "Magento \ Framework \ View \ Element \ Js \ Components" name = "captcha_page_head_components" template = "Magento_Captcha :: js / components.phtml" />
        </referenceBlock>
    </body>
</page>

Крок 4: Vendor/Module/Block/CaptchaForm.php

простір імен постачальник \ модуль \ блок;


клас CaptchaForm розширюється \ Magento \ Framework \ Вид \ Елемент \ Шаблон
{
    публічна функція getFormAction ()
    {
        повернути $ this-> getUrl ('yourroute / index / post', ['_secure' => вірно]);
    }
}

Крок 5: Vendor/Moduel/view/frontend/templates/captchaform.phtml

<form class = "контакт з формою"
      action = "<? php / * @escapeNotVerified * / echo $ block-> getFormAction ();?>"
      id = "контактна форма"
      method = "повідомлення"
      data-hasrequired = "<? php / * @escapeNotVerified * / echo __ ('* Обов'язкові поля')?>"
      data-mage-init = '{"валідація": {}}'>
    <fieldset class = "fieldset">
        <legend class = "legend"> <span> <? php / * @escapeNotVerified * / echo __ ("Напишіть нам")?> </span> </legend> <br />

        <div class = "потрібна назва поля">
            <label class = "label" for = "name"> <span> <? php / * @escapeNotVerified * / echo __ ('Ім'я')?> </span> </label>
            <div class = "control">
                <input name = "name" id = "name" title = "<? php / * @escapeNotVerified * / echo __ ('Ім'я')?>" value = "" class = "input-text" type = "text" data-validate = "{обов'язково: правда}" />
            </div>
        </div>
        <div class = "поле електронної пошти потрібно">
            <label class = "label" for = "email"> <span> <? php / * @escapeNotVerified * / echo __ ('Електронна пошта')?> </span> </label>
            <div class = "control">
                <input name = "email" id = "email" title = "<? php / * @escapeNotVerified * / echo __ ('Електронна пошта')?>" value = "" class = "input-text" type = "email" data-validate = "{обов'язково: вірно," перевірити електронну пошту ": істина}" />
            </div>
        </div>
        <? php echo $ block-> getChildHtml ('form.additional.info'); ?>
    </fieldset>
    <div class = "панель інструментів дій">
        <div class = "основний">
            <input type = "hidden" name = "hidit" id = "hidit" value = "" />
            <button type = "submit" title = "<? php / * @escapeNotVerified * / echo __ (" Надіслати ")?>" class = "дія надіслати первинну">
                <span> <? php / * @escapeNotVerified * / echo __ ('Надіслати')?> </span>
            </button>
        </div>
    </div>
</form>

Тепер ви можете побачити капчу у вашій формі. Тепер потрібно перевірити свою капчу за допомогою спостерігача. Тому я використовую поштовий контролер передпосилальної події для перевірки.

Крок 6: Vendor/Module/etc/frontend/events.xml

<? xml version = "1.0"?>
<config xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: noNamespaceSchemaLocation = "урна: magento: Framework: подія / тощо / події.xsd">
    <ім'я події = "контролер Managed_predispatch_yourroute_index_post">
        <observer name = "captcha_custom_form" instance = "Постачальник \ Модуль \ Оглядач \ CheckCustomFormObserver" />
    </event>
</config>

Крок 7: Vendor/Module/Observer/CheckCustomFormObserver.php

простір імен постачальник \ модуль \ спостерігач;

використовувати Magento \ Framework \ Event \ ObserverInterface;
використовувати Magento \ Framework \ App \ Запит \ DataPersistorInterface;
використовувати Magento \ Framework \ App \ ObjectManager;
використовувати Magento \ Captcha \ Observer \ CaptchaStringResolver;

клас CheckCustomFormObserver реалізує ObserverInterface
{
    / **
     * @var \ Magento \ Captcha \ Helper \ Data
     * /
    захищений $ _helper;

    / **
     * @var \ Magento \ Framework \ App \ ActionFlag
     * /
    захищений $ _actionFlag;

    / **
     * @var \ Magento \ Framework \ Message \ ManagerInterface
     * /
    захищений $ messageManager;

    / **
     * @var \ Magento \ Framework \ App \ Response \ RedirectInterface
     * /
    захищений $ переадресація;

    / **
     * @var CaptchaStringResolver
     * /
    захищений $ captchaStringResolver;

    / **
     * @var DataPersistorInterface
     * /
    приватний $ dataPersistor;

    / **
     * @param \ Magento \ Captcha \ Helper \ Data $ helper
     * @param \ Magento \ Framework \ App \ ActionFlag $ actionFlag
     * @param \ Magento \ Framework \ Message \ ManagerInterface $ messageManager
     * @param \ Magento \ Framework \ App \ Response \ RedirectInterface $ redirect
     * @param CaptchaStringResolver $ captchaStringResolver
     * /
    публічна функція __construct (
        \ Magento \ Captcha \ Helper \ Data $ helper,
        \ Magento \ Framework \ App \ ActionFlag $ actionFlag,
        \ Magento \ Framework \ Message \ ManagerInterface $ messageManager,
        \ Magento \ Framework \ App \ Response \ RedirectInterface $ redirect,
        CaptchaStringResolver $ captchaStringResolver
    ) {
        $ this -> _ helper = $ помічник;
        $ this -> _ actionFlag = $ actionFlag;
        $ this-> messageManager = $ messageManager;
        $ this-> redirect = $ redirect;
        $ this-> captchaStringResolver = $ captchaStringResolver;
    }

    / **
     * Перевірте CAPTCHA на спеціальній формі
     *
     * @param \ Magento \ Framework \ Подія \ спостерігач $ спостерігач
     * @return void
     * /
    виконання публічної функції (\ Magento \ Framework \ Event \ Observer $ observer)
    {
        $ formId = 'custom_form';
        $ captcha = $ this -> _ helper-> getCaptcha ($ formId);
        if ($ captcha-> isRequired ()) {
            / ** @var \ Magento \ Framework \ Додаток \ Дія \ Контролер $ дій * /
            $ controller = $ observer-> getControllerAction ();
            if (! $ captcha-> isCorrect ($ this-> captchaStringResolver-> resolution ($ controller-> getRequest (), $ formId))) {
                $ this-> messageManager-> addError (__ ('Неправильна CAPTCHA.'));
                $ this-> getDataPersistor () -> set ($ formId, $ controller-> getRequest () -> getPostValue ());
                $ this -> _ actionFlag-> set ('', \ Magento \ Framework \ App \ Action \ Action :: FLAG_NO_DISPATCH, правда);
                $ this-> redirect-> redirect ($ controller-> getResponse (), 'yourroute / index / index');
            }
        }
    }

    / **
     * Отримати персистор даних
     *
     * @return DataPersistorInterface
     * /
    приватна функція getDataPersistor ()
    {
        if ($ this-> dataPersistor === null) {
            $ this-> dataPersistor = ObjectManager :: getInstance ()
                -> отримати (DataPersistorInterface :: class);
        }

        повернути $ this-> dataPersistor;
    }
}

Дуже детально. Я спробую це.
Павло

@Sohel Rana як можна додати його до форми відгуку про товар
supriya mishra

@supriyamishra потрібно перевірити
Сохель Рана

1
Привіт Капча відображається, але контролер спостерігача
washing_predispatch

1
Я вирішив вище помилку, але я не бачу капчу в моїй спеціальній формі
jafar pinjar

1

Для тих із вас, хто не може змусити це працювати, можливо, вам доведеться зробити те, що я зробив:

Причина, яку ви не можете відображати в Captcha, полягає в тому, що базові параметри полягають у використанні блоку captcha за замовчуванням, який у _toHtml робить перевірку, щоб перевірити, чи потрібна вона.

Якщо у вас є налаштування для показу captcha завжди, ніж ви, ймовірно, не стикалися з цією проблемою, однак якщо він не налаштований завжди показувати captchas і ви не хочете завжди показувати капчу (тобто створення облікового запису / вхід і т.д.), ніж вам потрібно встановіть логіку лише для вашої власної капчу на "Завжди потрібно".

на лінії 69 постачальника / magento / module-captcha / Block / Captcha / DefaultCaptcha.php ви побачите:

    /**
 * Renders captcha HTML (if required)
 *
 * @return string
 */
protected function _toHtml()
{

    if ($this->getCaptchaModel()->isRequired()) {
        $this->getCaptchaModel()->generate();
        return parent::_toHtml();
    }
    return '';
}

$this->getCaptchaModel()дзвінки, $this->_captchaData->getCaptcha()які є у постачальника / magento / module-captcha / Helper / Data.php

    /**
 * Get Captcha
 *
 * @param string $formId
 * @return \Magento\Captcha\Model\CaptchaInterface
 */
public function getCaptcha($formId)
{
    if (!array_key_exists($formId, $this->_captcha)) {
        $captchaType = ucfirst($this->getConfig('type'));
        if (!$captchaType) {
            $captchaType = self::DEFAULT_CAPTCHA_TYPE;
        } elseif ($captchaType == 'Default') {
            $captchaType = $captchaType . 'Model';
        }

        $this->_captcha[$formId] = $this->_factory->create($captchaType, $formId);
    }
    return $this->_captcha[$formId];
}

Тут метод getCaptcha перевіряє значення конфігурації для типу captcha для візуалізації та завантажує його завод $this->_factory->create()

Однак, вступивши в цей заводський клас, ви побачите

 public function create($captchaType, $formId)
{
    $className = 'Magento\Captcha\Model\\' . ucfirst($captchaType);

    $instance = $this->_objectManager->create($className, ['formId' => $formId]);
    if (!$instance instanceof \Magento\Captcha\Model\CaptchaInterface) {
        throw new \InvalidArgumentException(
            $className . ' does not implement \Magento\Captcha\Model\CaptchaInterface'
        );
    }
    return $instance;
}

Проблема тут полягає в тому, що незалежно від того, що фабрика буде виглядати в модулі Magento Captcha для будь-якої моделі заводу .. так

Нам потрібно створити плагін, щоб обернутися навколо помічника і перевірити, чи не використовується наш ключ форми, і якщо він використовується наш ключ форми, нам потрібно створити новий заводський клас, що завантажує нашу модель, яка розширює \ Magento \ Captcha \ Model \ DefaultModel та overides метод isRequired () Щось так виглядає:

у \ Ваш \ Модуль \ тощо \ 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">

<!--Custom Captcha-->
<type name="\Magento\Captcha\Helper\Data">
    <plugin name="custom-captcha" type="Your\Module\Plugin\Helper\CaptchaData" />
</type>

у вашому \ Модулі \ Плагін \ Помічник \ CaptchaData

<?php

namespace Your\Module\Plugin\Helper;

class CaptchaData
{
protected $_captcha = [];

public function __construct(
    \Your\Module\Model\CaptchaFactory $captchaFactory
) {
    $this->captchaFactory = $captchaFactory;
}

/**
 * @param \Magento\Captcha\Helper\Data $subject
 * @param \Closure $proceed
 * @param $formId
 * @return mixed
 */
public function aroundGetCaptcha(\Magento\Captcha\Helper\Data $subject, \Closure $proceed, $formId)
{
    if ($formId == 'your_form_key') {
        $this->_captcha[$formId] = $this->captchaFactory->create();
        return $this->_captcha[$formId];

    }
    return $proceed($formId);

}

}

в \ Ваш \ Модуль \ Модель \ CaptchaFactory

<?php
/**
* Captcha model factory
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Your\Module\Model;

class CaptchaFactory
{
/**
 * @var \Magento\Framework\ObjectManagerInterface
 */
protected $_objectManager;

/**
 * @param \Magento\Framework\ObjectManagerInterface $objectManager
 */
public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager)
{
    $this->_objectManager = $objectManager;
}

/**
 * Get captcha instance
 *
 * @param string $captchaType
 * @param string $formId
 * @return \Magento\Captcha\Model\CaptchaInterface
 * @throws \InvalidArgumentException
 */
public function create()
{
    $instance = $this->_objectManager->create('Your\Module\Model\Captcha', ['formId' => 'event_subscriber']);
    if (!$instance instanceof \Magento\Captcha\Model\CaptchaInterface) {
        throw new \InvalidArgumentException(
            'Your\Module\Model\Captcha does not implement \Magento\Captcha\Model\CaptchaInterface'
        );
    }
    return $instance;
}
}

і, нарешті, ваша модель, щоб перекрити потрібний параметр у \ Your \ Module \ Model \ Captcha :

<?php

namespace Your\Module\Model;

class Captcha extends \Magento\Captcha\Model\DefaultModel
{
    public function isRequired($login = null)
    {
        return true;
    }
 }

0

Мені потрібна капчу на сторінці передплатників бюлетеня, завдяки тому я був використаний спостерігачем за розсилками та роботою captcha на сторінці розсилки.

1) додаток / код / ​​ім'я постачальника / ім'я модуля / тощо / config.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <customer>
            <captcha>
                <shown_to_logged_in_user>
                    <custom_newsletter>1</custom_newsletter>
                </shown_to_logged_in_user>
                <always_for>
                    <custom_newsletter>1</custom_newsletter>
                </always_for>
            </captcha>
        </customer>
        <captcha translate="label">
            <frontend>
                <areas>
                    <custom_newsletter>
                        <label>Newsletter Form</label>
                    </custom_newsletter>
                </areas>
            </frontend>
        </captcha>
    </default>
</config>

2) Перейдіть на "Адміністратор -> Магазини -> Конфігурація -> Клієнт -> Конфігурація клієнта -> Captcha" та налаштуйте. Ви можете побачити значення нових форм "Форма бюлетеня".

3) скопіювати файл макета в тему (default.xml)

<block class="Magento\Newsletter\Block\Subscribe" name="subscribe form " template="Magento_Newsletter::subscribe.phtml">
                <container name="form.additional.info" label="Form Additional Info">
                    <block class="Magento\Captcha\Block\Captcha" name="captcha" after="-" cacheable="false">
                        <action method="setFormId">
                            <argument name="formId" xsi:type="string">custom_newsletter</argument>
                        </action>
                        <action method="setImgWidth">
                            <argument name="width" xsi:type="string">230</argument>
                        </action>
                        <action method="setImgHeight">
                            <argument name="width" xsi:type="string">50</argument>
                        </action>
                    </block>
                </container>

4) Створити спостерігача -> створити файл event.xml у додатку / код / ​​Ім'я продавця / Ім'я модуля / тощо / frontend

 <?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_predispatch_newsletter_subscriber_new">
        <observer name="captcha_newletter_form" instance="Vendorname/Modulename/Observer\CheckCustomFormObserver" />
    </event>
</config>

5) Створіть модель спостерігача та перевірте додаток / код captcha / ім'я постачальника / ім'я модуля / спостерігача / CheckCustomFormObserver.php

public function execute(\Magento\Framework\Event\Observer $observer)
        {   $formId = 'custom_newsletter';
            $captcha = $this->_helper->getCaptcha($formId);
            if ($captcha->isRequired()) {
                /** @var \Magento\Framework\App\Action\Action $controller */
                $controller = $observer->getControllerAction();
                $params=$controller->getRequest()->getPost();
                $currentpage = $params['currentpage'];


                if (!$captcha->isCorrect($this->captchaStringResolver->resolve($controller->getRequest(), $formId))) {                
                    $this->messageManager->addError(__('Incorrect CAPTCHA.'));
                    $this->getDataPersistor()->set($formId, $controller->getRequest()->getPostValue());
                    $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
                    $this->redirect->redirect($controller->getResponse(), $currentpage);
                }
            }
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.