如何使用EWZRecaptchaBundle在单个页面上显示多个recaptcha?

时间:2015-08-21 09:52:20

标签: php symfony recaptcha

我正在使用EWZRecaptchaBundle,这是一个为Symfony提供reCAPTCHA表单字段的包。

当我尝试渲染1次recaptcha时,它工作正常,但是当我尝试2时,它只显示第一次。

是否可以使用此捆绑包在单个页面上显示多个recaptcha?

我的代码:

composer.json

"require": {
    ...
    "excelwebzone/recaptcha-bundle": "~1.4.1",
}


AppKernel.php

$bundles = array(
    // ...
    new EWZ\Bundle\RecaptchaBundle\EWZRecaptchaBundle(),
    // ...
);


# app/config/config.yml

ewz_recaptcha:
    public_key:  here_is_your_public_key
    private_key: here_is_your_private_key
    locale_key:  %kernel.default_locale%


//form class
<?php

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('recaptcha', 'ewz_recaptcha', [
            'required'    => true,
            'constraints' => [
                new RecaptchaTrue()
            ],
            'mapped' => false,
        ])


//twig template
<div id="recaptcha_google_div" {% if not signupForm.recaptcha.vars.valid %}class="left"{% endif %}>
    {{ form_widget(signupForm.recaptcha) }}
    {{ form_errors(signupForm.recaptcha) }}
</div>

1 个答案:

答案 0 :(得分:3)

我在谷歌上查了这个问题,但遗憾地找不到答案。我设法找到了解决方案,所以我的工作方式如下:

首先我制作了一个自定义表单主题:

{% block ewz_recaptcha_widget %}
{% spaceless %}
    {% if form.vars.ewz_recaptcha_enabled %}
        {% if not form.vars.ewz_recaptcha_ajax %}
            <script>
                var captchaCallback = function() {
                    var captchas = document.getElementsByClassName('g-recaptcha');

                    for (var i = 0; i < captchas.length; i++) {
                        grecaptcha.render(captchas[i], {
                            'sitekey': '{{ form.vars.public_key }}',
                            'theme': '{{ attr.options.theme }}'
                        });
                    }
                };
            </script>
            <div class="g-recaptcha" data-theme="{{ attr.options.theme }}" data-size="{{ attr.options.size }}" data-type="{{ attr.options.type }}" data-sitekey="{{ form.vars.public_key }}" {% if attr.options.expiredCallback is defined %}data-expired-callback="{{ attr.options.expiredCallback }}"{% endif %}></div>
            <noscript>
                <div style="width: 302px; height: 352px;">
                    <div style="width: 302px; height: 352px; position: relative;">
                        <div style="width: 302px; height: 352px; position: absolute;">
                            <iframe src="https://www.google.com/recaptcha/api/fallback?k={{ form.vars.public_key }}"
                                    frameborder="0" scrolling="no"
                                    style="width: 302px; height:352px; border-style: none;"
                            >
                            </iframe>
                        </div>
                        <div style="width: 250px; height: 80px; position: absolute; border-style: none; bottom: 21px; left: 25px; margin: 0; padding: 0; right: 25px;">
                            <textarea id="g-recaptcha-response" name="g-recaptcha-response"
                                      class="g-recaptcha-response"
                                      style="width: 250px; height: 80px; border: 1px solid #c1c1c1; margin: 0; padding: 0; resize: none;"
                            >
                            </textarea>
                        </div>
                    </div>
                </div>
            </noscript>
        {% else %}
            <div id="ewz_recaptcha_div"></div>

            <script type="text/javascript">
            (function() {
                var script = document.createElement('script');
                script.type = 'text/javascript';
                script.onload = function() {
                    Recaptcha.create('{{ form.vars.public_key }}', 'ewz_recaptcha_div', {{ attr.options|default({})|json_encode|raw }});
                };
                script.src = '{{ form.vars.url_api }}';
                {% if attr.options.defer is defined and attr.options.defer %}script.defer = true;{% endif %}
                {% if attr.options.async is defined and attr.options.async %}script.async = true;{% endif %}
                document.getElementsByTagName('head')[0].appendChild(script);
            })();
            </script>
        {% endif %}
    {% endif %}
{% endspaceless %}
{% endblock ewz_recaptcha_widget %}

它与默认形式主题几乎相同,只是我更改了两件事。我添加了一个回调函数,我删除了google recaptcha api脚本(以防止它两次调用回调函数)。

然后,您必须在其中一个模板中手动加载recaptcha api脚本:

<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl={{ app.request.locale }}&amp;onload=captchaCallback&amp;render=explicit" defer async></script>

您需要在加载表单的任何地方加载自定义表单主题:

{% form_theme form 'form/captcha_layout.html.twig' %}

这应该允许您在同一页面上拥有多个验证码。