15. Dec. 2011

Tools Plugin – Part 2: Contact Form

15 Dec

I want to show how easy it is to make a solid and universal contact form in Cake(2).
The full code can be found in the github rep of the Tools plugin.


The most important part first: We need a solid validation for the form. How many forms are out there that do not have any validation. The first thing I always do on about any public contact form: Hit the submit button and smile it if tells me that my empty form "has just been successfully sent". We can do better than that 🙂

class ContactForm extends ToolsAppModel {
	protected $_schema = array(
		'name' => array('type' => 'string' , 'null' => false, 'default' => '', 'length' => '30'),
		'email' => array('type' => 'string' , 'null' => false, 'default' => '', 'length' => '60'),
		'subject' => array('type' => 'string' , 'null' => false, 'default' => '', 'length' => '60'),
		'message' => array('type' => 'text' , 'null' => false, 'default' => ''),
	public $useTable = false;
	public $validate = array(
		'name' => array(
			'notEmpty' => array(
				'rule' => array('notEmpty'),
				'message' => 'valErrMandatoryField',
				'last' => true

The _schema var mocks a database table so that we don’t really need one. This helps the FormHelper to generate the inputs (maxlength, type, …).
The validation rules will make sure the email is valid and the user actually entered some text.


The logic takes care of the validation on POST.

class ContactController extends AppController {
	public $uses = array('Tools.ContactForm');
	public function index() {
		if ($this->request->is('post') || $this->request->is('put')) {
			if (!$this->Session->check('')) {
			if ($this->ContactForm->validates()) {
				$name = $this->request->data['ContactForm']['name'];
				$email = $this->request->data['ContactForm']['email'];
				$message = $this->request->data['ContactForm']['message'];
				// send email with CakeEmail
			} else {
				// error flash message
		$this->helpers = array_merge($this->helpers, array('Tools.Captcha'));

As you can see it only sends emails after successfully validating.
For public contact forms I usually like some easy captcha behavior attached so that spam doesnt reach me. You can omit that, of course.
Also note: you should use your own setFlash() method instead of mine!

Last but not least: View


<?php echo $this->Form->create('ContactForm');?>
		<legend><?php echo __('contactLegend');?></legend>
		echo $this->Form->input('name');
		echo $this->Form->input('email');
		echo $this->Form->input('subject');
		echo $this->Form->input('message', array('rows'=>15));
		if (!$this->Session->read('')) {
			echo $this->Captcha->input('ContactForm');
<?php echo $this->Form->submit(__('Submit')); ?>
<?php echo $this->Form->end();?>


Browse to /contact/
That should display the form right away.
After the successful POST you should redirect back to the contact form (emptied then) or to another custom page.

Final notes

Currently, the Model is in the Tools.Plugin. You could put it into your normal app model folder, as well.
But I use it in many projects and therefore I want to keep it dry. Feel free to adjust any of the code to your own needs. Same goes for my own custom methods like $this->Common->flashMessage() etc.

Some might wonder why "ContactController" and not "ContactsController". The latter would be cake conventions. But there are situations where you can and should diverge form those. As in this case where "contacts" would mean more like sth to manage your addressbook. It also makes the url more meaningful out of the box (without any custom routes). With cake2 this all works without any additional customization.

The other thing: I didn’t name the Model "Contact" but "ContactForm" in order to not create possible conflicts which exactly such contacts/contact mangement MVCs (as I did in a contact management suite).

4.75 avg. rating (93% score) - 4 votes

Posted by Mark in CakePHP



Leave a Reply

If you need to post a piece of code use {code type=php}...{/code}.
Allowed types are "php", "mysql", "html", "js", "css".

Please do not escape your post (leave all ", <, > and & as they are!). If you have encoded characters and need to reverse ("decode") it, you can do that here!

  1. Adam

    June 4, 2013 at 08:30

    Thankyou for this tutorial, how do I go about styling the Captcha labels? It’s coming though with captchaExplained and then captchaTip after the field.


  2. Alain

    August 6, 2013 at 12:51


    Wen a form is sent and its content is not valid, when you re display the form, fields are not filled with the content use when the form was submited.

    Is there a reason for this ?

  3. Mark

    August 6, 2013 at 12:55

    Jep, then your code is wrong.
    Because – doing it the right way – the form will keep the information you posted.
    Without more information I cannot tell you, though, what exactly you are doing wrong there.

  4. Jian Zhan

    November 27, 2013 at 16:00

    Hi Mark,

    When I click submit and nothing happen.

    I guess your tools is not compatible with Cakephp 2.4.1

    Or I did something wrong?

    I just followed your instruction step by step.

    Jian Zhan

  5. Jian Zhan

    November 27, 2013 at 16:00

  6. Mark

    November 27, 2013 at 16:07

    a) its /contact (lowercase c)
    b) its compatible with all 2.4 and 2.5 versions. you seem to miss the HTML5 validation going on there. disable it if unneeded.

  7. Jian Zhan

    November 28, 2013 at 03:55

    ONLY does work.
    What’s wrong with my setup? does not work.

    How to disable HTML5 validation?

    Error: Contact.ContactController could not be found.
    Error: Create the class ContactController below in file: /home/content/95/4770795/html/PolarLamp/cakephp/plugins/contact/Controller/ContactController.php
    class ContactController extends ContactAppController {

    Notice: If you want to customize this error message, create PolarLamp/View/Errors/missing_controller.ctp

  8. Jian Zhan

    November 28, 2013 at 03:59 does work.

    But when I click submit and nothing happen.

    How to disable HTML5 validation?

    Jian Zhan

  9. Jian Zhan

    November 28, 2013 at 23:40

    Ho do I use your Captcha in my controller?

    I checked your previous post spmewhere:
    or alternately for all actions in one controller via model:
    var $actsAs = array(‘Captcha’);


    Jian Zhan

  10. luatnguyen

    January 10, 2014 at 12:05

    How to use Bootstrap with your tools?