Creating a Contact Form in CakePHP 1.2
Most contact forms take a name and feedback from a user and mail it off to the administrator but don't store any information in the database. This tutorial will show how to use CakePHP's models, even when no table is being used.
CakePHP is great in that you set up a database table, define an empty class file for the Model and suddenly you're halfway there. The Form helper can automatically display error messages and outputs the proper input type depending on the field data type.
However, what do you do when you don't have a database table, as is the case with our contact form? We look to the model property, _schema
. Normally this is automatically populated by CakePHP when it figures out what the database says. With no database table, you have to define the schema by hand.
Here's an example schema for our contact form:
class Contact extends AppModel {
var $useTable = false;
var $_schema = array(
'name' =>array('type'=>'string', 'length'=>100),
'email' =>array('type'=>'string', 'length'=>255),
'details' =>array('type'=>'text')
);
}
As you can see, we've told the model not to use a table by setting useTable
to false. Then, we define the schema for the table. In this case, we're going to ask the site visitor to fill out name, email, and contact details.
With the schema defined, we can also specify some validation rules to go along with that:
var $validate = array(
'name' => array(
'rule'=>array('minLength', 1),
'message'=>'Name is required' ),
'email' => array(
'rule'=>'email',
'message'=>'Must be a valid email address' ),
'details' => array(
'rule'=>array('minLength', 1),
'message'=>'Feedback is required' )
);
With the model now set up and ready to go, setting up the view is a piece of cake:
<?php
echo $form->create('Contact');
echo $form->inputs();
echo $form->end('Send');
?>
Then, all we have to do is set up our controller to do something.
function add() {
if ($this->RequestHandler->isPost()) {
$this->Contact->set($this->data);
if ($this->Contact->validates()) {
//send email using the Email component
$this->Email->to = 'admin@example.com';
$this->Email->subject = 'Contact message from ' . $this->data['Contact']['name'];
$this->Email->from = $this->data['Contact']['email'];
$this->Email->send($this->data['Contact']['details']);
}
}
}
And that's it! The process for the contact form, validating and sending emails hasn't changed. All we had to do was define the schema to be able to take advantage of our model validation.
Conversation
Great tutorial!
Does this mean that, as long as one is not doing anything "weird" in a form, you don't need to put every field?!?
When did this happen?
@Walker: hehe, you like that, eh? Somewhere in the 1.2 stuff, it got in there. Pure genius (and I used it to show off just how easy the form helper can be).
Pure.
Completely Pure.
Darn...I really need to re-bake my applications between each release to see the new changes. Thanks for that information on the form helper's new method, Jonathan! I've seen $_schema in my debug output too, but didn't realize what it was exactly, so that part's also very useful. Thanks a bunch!
Man, you really rock JSnook. I was never aware of that $form->inputs() function. Great tutorial dude. CakePHP is freakin awesome.
Hi,
many thanks about this tip, but you forgot to 'echo' the '$form->' in the views.
T+
@byBartus: good catch. fixed.
Hi Jonathan:
You should try Kohana as well. (www.kohanaphp.com)
Today I was doing a contact form too. And was surprisingly easy
In the controller:
In the View:
I just love it. Its like jQuery
WoW... It's great, I've been working with cake about 6 months and it's very great, but I don't migrate to 1.2 yet.
@Jonathan do you think CakePHP 1.2 is stable sufficiently to use on a serious web project?
Thanks for share.
Do you additionally use the Security component to secure the form or do you find the $this->RequestHandler->isPost() is sufficient ? I guess this question also applies in general to other forms as well e.g. Comments, was just curious.
Thanks for the insight into $from->inputs() hadn't seen that yet, is there a nice way when using that method to also customize the labels ?
Nice! Thnx Jonathan!
@Pablo: The syntax for Kohana seems really interesting. It's nice to see other frameworks taking the simplicity approach.
@Juarez: Yes, CakePHP 1.2 is definitely stable. They're onto release candidates with a final version likely out within the month.
@Brett Wilton: No, I don't use the Security component. I'm okay with just ensuring that it's a post request.
This is so cool, CakePHP rocks!!
This is great. I just needed something quite similar for my app. Thanks alot!
Just in case I've missed some other auto magic features in 1.2, is there an auto magic means of setting custom input labels when using the $from->inputs() method ?
I have been aware of Cake for some time, but this is the first time I've seen any code examples. I have been thinking about doing something similar in PHP for some time where all the details for the form are stored in an XML file, which configures a controlling class. All you need to do is write and ref. the XML and its done.
Is the textarea field named 'feedback' or 'details'? Seems like you are using both.
I've been reading up on different frameworks for a while and recently noticed what seems to be a misunderstanding/misuse of the View portion of the MVC pattern.
@Pablo: It seems wrong to me that the Controller, with respect to the MVC pattern, should have the ability to define the content and structure of the View. To me, this violates the separation of logic layers by which the View should define itself.
I found the same inherent problem in the Zend Framework. Perhaps i'm missing something, but i'm surprised to see it in Big-Name frameworks like Zend. Does anyone want to explain their perception of this?
@Snook: It also seems wrong to me that the CakePHP Model is *assumed* to be database driven, and therefore you have to specifically tell it *not* to connect to a database table.
Do you have any comments on this behavior?
@Brett Wilton: If you declare the field names, you can declare custom labels with them. Like,
$form->inputs(array('name'=>array('label'=>'My name')))
@Orhan: you're correct. A typo in the middle there which I've now corrected. Thanks!
@Eric (1): Zend in particular is a framework that can be used for MVC but wasn't built specifically as an MVC framework. I haven't looked too closely but last time I remember, their CakePHP or Code Igniter equivalent was pretty loose.
@Eric (2): CakePHP has a similar "convention over configuration" mindset as Ruby on Rails and the fact is, it's built for the 80% of apps which are database driven. It's about solving the common goal, not about some strict adherence to a methodology. Of all the apps I've built with CakePHP, 98% of the controllers have needed a database table association. I like CakePHP for automating that.
Thanks for the response,
@Snook (1): You're right, I went to find something which stated the Zend Framework was designed specifically as an MVC framework, but couldn't find it. I still think its strange that they implement the MVC pattern (in the tutorial i'm referring to here: http://akrabat.com/zend-framework-tutorial/) and seemingly devalue the concept of independent logic layers.
@Snook (2): I definitely appreciate the "convention over configuration" philosophy - I employ it constantly. I question why the CakePHP Model doesn't skip loading table data until a database request is made. For example:
... looks like "configuration" to me. This could easily be avoided in the spirit of "convention":
... should be the only code needed to accomplish this, and even that could be simplified.
I guess this is relatively minor in retrospect, but it's part of what keeps me from using CakePHP and Zend frameworks. Ruby On Rails seems to have more correctly adopted this philosophy, though, I'm not a Ruby programmer. CakePHP seems like the best of the available PHP frameworks anyway.
Wow Snook! Clean. I remember chating with you on IRC a month or so ago about this subject. You really discovered a slick solution. Kudos to you and anyone else who helped come up with this solution.
This is a great tutorial and clean solutions. I certainly like the convention over configuration philosophy in CakePHP. One of the most powerful features is the relational mapping provided by the model, and CakePHP is furthermore awesome for automating.
Btw, why CakePHP? Can you explain your chooice? Thanks.
Alexei: I chose CakePHP because I felt it was the PHP framework that best took the "convention over configuration" approach. I've been very happy with the features and feel that it ultimately saves me time in developing applications (and more so than any other framework I've tried so far).
Thanks for tutorial - great job :) On my own I would spend a few hours above it
I'm trying out CakePHP. Thanks for the nice tutorial !
Smart! Didn't knew about the $_schema property! Simple and useful!
Maybe a bit offtopic. But I always save contactform data also in the database. Because I had some clients complaining about lost emals and such. Also it's so damn easy in Cake :)
thanks for the tuto,
I am a beginner and have a error :
Call to a member function isPost() on a non-object
What's wrong ? I did a copy/past of your code
Tom: the example uses the RequestHandler component to check if it's a post request. If you don't use the RequestHandler, you can check for the existence of $this->data or there's a server variable (if I remember correctly) that you can use to check that it's a POST request.
$_SERVER['REQUEST_METHOD']
I think.Thank you, but can you just tell me how can I use RequestHandler. I checked the file on the directory cake » libs » controller » components and I have it.
OK, I put a declaration of the components and It seems to be OK. But I don't receive the email when I check on my development environnement, is it normal ?
I tried in a production mode, and it's work, OK
great article
Thanks for this tutorial :) It's work
Thanks for the tute, Jonathan.
I'm new to PHP and Cake. I'm wondering what the code you provided would look like if it were modified to allow the user to select (from a select list) who the e-mail is sent to, rather than just 'admin@example.com'. Eg: john@example.com, barry@example.com, danny@example.com, etc.
And what if the user wanted to choose a subject title from a list, like 'Sales', 'Orders', 'Support', 'Website', etc?
Great tutorial - it was very helpful for me :)
Thanks for this, I just looking for thath
Hi,
thx for sharing that :).
I've one question about this piece of code :
Do you know any solution to display something else than the "name field" as a "<label>", witch is sometime not very friendly ?
Best regards
François
sorry for my english :)
You can specify the fields manually and then declare the label on any specific field.
It's all work :) Thanks
I just looking for this. Thanks.
I was googling around looking for a howto about cake's forms, and I found your great site.
I am taking a look at cake 1.2, and I run into problems with the validation of form data. I took advantage of the console application to bake some views, a model, and a controller based on an existing MySQL-database. I don't yet have a deep understanding of cake, and would happily welcome hints and pointers which direction I should go.
All fields are considered invalid and the validation fails whatever data I use to fill in the form. I verified that the correct data from the form are assigned to the controller object's data array with Configure::write('debug', 3); The view contains code to evaluate the validation: pr($this->validationErrors);
PHP version: 5.1.6
OS: Linux
CakePHP version:
$Id: VERSION.txt 7692 2008-10-02 05:06:48Z nate $
libs/model/model.php version:
$Id: model.php 7690 2008-10-02 04:56:53Z nate $
It's hard to say exactly what you might be running into without seeing the code (maybe paste it to a bin). Are you trying to validate() the code? If so, remember to set the data to the model like I've done in the article (
$this->Contact->set($this->data)
).I am trying to post data from a form to a database. However, whatever data I post, I get redirected back to the form, where a label "This field cannot be left blank" is attached to all fields. For instance if I fill the alphanumeric field "last_name" with "Jones" (without qoutes), I will get the error message: "This field cannot be left blank". Futhermore, $this->validationErrors contains all fields and the same error message.
The view is just a simple form like:
echo $form->create('Lead');
echo $form->input('last_name');
echo $form->input('modified_user_id');
... quite a few more fields here ...
echo $form->end('Submit');
There are also a few form fields added with pure html code. These fields are not supposed to be posted to the database, neither be validated with the standard cake validation feature.
In the model, there is nothing but "name" and the validation array.
The model's validation array looks like:
var $validate = array(
'last_name' => array('alphanumeric'),
'modified_user_id' => array('alphanumeric'),
--- quite a few more fields here ---
)
The controller's add function:
function add() {
if (!empty($this->data)) {
if ($this->RequestHandler->isPost()) {
$this->Lead->create();
$this->Lead->set($this->data);
if ($this->Lead->save($this->data)) {
$this->Session->setFlash(__('The Lead has been saved', true));
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash(__('The Lead could not be saved. Please, try again.', true));
}
}
}
}
I also tried the following code in the controller: if ($this->Lead->validates()) with the same result.
Nothing instantly jumps out at me. Sorry I can't be of more help. Try posting to the CakePHP Google Group if you haven't already.
how to create of confirmation form(with back button) in cakephp for a contact form with database,
Wow.. great tutorial, big help on my project. keep up the good work man..
Thanks..
Joseph P. Buarao
Web Developer
Azure Web Design
Hello! caegdde interesting caegdde site!
Very nice site!
Hello, I am sorry, I have acode:
echo $form->create('Message', array(
'url' => array(
'controller' => 'contacts',
'action' => 'view',
$contact['Contact']['alias'],
),
));
But I can't understand, can you help me, thank you very much.