В настоящее время статья полезна исключительно для ознакомления. В Zend Framework был добавлен компонент Zend_Captcha, который, в том числе, может работать и с сервисом reCAPTCHA.

Всем привет.
Думаю, многие знают проект reCAPTCHA. Суть этого проекта в том, что за счёт капчи пользователи помогают оцифровывать книжные архивы.
Сейчас мы будем интегрировать reCAPTCHA в Zend Framework, и, в частности, в Zend_Form.

Немного про проект reCAPTCHA. На капче показываются два слова, одно из которых уже было распознано и специальным образом искажено. Второе слово автоматически распознать не получилось. Пользователю же приходится вводить оба слова. Таким нехитрым способом пользователи ресурса помогают доброму делу.
Разумеется, этим дело не ограничивается – reCAPTCHA также предоставляет удобный интерфейс для работы с капчей, позволяющий даже прослушать содержимое. Таким образом, решается ещё одна проблема, особенно свойственная рунету – пользователи, имеющие проблемы со зрением, тоже смогут пройти проверку и не будут приравнены к роботам.
Ну и, напоследок: очень много информации о проекте reCAPTHCA

Прежде всего, вам необходимо будет зарегистрироваться и получить два ключа (public и private) для вашего домена. Затем скачать PHP-класс recaptchalib.php и разместить его в папке library/Recaptcha, по аналогии с library/Zend. Также вы можете взять этот класс во вложении к статье.

Для интеграции reCAPTCHA с Zend Framework я написал некоторые компоненты:

  • Serkys_Form_Element_ReCaptcha
  • Serkys_Validate_ReCaptcha
  • Serkys_View_Helper_FormReCaptcha

Объявляем функцию getCaptchaKey(). Обратите внимание – вам необходимо указать свой путь к файлу конфигурации recaptcha.ini (формат см. ниже).

1
2
3
4
5
6
7
8
function getCaptchaKey($keyType) {
    static $serverName;
    if (empty($serverName)) {
        $serverName = preg_replace('/^(www.){0,1}/', '', $_SERVER['SERVER_NAME']);
    }
    $config = new Zend_Config_Ini('cfg/recaptcha.ini', $serverName);
    return $config->$keyType;
}

Конфигурационный файл recaptcha.ini:

1
2
3
4
5
6
[yandex.ru]
public = "6Ld1fAIAAAAAA..............P54biKD_xPkXtyr9l7"
private = "6Ld1fAIAAAAA............JNsBTpUmLNOdvP4Hggr"
[yandex.local]
public = "6Ld2fAIAAAAAALI.............InBTX2nnmxemU"
private = "6Ld2fAIAAAAAA...........qBPu0o-pZmq2Hc-MMv"

library/Serkys/Form/Element/ReCaptcha.php (комментарии убраны для компактности, в архиве с файлами всё есть)

1
2
3
4
5
6
require_once 'Zend/Form/Element/Xhtml.php';
require_once 'Recaptcha/recaptchalib.php' ;
class Serkys_Form_Element_ReCaptcha extends Zend_Form_Element_Xhtml
{
    public $helper = 'formReCaptcha';
}

library/Serkys/Validate/ReCaptcha.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
require_once 'Zend/Validate/Abstract.php';
require_once('Recaptcha/recaptchalib.php');
class Serkys_Validate_ReCaptcha extends Zend_Validate_Abstract
{
    const IS_ERROR = 'isError';
    protected $_messageTemplates = array(
        self::IS_ERROR => "Incorrect CAPTCHA string"
    );
    protected $_challengeField, $_privateKey;
    public function __construct($challengeField) {
        $this->_challengeField = (string)$challengeField;
        $this->_privateKey = getCaptchaKey('private');
    }
    public function isValid($value)
    {
        $valueString = (string) $value;
        $this->_setValue($valueString);
        if (!recaptcha_check_answer($this->_privateKey, $_SERVER["REMOTE_ADDR"], $this->_challengeField, $valueString)->is_valid) {
            $this->_error();
            return false;
        }
        return true;
    }
}

library/Serkys/View/Helper/FormReCaptcha.php

1
2
3
4
5
6
7
8
9
10
require_once 'Zend/View/Helper/FormElement.php';
require_once 'Recaptcha/recaptchalib.php';
class Serkys_View_Helper_FormReCaptcha extends Zend_View_Helper_FormElement
{
    public function formReCaptcha($name, $value = null, $attribs = null)
    {
        $xhtml = recaptcha_get_html(getCaptchaKey('public'));
        return $xhtml;
    }
}

Пример использования вместе с Zend_Form. Здесь есть одна тонкость – пока нет возможности указать имя, отличное от ‘recaptcha_response_field’. В будущем я намерен устранить это. Если кто-нибудь исправит эту недоработку – буду рад :)

1
2
3
4
$element = new Serkys_Form_Element_ReCaptcha('recaptcha_response_field');
$element->addValidator(new Serkys_Validate_ReCaptcha(@$_POST['recaptcha_challenge_field']))
    ->setRequired(true);
$form->addElement($element);

Архив с исходными текстами

3 Comments

  1. badtema says:

    Спасиб за подсказку, а то с этой капчей уже долго мучаюсь!

  2. admin says:

    Это всё уже пустое :)
    В инкубаторе ZF’а лежит компонент для работы с reCAPTHA. Пока в инкубаторе – использовать не советую, а вот переместят в library – уже можно будет поюзать.

  3. amxm says:

    Сколько я мучался с этим зендом, но даже сейчас кажется что слишком уж много времени надо потратить что бы сделать элементарное. Чисто моё мнение.
    А если конкретно по этому посту, то тут всё отлично описано.

Leave a Reply