• Subscribe to the RSS feed!
  • Subscribe by Email
  • home
  • blog
  • dev
  • Recent Posts

    • Ubuntu Administrator
      • on January 6, 2009
    • Login example with Zend_Auth
      • on January 5, 2009
    • 2008: Moments worth a note
      • on December 27, 2008
    • Styling the default Zend_Form layout
      • on December 23, 2008
    • Data filtering with PHP’s Filter extension
      • on December 15, 2008
    • MyUrl view helper for Zend Framework
      • on December 2, 2008
    • One day for Human Rights
      • on November 26, 2008
    • LAMP and SVN on Ubuntu 8.10
      • on November 24, 2008
    • TickTweet WordPress plug-in
      • on November 21, 2008
    • School’s out!
      • on November 13, 2008
  • Recent Comments

    • vasim
      • on January 2nd @ 3:45 pm
    • Jonathan Kushner
      • on January 2nd @ 4:48 am
    • BradGman
      • on December 31st @ 4:16 am
    • gsx
      • on December 30th @ 4:07 am
    • Robert Kubica
      • on December 28th @ 6:45 pm
    • abtris
      • on December 27th @ 2:30 pm
    • Christian
      • on December 27th @ 12:35 am
    • Fernando Bittencourt
      • on December 26th @ 3:07 pm
    • Josh
      • on December 26th @ 7:13 am
    • gimly
      • on December 21st @ 5:29 pm
  • Friends and Blogs

    • Andrew Taylor
    • Bojan Pejić
    • Eran Galperin
    • Graham Smith
    • Matthew Weier O’Phinney
    • Nebojša Radović
    • Nemanja Avramović
    • Nikola Krajačić
    • Nikola Plejić
    • Pádraic Brady
    • Rob Allen
    • Swizec
    • WeAreJustCreative
  • I use

    • 960 Grid System
    • jQuery
    • Notepad++
    • Zend Framework
  • Tags

    • php
    • example
    • framework
    • zend
    • site
    • about
    • wordpress
    • ubuntu
    • random
    • introduction
    • apache
    • setup
    • linux
    • blog
    • lamp
    • mysql
    • comic
    • facebook
    • registration
    • virtualbox
  • Categories

    • Blablabla
    • Development
    • Free time
    • Places on the web
    • Programming
    • Software
  • Archives

    • January 2009
    • December 2008
    • November 2008
    • October 2008
    • September 2008

A Zend_Captcha example

by Robert Basic on October 22nd, 2008

Update: I made an error in the example code, regarding the CAPTCHA image URL. I’m sorry for any troubles caused by this mistake.

Update #2: Here’s an example of using Zend_Captcha without the whole Zend Framework stuff.

Update #3: There was an unintentional error in the captchaAction() method, Adam warned me about it in the comments. The error is fixed now. Thanks Adam.

OK, this was a bit tricky and I found no examples about it, so I thought to blog it. I’ll just show a quick example how to implement Zend_Captcha into a Zend_Form, may be useful for someone. There are several CAPTCHA types in ZF, like the Image, Figlet and Dumb. I use Image.

First of all, we’ll use sessions, so we need to change the bootstrap file a little:

// Put this line somewhere after the Zend_Loader::registerAutoload(); line
Zend_Session::start();

We need to start the session to use it, putting it close to the top will assure that there will be no “Headers already sent by…” errors caused by a wrongly placed session start.

Next we need a folder which has a 777 permission on it (Windows users, you can skip this… Or start using GNU/Linux) where we will put our captcha images for a while… This folder must be in the public folder somewhere. So create one.

How does this work? When a captcha is generated, it generates a unique ID (e.g. 539e517b0c0f4e32ef634dae92f07f77) and the word on the image. That unique ID is used for the file name of the image and for the session namespace (the namespace is like: Zend_Form_Captcha_uniqueId), so it knows which image belongs to which session. Also, the generated word is placed inside it’s own session. That ID is placed on the form in a hidden field, so when the submission is received, we can access the ID and recreate the correct session namespace and access the data in it: the word on the image.

Awesome. Now, to the fun part. I use the Zend_Form_Element_Captcha class, so no additional fooling around is needed to put the captcha in the form. Here’s the code:

public function indexAction()
{
// Our form object...
$form = new Zend_Form();
// And here's our captcha object...
$captcha = new Zend_Form_Element_Captcha(
        'captcha', // This is the name of the input field
        array('label' => 'Write the chars to the field',
        'captcha' => array( // Here comes the magic...
        // First the type...
        'captcha' => 'Image',
        // Length of the word...
        'wordLen' => 6,
        // Captcha timeout, 5 mins
        'timeout' => 300,
        // What font to use...
        'font' => '/path/to/font/FontName.ttf',
        // Where to put the image
        'imgDir' => '/var/www/project/public/captcha/',
        // URL to the images
        // This was bogus, here's how it should be... Sorry again :S
        'imgUrl' => 'http://project.com/captcha/',
)));
// Add the captcha element to the form...
$form->setAction('/index/captcha/')
        ->setMethod('post')
        // Add the captcha to the form...
        ->addElement($captcha)
        ->addElement('submit','Submit')
// Pass the form to the view...
$this->view->form = $form;
}

On the other side, it goes something like this:

public function captchaAction()
{
  $request = $this->getRequest();
  // Get out from the $_POST array the captcha part...
  $captcha = $request->getPost('captcha');
  // Actually it's an array, so both the ID and the submitted word
  // is in it with the corresponding keys
  // So here's the ID...
  $captchaId = $captcha['id'];
  // And here's the user submitted word...
  $captchaInput = $captcha['input'];
  // We are accessing the session with the corresponding namespace
  // Try overwriting this, hah!
  $captchaSession = new Zend_Session_Namespace('Zend_Form_Captcha_'.$captchaId);
  // To access what's inside the session, we need the Iterator
  // So we get one...
  $captchaIterator = $captchaSession->getIterator();
  // And here's the correct word which is on the image...

  $captchaWord = $captchaIterator['word']
  // Now just compare them...
  if($captchaInput == $captchaWord)
  {
  // OK
  }
  else
  {
  // NOK
  }
}

Easy, ain’t it?

Happy hacking :)

Tip: Using a monospace or a serif font for the words on the image (like FreeMono.ttf found by default on Ubuntu), makes the word quite unreadable — with the FreeMono.ttf about 8 out of 10 is UNreadable — so use a sans-serif font.

Share this post:
  • Digg
  • description
  • del.icio.us
  • StumbleUpon
  • Facebook
  • Reddit
  • TwitThis
  • Google
  • E-mail this story to a friend!
Tags: captcha, example, framework, php, zend.
Categories: Development, Programming, Software.
Subscribe to the feed.

Comments: 20

Grab the comments feed

  • Jani Hartikainen

  • October 23rd, 2008

Unless I’m mistaken, you could simply do $form->isValid($_POST) to check if the CAPTCHA element (and any other elements) in the form was valid or not. You would of course need to recreate the form, but you could probably delegate that to a method in the controller so you could easily use it in both actions.

  • Simple CAPTCHA Tutorial with Zend Framework | eKini: Web Developer Blog

  • October 24th, 2008

[...] 2008-10-24 This guy has an updated post for Zend_Captcha. Mine is old an [...]

  • Robert

  • October 24th, 2008

Hi Jani!

Yes, it can be done that way also, but I just wanted to show how the session can be recreated and the captcha validated “by hand”. Soon as I get some time, I’ll update the post to show the validation with the isValid() method also.

Thanks for the feedback :)

Regards,
Robert

  • Robert Basic’s Blog: A Zend_Captcha example : WebNetiques

  • October 24th, 2008

[...] and Zend_Form components of the Zend Framework “a bit tricky” and decided to share an example he’s come up with to help others out [...]

  • Robert Basic’s Blog: A Zend_Captcha example : Dragonfly Networks

  • October 24th, 2008

[...] and Zend_Form components of the Zend Framework “a bit tricky” and decided to share an example he’s come up with to help others out [...]

  • Links interesantes

  • October 29th, 2008

[...] A Zend_Captcha exaple - Robert Basic [...]

  • Mike

  • November 2nd, 2008

Hi,

nice example, how i can get the /var/www/project/public/captcha/ without hard coding if i only extends Zend_Form. i.e.

class Form_Message extends Zend_Form
{
public function init()
{
$captcha = new Zend_Form_Element_Captcha(
‘captcha’, // This is the name of the input field
array(’label’ => ‘Write the chars to the field’,
‘captcha’ => array( // Here comes the magic…
// First the type…
‘captcha’ => ‘Image’,
// Length of the word…
‘wordLen’ => 6,
// Captcha timeout, 5 mins
‘timeout’ => 300,
// What font to use…
‘font’ => ‘/path/to/font/FontName.ttf’,
// Where to put the image
‘imgDir’ => ‘/var/www/project/public/captcha/’,
// URL to the images
‘imgUrl’ => ‘/var/www/project/public/captcha/’,
)));
}
}

Thanks,

Mike

  • Robert

  • November 2nd, 2008

Hi Mike!

Sorry but I don’t understand what you want to do. What hard-coding?

  • Mike

  • November 3rd, 2008

Hi Robert,

many thanks for fast response. What i mean is that in Zend_Form_Element_Captcha it requires the path and file for font, imgDir and imgUrl. Is it possible that i can pass like a baseURL ($this->baseUrl) rather than hard-coded path (/var/www/project/public/captcha/). The class declartion i set was

class myForm extends Zend_form
{
public class init(){
// my form here with captcha
}
}

Thanks again,

Mike

  • Robert

  • November 3rd, 2008

Sure you can Mike!

Zend_Controller_Front::getInstance()->getBaseUrl() will get you the base URL.
You can also define the paths in some config file and load it from there.
I’m short on time so I just can give you where to look in the manual:
8.4.2.2. Base Url and Subdirectories
6.3. Zend_Config_Ini

Cheers!

  • Mike

  • November 3rd, 2008

Hi Robert,

many thanks, it works, $_SERVER['DOCUMENT_ROOT'] and Zend_Registry is fine with me

setAction(’/message’)
->setMethod(’post’)
->setName(’frmMessage’)
->setAttribs(array(’id’ => ‘frmMessage’, ‘onSubmit’ => ‘return validateMessage();’));

$name = new Zend_Form_Element_Text(’name’);
$name->setLabel(’Name’)
->setRequired(true)
->addValidator(’NotEmpty’, true)
->setValue(’Guess’)
->setDecorators(array(
‘ViewHelper’,
‘Description’,
‘Errors’,
array(’HtmlTag’, array(’tag’ => ‘div’)),
array(’Label’, array(’tag’ => ‘div’)),
));

$message = new Zend_Form_Element_Textarea(’message’);
$message->setLabel(’Message’)
->setRequired(true)
->addValidator(’NotEmpty’)
->setAttribs(array(’rows’ => ‘1′, ‘cols’ => ‘15′))
->setDecorators(array(
‘ViewHelper’,
‘Description’,
‘Errors’,
array(’HtmlTag’, array(’tag’ => ‘div’)),
array(’Label’, array(’tag’ => ‘div’)),
));

$captcha = new Zend_Form_Element_Captcha(
‘captcha’, // This is the name of the input field
array(’label’ => ‘Write the chars to the field’,
‘captcha’ => array( // Here comes the magic…
// First the type…
‘captcha’ => ‘Image’,
// Length of the word…
‘wordLen’ => 3,
// Captcha timeout, 5 mins
‘timeout’ => 300,
// What font to use…
‘font’ => $_SERVER['DOCUMENT_ROOT'] . ‘/captcha/times.ttf’,
// Where to put the image
‘imgDir’ => $_SERVER['DOCUMENT_ROOT'] . ‘/captcha/’,
// URL to the images
‘imgUrl’ => Zend_Registry::getInstance()->configuration->webhost . ‘/captcha/’,
)));

$captcha->setDecorators(array(
‘Description’,
‘Errors’,
array(’HtmlTag’, array(’tag’ => ‘div’)),
array(’Label’, array(’tag’ => ‘div’)),
));

$submit = new Zend_Form_Element_Submit(’submit’);
$submit->setLabel(’Submit’)
->setDecorators(array(
‘ViewHelper’,
‘Description’,
‘Errors’,
array(’HtmlTag’, array(’tag’ => ‘div’)),
));

$this->addElements(array($name, $message,
$captcha, $submit));
}
}

thanks,

Mike

  • Mussawir

  • November 26th, 2008

I am really thankful to you for this tutorial I have found it the best among all the tutorial published by any one including zend

  • HardCoder

  • December 16th, 2008

Good example!!!! A lot of thanx to you!!!!

  • Tutorial: Using Zend_Captcha_Image - SankhoMallik.com

  • December 17th, 2008

[...] best example I found was on Robert Basic’s Blog. My only gripe about it was that it used [...]

  • Adam

  • December 20th, 2008

Hey mate, nice tutorial.
Just wanted to let you know that on line 3 of the captchaAction() code snippet it ought to be
$request = $this->getRequest();
instead of
$request->$this->getRequest();

cheers.

  • Использование Zend_Captcha | Zend Framework по-русски

  • December 20th, 2008

[...] Если вы используете Zend_Form, то вам понадобится статья Zend_Captcha example, автор Robert Basic. В случае, если вы хотите использовать [...]

  • Robert

  • December 20th, 2008

Hi Adam!

Thanks for the heads up, fixed now :)

Cheers!

  • gimly

  • December 21st, 2008

Thanks alot - great tutorial! I got it running in no time.

  • gsx

  • December 30th, 2008

Robert thanks

But if I want to add more fonts and random generate it what should I do ?

  • BradGman

  • December 31st, 2008

A little confusing towards the end there …

Just to clarify Zend_Form’s built in isValid functionality will confirm the validity of captchas as well.

Leave a Reply

 

Robert Basic © 2009
Design & graphics by: Livia Radvanski
Coded by: Robert Basic
Home page last updated on January 3rd, 2009.
Frameworks used: Zend Framework, jQuery, 960 Grid System
Blog is powered by Wordpress
Subscribe: Entries — RSS & Comments — RSS