📜 ⬆️ ⬇️

Customization captcha in Zend Framework 2

The Zend \ Captcha component can take various forms, including asking logical questions, generating distorted fonts, and transferring multiple images by establishing a connection between them. Zend \ Captcha aims to provide a variety of server solutions that can be used either offline or in combination with the Zend \ Form component.

The Captcha element has more than one field that is rendered one after another. The built-in captch image generator ( Zend \ Captcha \ Image.php ) uses its own helper ( Zend \ Form \ View \ Helper \ Captcha \ Image.php ) to create an image. Also, in Zend \ Captcha \ Image.php is the 'getHelperName' method. This method sends the name of the helper for rendering the captcha image. By default, 'getHelperName' sends 'captcha / image' - an instance of the class Zend \ Form \ View \ Helper \ Captcha \ Image.php . If you go deep with the debugger, you can see that in the instance property of phpRenderer :: __ helpers , in invokablesClasses is the helper 'captchaimage'. This is the Zend \ Form \ View \ Helper \ Captcha \ Image.php mentioned earlier. Roughly speaking, you simply create an image, and the renderer does the rest for you using a helper, although not everyone is happy with this state of affairs.

When you create a Captcha form element ( Zend \ Form \ Element \ Captcha.php ), you transfer a captcha image ( Zend \ Captcha \ Image.php ) to this element. The Captcha form element, in turn, also has its own helper ( Zend \ Form \ View \ Helper \ FormCaptcha.php ). In the render method of this helper, you will see that the captcha image ( Zend \ Captcha \ Image.php ) is loaded using the ElementInterface:

//Zend\Form\View\Helper\FormCaptcha.php public function render(ElementInterface $element) { $captcha = $element->getCaptcha(); 

')
after which the helper is called via the 'getHelperName' method:

 $helper = $captcha->getHelperName(); 


As a result, we get an instance of the helper class using the PhpRenderer instance and return the view:

 $helper = $renderer->plugin($helper); return $helper($element); 


We need to clearly understand the difference between the 'Captcha form element and its helper' and the 'Captcha image also with its helper'. We will pass the 'captcha image' to the Captcha form element, which already has an associated helper. The render method of the Captcha form element will embed an instance of the Captcha image that we passed using the helper to generate the image and return the view. All that needs to be done is to transfer the new helper to the Captcha image, which will display the presentation in the way we are satisfied and rewrite Zend \ Captcha \ Image.php to get our new helper, and not our default.

Before we begin, let's pay attention to a few details:
Zend \ Form \ View \ Helper \ Captcha \ Image.php helper for captcha defines the pattern as% s% s% s:

 $pattern = '%s%s%s'; 


Thus, the first thing that is needed is our custom helper with its own pattern. Let's create it in the Application module:

 //module\Application\src\Application\View\Helper\Form\Captcha\ViewHelperCaptcha.php <?php namespace Application\View\Helper\Form\Captcha; use Zend\Form\View\Helper\Captcha\AbstractWord; use Application\View\Helper\Form\Captcha\CustomCaptcha as CaptchaAdapter; use Zend\Form\ElementInterface; use Zend\Form\Exception; class ViewHelperCaptcha extends AbstractWord { /** * Override * * Render the captcha * * @param ElementInterface $element * @throws Exception\DomainException * @return string */ public function render(ElementInterface $element) { //         . $this->setSeparator('') $captcha = $element->getCaptcha(); if ($captcha === null || !$captcha instanceof CaptchaAdapter) { throw new Exception\DomainException(sprintf( '%s requires that the element has a "captcha" attribute of type Zend\Captcha\Image; none found', __METHOD__ )); } //     (  600). $captcha->setExpiration(10); //    (  10).        . $captcha->setGcFreq(1); $captcha->generate(); $imgAttributes = array( 'width' => $captcha->getWidth(), 'height' => $captcha->getHeight(), 'alt' => $captcha->getImgAlt(), 'src' => $captcha->getImgUrl() . $captcha->getId() . $captcha->getSuffix(), ); $closingBracket = $this->getInlineClosingBracket(); $img = sprintf( '<img %s%s', $this->createAttributesString($imgAttributes), $closingBracket ); $position = $this->getCaptchaPosition(); $separator = $this->getSeparator(); $captchaInput = $this->renderCaptchaInputs($element); //   $pattern = '<div class="captcha_image"> %s</div> %s<div class="captcha_input"> %s</div>' if ($position == self::CAPTCHA_PREPEND) { return sprintf($pattern, $captchaInput, $separator, $img); } return sprintf($pattern, $img, $separator, $captchaInput); } } 


The class of our helper duplicates the class Zend \ Form \ View \ Helper \ Captcha \ Image.php with a few changes. Our helper does not use Zend \ Captcha \ Image.php to generate an image, unlike the original one. Remember that Zend \ Captcha \ Image.php provides the 'getHelperName' method that returns the hard-coded helper name 'captcha / image', so when the form generates an image, it will not receive its default helper, but the newly created us. What else is needed is to pass our custom helper to phpRenderer and generate a new captcha image that will extend the original Zend \ Captcha \ Image.php class and rewrite the 'getHelperName' method by setting the name of the helper we created.

So let's add our class to the phpRenderer invokables helper configuration. We implement this in module.config.php:

 //module\Application\config\module.config.php ... 'view_helpers' => array( 'invokables' => array( 'viewhelpercaptcha' => 'Application\View\Helper\Form\Captcha\ViewHelperCaptcha', ), ), 


The next step is to create a captcha image that will return our helper added to the module configuration as the phpRenderer invokables class. There is no need to redefine the whole Zend \ Captcha \ Image.php class , it is enough to point our custom helper class as a parameter to the 'getHelperName' method. To do this, create a class and name it, for example, CustomCaptcha.php in the module \ Application \ src \ Application \ View \ Helper \ Form \ Captcha folder. We are going to extend the original Zend \ Captcha \ Image.php class and override the 'getHelperName' method so that it returns our helper 'viewhelpercaptcha'. It does not hurt to override the error messages in the $ messageTemplates property. At your discretion.

 //module\Application\src\Application\View\Helper\Form\Captcha\CustomCaptcha.php <?php namespace Application\View\Helper\Form\Captcha; // ,   . use Zend\Captcha\Image as CaptchaImage; //  ,      . class CustomCaptcha extends CaptchaImage { protected $messageTemplates = array( self::MISSING_VALUE => ' ', self::MISSING_ID => ' ID ', self::BAD_CAPTCHA => '  ', public function getHelperName() { return 'viewhelpercaptcha'; } } 


The last thing we need to do is use our CustomCaptcha image in shape. To do this, create two folders: one for the font (zf2folder / data / fonts), which you will need to generate captcha words, and another, for storing the captch image files (zf2folder / public / img / captcha). Naturally, copy the * .ttf font to the fonts folder, for example arial.ttf.

For example, you can take the form from the official tutorial:

 <?php namespace Album\Form; use Zend\Form\Form; use Application\Form\View\Helper\Captcha\CustomCaptcha; class AlbumForm extends Form { public function __construct($name = null) { //    parent::__construct('album'); $this->setAttribute('method', 'post'); //    ... //    Captcha $dirdata = './data'; //  CustomCaptcha  $captchaImage = new CustomCaptcha(array( 'font' => $dirdata . '/fonts/arial.ttf', 'width' => 120, 'height' => 60, 'fsize' => 20, 'wordLen' => 5, 'dotNoiseLevel' => 25, 'lineNoiseLevel' => 2 )); //     $captchaImage->setImgDir('public/img/captcha/'); //      $captchaImage->setImgUrl('/img/captcha/'); $captchaImage->setImgAlt('   ?'); //   Captcha    CustomCaptcha,   $this->add(array( 'type' => 'Zend\Form\Element\Captcha', 'name' => 'captcha', 'options' => array( 'captcha' => $captchaImage, ), 'attributes' => array( 'class' => 'some_class', ) )); $this->add(array( 'name' => 'submit', 'attributes' => array( 'type' => 'submit', 'value' => 'Go', 'id' => 'submitbutton', ), )); } } 


Add a captcha element to the view file

 echo $this->formRow($form->get('captcha')) . PHP_EOL; 


After examining the structure of the html document that is output, you will see that now the image and the captcha input field are wrapped in divs. We got a more orderly design.

Used sources:
framework.zend.com/manual/2.2/en/modules/zend.captcha.intro.html
framework.zend.com/manual/2.2/en/modules/zend.captcha.operation.html
framework.zend.com/manual/2.2/en/modules/zend.captcha.adapters.html
framework.zend.com/manual/2.2/en/user-guide/forms-and-actions.html
zendtemple.blogspot.com/2012/12/zend-framework-2-zf2-creating-view.html
samsonasik.wordpress.com/2012/09/12/zend-framework-2-using-captcha-image-in-zend-form

Source: https://habr.com/ru/post/183232/


All Articles