RSS
 
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.

Model

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.

Controller

The logic takes care of the validation on POST. /Controller/ContactController.php

<?php
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('Auth.User.id')) {
                $this->ContactForm->Behaviors->attach('Tools.Captcha');
            }
            $this->ContactForm->set($this->request->data);
            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

/View/Contact/index.ctp

<?php echo $this->Form->create('ContactForm');?>
    <fieldset>
        <legend><?php echo __('contactLegend');?></legend>
    <?php
        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('Auth.User.id')) {
            echo $this->Captcha->input('ContactForm');
        }
    ?>
    </fieldset>
<?php echo $this->Form->submit(__('Submit')); ?>
<?php echo $this->Form->end();?>

Result

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).

Tools Plugin – Part 2: Contact Form
3 votes, 4.67 avg. rating (92% score)
 
No Comments

Posted by Mark in CakePHP

 

Tags:

Leave a Reply

Tip:
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!