Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Using Captcha Image in Zend\Form

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on September 12, 2012

Zend Framework provide a component named Zend\Captcha\Image that can be integrated with Zend\Form. It’s very fast to create a captcha image, and put to our form application. I will give an example to you how to work with it.

We want to create form like this :

So, we should create directory structure like the following :

captcha folder is to save image captcha that will be generated.and fonts folder is to save fonts we will needed.
Ok, let’s configure :
1. Register Controller invokables

'controllers' => array(
     'invokables' => array(
         'Test\Controller\Testcaptcha' => 'Test\Controller\TestcaptchaController'

2. Set Route

'router' => array(

    'routes' => array(

        'Test' => array(
            'type'    => 'Literal',
            'options' => array(
                // Change this to something specific to your module
                'route'    => '/test',
                'defaults' => array(
                    // Change this value to reflect the namespace in which
                    // the controllers for your module are found
                    '__NAMESPACE__' => 'Test\Controller',
                    'controller'    => 'testcaptcha',
                    'action'        => 'form',
            'may_terminate' => true,
            'child_routes' => array(

                'captcha_form' => array(
                    'type'    => 'segment',
                    'options' => array(
                        'route'    => '/[:controller[/[:action[/]]]]',
                         'constraints' => array(
                            'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'defaults' => array(),

                'captcha_form_generate' => array(
                    'type'    => 'segment',
                    'options' => array(
                        'route'    =>  '/[:controller[/captcha/[:id]]]',
                         'constraints' => array(
                            'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'defaults' => array(
                            'controller' => 'testcaptcha',
                            'action'     => 'generate',

3. Configuration done, let’s create a form :

namespace Test\Form;

use Zend\Form\Form,
    Zend\Captcha\Image as CaptchaImage;

class TestCaptchaForm extends Form
    public function __construct($urlcaptcha = null)
        parent::__construct('Test Form Captcha');
        $this->setAttribute('method', 'post');

        $dirdata = './data';

                                         //pass captcha image options
        $captchaImage = new CaptchaImage(  array(
                'font' => $dirdata . '/fonts/arial.ttf',
                'width' => 250,
                'height' => 100,
                'dotNoiseLevel' => 40,
                'lineNoiseLevel' => 3)

        //add captcha element...
            'type' => 'Zend\Form\Element\Captcha',
            'name' => 'captcha',
            'options' => array(
                'label' => 'Please verify you are human',
                'captcha' => $captchaImage,

            'name' => 'submit',
            'attributes' => array(
                'type'  => 'submit',
                'value' => 'Test Captcha Now'


4. Create Controller :

namespace Test\Controller;

use Zend\Mvc\Controller\AbstractActionController,

class TestcaptchaController extends AbstractActionController

    public function generateAction()
        $response = $this->getResponse();
        $response->getHeaders()->addHeaderLine('Content-Type', "image/png");

        $id = $this->params('id', false);

        if ($id) {

            $image = './data/captcha/' . $id;

            if (file_exists($image) !== false) {
                $imagegetcontent = @file_get_contents($image);


                if (file_exists($image) == true) {


        return $response;

    public function formAction()
        $form = new TestCaptchaForm($this->getRequest()->getBaseUrl().'/test/testcaptcha/captcha/');
        $request = $this->getRequest();
        if ($request->isPost()) {
            //set data post

            if ($form->isValid()) {
                echo "captcha is valid ";

        return array('form' => $form);

5. Show in the view :

$form = $this->form;
                               array('controller'=>'testcaptcha', 'action' => 'form')));

echo $this->form()->openTag($form);

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

echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag();

6. Testing, access the form :

btw, i just publish the source code at my github account : https://github.com/samsonasik/SanCaptcha , follow the instruction.

Done !

73 Responses

Subscribe to comments with RSS.

  1. Manuel Stosic said, on September 12, 2012 at 12:48 pm

    What the hell is “$dirdata = dirname(dirname(dirname(dirname(dirname(__DIR__))))).’/data’;”

    Take a look at “public/index.php”
    You’ll see “chdir(dirname(__DIR__));”

    This means, that the relative path for all future includes – as long as not changed at a later time – will be based off of ZF2’s root path.
    This means that your super long $dirdata could just be “$dirdata = ‘./data’;”

    Other than that, good idea to extend from a captcha-form.

  2. samsonasik said, on September 12, 2012 at 1:54 pm

    Aha,my bad. Thank You very much. the post updated !

  3. moe said, on October 18, 2012 at 9:38 pm

    I don’t get it, how is the image rendered in the view? the view trys to render the captcha image from
    src=”/application/index/captcha/5aa8e20f569e8abe6c919078be3ef7f4.png” and can’t find the image.

    • samsonasik said, on October 18, 2012 at 11:29 pm

      what zf version you’re using ? if you try to follow my tutorial, i’m sure the result will success.

    • moe said, on October 18, 2012 at 11:38 pm

      i guess my problem is, where u call the generateAction😦

      • samsonasik said, on October 19, 2012 at 5:20 am

        just look at the module.config route🙂

  4. Andre said, on October 21, 2012 at 1:35 am

    did not work for me

    $this->getRequest()->getBaseUrl() is not getting the value. I used this version:

    $uri = $this->getRequest()->getUri();
    $scheme = $uri->getScheme();
    $host = $uri->getHost();
    $base = sprintf(‘%s://%s’, $scheme, $host);

    $form = new RegisterForm($base.’/register/generate/’);

    and also changed the route

    ‘register’ => array(
    ‘type’ => ‘segment’,
    ‘options’ => array(
    ‘route’ => ‘/register[/:action][/:id]’,
    ‘defaults’ => array(
    ‘__NAMESPACE__’ => ‘Login\Controller’,
    ‘controller’ => ‘Login\Controller\Register’,
    ‘action’ => ‘index’,


  5. moe said, on October 30, 2012 at 1:51 am

    sry for codespamming but i dont get it how your example ever could work😦 using zf 2.0.2
    i dont get the image rendered in browser and dont have a call to the generateAction.
    my route:
    ‘recover’ => array(
    ‘type’ => ‘Literal’,
    ‘options’ => array(
    ‘route’ => ‘/application’,
    ‘defaults’ => array(
    ‘__NAMESPACE__’ => ‘Application\Controller’,
    ‘controller’ => ‘Index’,
    ‘action’ => ‘recover’,
    ‘may_terminate’ => true,
    ‘child_routes’ => array(
    ‘captcha_form’ => array(
    ‘type’ => ‘segment’,
    ‘options’ => array(
    ‘route’ => ‘/[:controller[/[:action[/]]]]’,
    ‘constraints’ => array(
    ‘action’ => ‘[a-zA-Z][a-zA-Z0-9_-]*’,
    ‘defaults’ => array(),
    ‘captcha_form_generate’ => array(
    ‘type’ => ‘segment’,
    ‘options’ => array(
    ‘route’ => ‘/[:controller[/captcha/[:id]]]’,
    ‘constraints’ => array(
    ‘action’ => ‘[a-zA-Z][a-zA-Z0-9_-]*’,
    ‘defaults’ => array(
    ‘controller’ => ‘index’,
    ‘action’ => ‘generate’,

    and my two actions:
    public function generateAction()
    $response = $this->getResponse();
    $response->getHeaders()->addHeaderLine(‘Content-Type’, “image/png”);

    $id = $this->params(‘id’, false);
    if ($id)
    $image = ‘./data/captcha/’ . $id;
    if (file_exists($image) !== false) {
    $imagegetcontent = @file_get_contents($image);


    if (file_exists($image) == true)
    return $response;

    public function recoverAction()
    $uri = $this->getRequest()->getUri();
    $scheme = $uri->getScheme();
    $host = $uri->getHost();
    $base = sprintf(“%s://%s”, $scheme, $host);
    $recform = new RecoverForm($base.’/application/index/captcha/’);
    $translator = $this->getServiceLocator()->get(‘translator’);

    $newView = new ViewModel();
    $newView->setVariable(“recform”, $recform);


    and in view:
    $recform = $this->recform;
    $recform->setAttribute(‘action’,$this->url(‘application/captcha_form’, array(‘controller’=>’index’, ‘action’ => ‘recover’)));

    And sorry for this long posting🙂

    • samsonasik said, on October 30, 2012 at 11:46 am

      have you create folder named captcha and fonts in folder data ? have you save the font arial.ttf in folder fonts ?
      btw, I just publish the source code at github : https://github.com/samsonasik/SanCaptcha , follow the instruction.

      • moe said, on October 30, 2012 at 4:41 pm

        creating the captchaimage works fine he only doenst render it in the view

      • samsonasik said, on October 30, 2012 at 8:04 pm

        you can comment unlink method after image created for testing. just check with firebug🙂. btw, you should check chmod of the directory ;

  6. loktheprince said, on December 5, 2012 at 6:53 pm

    working f9 if iam using your code.I tried with my album module. captcha image is not showing in view. if i use like below it is working
    $form = new AlbumForm($this->getRequest()->getBaseUrl().’/SanCaptcha/testcaptcha/captcha/’);
    may i know y this is not working like below
    $form = new AlbumForm($this->getRequest()->getBaseUrl().’/Album/album

    • samsonasik said, on December 5, 2012 at 11:56 pm

      check your module.config.php with your captcha route config.

      • loktheprince said, on December 6, 2012 at 2:42 pm

        yes. there was problem with route. now it is f9. thanq for your response.

      • samsonasik said, on December 6, 2012 at 2:52 pm

        you’re welcome.

      • Gustavo Souza Gonçalves said, on August 11, 2015 at 4:04 am

        Hello, i’m having same problem as loktheprince. I couldn’t find where is wrong. There are things different according your code, sure, but i took care to watch about it. Still…
        I’m using the main module (Application) and the generateAction is in IndexController. I’m calling from the LoginController. The picture is generated, but the view is not rendering it.

        The problem must be simple to resolve, but i can’t figure where is.


        Thanks in advance.

      • samsonasik said, on August 11, 2015 at 3:41 pm

        check the route, at your case, it under ‘lang’ as child route and you need to adapt that.

  7. Aamir said, on January 29, 2013 at 11:31 am

    Can you explain the flow…..i m new in zend plz

    • Aamir said, on January 29, 2013 at 11:34 am

      I cant understand how you call generateAction……

      • samsonasik said, on January 29, 2013 at 1:23 pm

        route segment :


        in routename ‘captcha_form_generate’ represented generateAction()

  8. Aamir said, on January 30, 2013 at 2:49 pm

    Thanx for yor response..

  9. Reginaldo Pires said, on February 14, 2013 at 6:35 pm

    Hi Abdul, your example worked very well and helped me a lot. Thank you.

    Now, how do I css styling with the error message the captcha?

    I tried to add separate objects (input, label, errormesages) in the view but, could not add the image of capctha separately.

    Thank you.

    • samsonasik said, on February 15, 2013 at 12:14 am

      You can use form element as the following :

      <div class="control-group">
          <?php echo $this->formLabel($form->get('captcha')); ?>
          <div class="controls">
              <?php echo $this->formElement($form->get('captcha')); ?>
              <?php echo $this->formElementErrors($form->get('captcha')); ?>

      And, you create custom view helper if needed, for example :

      namespace SanCommons\View\Helper;
      use Zend\Form\View\Helper\FormElementErrors as ParentElementErrors;
      class FormElementErrors extends ParentElementErrors
          protected $messageOpenFormat      = '<ul class="error" %s><li>';

      and register your custom FormElementErrors in view_helpers invokables.

          'view_helpers' => array(
              'invokables' => array(
                  'formelementerrors' => 'SanCommons\View\Helper\FormElementErrors',
  10. Tran Viet said, on February 26, 2013 at 11:38 am

    Code does not work😦
    I have access directly http://localhost/zf2_tutorial/public/test/testcaptcha/form/de588aaa7e5a8f155941877e0a05320a.png and receive messages (firefox) can not be displayed beacause it contains errors.

    But if I delete line $ response->getHeaders ()->addHeaderLine(‘Content-Type’, “image / png”); and get the contents of this file image. I think the problem is the header of problem zf2.

    Appreciate your help, thank you

    • samsonasik said, on February 26, 2013 at 1:41 pm

      The image re-rendered after refresh, so you will not find the image, if you want to keep image, just remove line


      I’m using ZF 2.1.3 ( latest ) and it’s just work. try get source from my github account : https://github.com/samsonasik/SanCaptcha and follow the README instruction. If problem persist, look at apache error log.

      • Tran Viet said, on February 26, 2013 at 3:01 pm

        I deleted the unnecessary lines, code now

        public function generateAction(){

        header(‘Content-Type: image/png’);

        $image = ‘./data/captcha/capt1.png’;

        $imagegetcontent = @file_get_contents($image);

        echo $imagegetcontent;

        I recievied error above😦

        I’m using the zf 2.1.3 and I have test https://github.com/samsonasik/SanCaptcha but still so

        Thank u🙂

      • samsonasik said, on February 26, 2013 at 3:24 pm

        it’s weird, i’m curious it’s your apache problem. check your apache error log.

      • Tran Viet said, on February 26, 2013 at 4:38 pm

        i tested your source code and recieved error
        Warning: Cannot modify header information – headers already sent by (output started at E:\xampp1.7.7\htdocs\zend2.0\module\SanCaptcha\src\SanCaptcha\Controller\TestcaptchaController.php:24) in E:\xampp1.7.7\htdocs\zend2.0\vendor\ZF2\library\Zend\Http\PhpEnvironment\Response.php on line 99

        it’s this line : $imageread = fpassthru($fp)😦

        I checked apache, no problem😦

  11. samsonasik said, on February 26, 2013 at 4:43 pm

    headers already sent come from whitespace, strip your code whitespace.

  12. Danilov Anatoly (@danilovonline) said, on July 15, 2013 at 12:27 am

    Thank you very much.
    I started learning zf2. I have not found a more intelligent than your examples. Thank you again.

  13. Francisco Leyva said, on July 31, 2013 at 12:21 am

    Hi Samsonasik!

    Thank you very much for your examples, are ver helpfull.

    The example work very well, but I have a rare case,I don´t know why sometimes the image doesn’t shows and after refresh (sometimes I have to refresh more than once) appears again, even though the image is not displayed, this is created in the directory.

    Thank you again and sorry for my english.

  14. samia said, on September 11, 2013 at 4:19 pm

    Hi Samsonasik. Brilliant Post. I used your captcha. It was working absolutely fine before but now i recently update zf2 version to the latest release and it keeps give me the error that captcha value is wrong eventhough i am putting in the right value. Can you please help me on this case. Thanks. Samia

  15. samsonasik said, on September 14, 2013 at 8:59 am

    I’m using ZF 2.2.4 and it just work. please use latest master update at http://github.com/samsonasik/SanCaptcha

  16. Dinesh sahoo said, on September 15, 2013 at 5:44 pm

    I want to hide the error message. How will I do that ?

  17. DD said, on October 3, 2013 at 5:12 pm

    Thanks for posting this.. Cheers!

  18. priyank said, on October 9, 2013 at 4:03 pm

    thanks bro for help…🙂

  19. sarada said, on October 29, 2013 at 7:15 pm

    how to get captch image code. or validate in client side captcha ?

  20. Farahmand Moslemi said, on November 24, 2013 at 3:26 am

    Thank you for this. Also, you can use the line bellow if you want to regenerate captcha by clicking on the captcha image:

    // file: testCaptchaForm.php
    // After line #25

    'name' => 'captcha-img',
    'type' => 'Zend\Form\Element\Image',
    'attributes' => array(
    'src' => $captchaImage->getImgUrl() . $captchaImage->getId() . $captchaImage->getSuffix(),

  21. Imrul said, on January 14, 2014 at 8:00 pm

    nice Farahmand Moslemi bro….

  22. bala said, on January 22, 2014 at 3:45 pm

    How to use captcha without using zend form.Can we use in normal HTML form?

  23. gaurav tayal said, on February 18, 2014 at 10:55 am

    Can you tell me how to show only five character in captcha Image

  24. bksi said, on April 14, 2014 at 6:28 am

    This doesn’t work😦 Using newest zend framework 2.3 Unknown class CaptchaImage. When trying the class Captcha, it doesn’t have methods setImgUrl, etc…

    • bksi said, on April 14, 2014 at 6:53 am

      I found the reason for my code don’t work, but my code works without the routes and generateAction in the controller. I think this action should be for AJAX usage or somthing like that. What do you think?

  25. Pan said, on June 8, 2014 at 4:50 am

    Hi there,

    Thank you for the example first of all, but allow me some comments. Why don’t you say exactly the name of the files that need modifications, like the module.config.php for example. Also, it does not work for me, I get errors


    Zend\View\Renderer\PhpRenderer::render: Unable to render template “test/testcaptcha/form”; resolver could not resolve to a file

    I would appreciate your help.



  26. Fabrizio Iacopini said, on July 7, 2014 at 8:27 pm

    In my case the attached fonts (arial.ttf) is not renderer on my centos6.4 X86 i must change to another fonts.
    In addition without: putenv(‘GDFONTPATH=’ . $somepath) , the fonts is never read, and in my vhost configuration the ./data directory cannot be used for fonts reading, i don’t why . I can read/write log files for example in this directory but the fonts is never be read. Hope this helps other users

  27. John said, on July 8, 2014 at 9:38 pm

    thank you for the great example ..

    is there possible to show me how a refresh button .. if ever the user click refresh button .. only the image of the captcha change .

    • samsonasik said, on July 9, 2014 at 3:41 pm

      you can add manually, and apply getted data image into image element. there is ZendService\Recaptcha that automatically have refresh button.

      • John said, on July 14, 2014 at 12:30 pm

        ty for the reply sir .. ive already fix it

  28. oskar92013 said, on September 25, 2014 at 8:04 pm

    Great work, thanks🙂 It does the job perfectly in your example form, but when I implement it to another module the image could not load. Have I missed some thing!

  29. seyferx said, on September 27, 2014 at 1:00 pm

    How to delete old generated captcha images in data dir?

  30. Hamed Narimani said, on November 10, 2014 at 1:52 pm

    Hi. I have a problem with captcha. I did everything as you said. everything works perfect except browser refresh button. I mean when I use captcha for first time and post correct code, isValid function returns true and works correctly. The form comes up again after post action with a new captcha.Then if I resend old info via browser refresh button, isValid function returns true but captcha has changed and it is validating the old captcha. Am I missing anything here?
    I have created a stackoverflow question and a github issue in links below:

  31. babak faghihian said, on April 18, 2015 at 8:04 pm

    have a problem i load everything and captcha is showing correctly,but form->isValid() always is true even if i put unmatched character form is valid anyway what is no correct ?

  32. Jose said, on September 24, 2015 at 5:53 am

    OK, funciona a la perfección.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: