Chapter 9[ 215 ] Adding Forms to Add New Questions and Answers With our application, we can view all the questions, we can view all the answers to a question, and we have even added a co
Trang 1Chapter 9
[ 215 ]
Adding Forms to Add New Questions and Answers
With our application, we can view all the questions, we can view all the answers to
a question, and we have even added a cool layout for our application But we still cannot do a very important task We still cannot add a new question or add a new answer That is exactly what we are going to do in this section We are going to add a form to the home() action that will be able to add a new question to Quickwall And
to add a new answer, we will also be adding a new form to the show() action So, without any delay, let's go and see how to do that
Time for Action
1 Since we will be using the home() action for both displaying all the questions and also to add a new question, add the following code to the home() action
of the Questions controller:
function home() {
if (!empty($this->data)) { $this->Question->create();
if ($this->Question->save($this->data)) { $this->Session->setFlash('Your Question has been added'); $this->redirect(array('action'=>'home'), null, true); } else {
$this->Session->setFlash('The Question could not be saved Please, try again.'); }
}
<?php e($form->create('Question', array('action' => 'home')));?> <fieldset>
<label for="QuestionQuestion" class="questionlabel">
<span>Your Question</span></label>
<?php e($form->text('question', array('class' =>
'fullwidth'))); ?><span class="big">?</span> <label for="QuestionQuestioner" class="questionerlabel"><spa
Trang 2Making Quickwall: The Basics
if(!$answer_count) e("(no answers yet)");
else if($answer_count == 1) e("(1 answer)");
else e("(".$answer_count." answers)");
3 The show() action is used to display a question and its answers We will also
be using it to add a new answer to question Add the following code to the
show() action of the Questions controller:
function show($id = null) {
if (!$id) { $this->Session->setFlash('Invalid Question.');
$this->redirect(array('action'=>'home'));
}
if (!empty($this->data)) { $this->Question->Answer->create();
if ($this->Question->Answer->save($this->data)) {
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 3Chapter 9
[ 217 ]
$this->Session->setFlash('The Answer has been saved'); $this->redirect(array('action' => 'show', $id), null, true);
} else {
$this->Session->setFlash('The Answer could not be saved Please, try again.'); }
<?php e($form->hidden('question_id', array('value' => $question['Question']['id']))); ?> <label for="AnswerAnswer" class="questionlabel"><span>Your Answer</span></label> <?php e($form->text('answer', array('class' =>
'fullwidth'))); ?><span class="big">!</span> <label for="AnswerAnswerer" class="questionerlabel"><span> Your Name</span></label> <?php e($form->text('answerer', array('class' =>
'halfwidth'))); ?> <?php e($form->submit('Post Your Answer', array('div' => false, 'class' => 'submitbutton'))); ?> </fieldset>
<?php e($form->end()); ?>
<?php if(empty($question['Answer'])): ?>
<p class="no_answer">No Answers yet Be the first one to answer!</p> <?php else: ?>
Trang 4Making Quickwall: The Basics
[ 218 ]
5 Now let's add validation rules so that users cannot enter empty questions and answers Open the Question model in your text editor, and add the following validation rules:
<?php class Question extends AppModel { var $name = 'Question';
var $hasMany = array(
'Answer' => array(
'className' => 'Answer' )
);
var $validate = array(
'question' => array(
'rule' => array('minLenght', 1), 'required' => true,
'allowEmpty' => false, 'message' => 'Question cannot be empty' ),
'questioner' => array(
'rule' => array('minLenght', 1), 'required' => true,
'allowEmpty' => false, 'message' => 'Please enter your name' )
);
} ?>
6 If there are any validation errors, we should show an error message to the user To do so, add the following code to /quickwall/app/views/questions/home.ctp:
<?php e($form->error('Question.question', null, array('class' => 'message'))); ?> <?php e($form->error('Question.questioner', null, array('class' => 'message'))); ?>
<?php e($form->create('Question', array('action' => 'home')));?> <fieldset>
<label for="QuestionQuestion" class="questionlabel"><span> Your Question</span></label>
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 5=> 'halfwidth'))); ?> <?php e($form->submit('Post Your Question', array('div' => false, 'class' => 'submitbutton'))); ?> </fieldset>
<?php e($form->end()); ?>
<?php if(empty($questions)): ?>
<p class="no_answer">No Questions yet Be the first one to post
a Question!</p> <?php else: ?>
<dl>
<?php foreach ($questions as $question): ?>
<dt><span><?php e($question['Question']['questioner']); ?></span></dt> <dd>
<?php e($html->link($question['Question']['question'] '?', '/questions/show/'.$question['Question']['id'])); ?> <?php
$answer_count = count($question['Answer']);
if(!$answer_count) e("(no answers yet)");
else if($answer_count == 1) e("(1 answer)");
else e("(".$answer_count." answers)");
var $belongsTo = array(
'Question' => array(
'className' => 'Question' )
Trang 6Making Quickwall: The Basics
'allowEmpty' => false, 'message' => 'Answer cannot be empty' ),
'answerer' => array(
'rule' => array('minLenght', 1), 'required' => true,
'allowEmpty' => false, 'message' => 'Please enter your name' )
);
} ?>
8 Add similar code as step 6 to /quickwall/app/views/show.ctp, to show validation errors:
<?php e($form->error('Answer.answer', null, array('class' => 'message'))); ?>
<?php e($form->error('Answer.answerer', null, array('class' => 'message'))); ?>
=> 'fullwidth'))); ?><span class="big">!</span>
<label for="AnswerAnswerer" class="questionerlabel"><span>
Your Name</span></label>
<?php e($form->text('answerer', array('class'
=> 'halfwidth'))); ?>
<?php e($form->submit('Post Your Answer', array('div'
=> false, 'class' => 'submitbutton'))); ?>
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 8Making Quickwall: The Basics
[ 222 ]
What Just Happened?
In step 1 of this section, we changed the home() action of the Questions controller,
to add the functionality to save a new question if submitted to it If any data is submitted to the request, Cake will store the POST data into $this->data So,
if $this->data is not empty, the first thing that is done is to call the create()
method of the Question model This prepares the model to save new data Then the
save() method is called and $this->data is passed to it This saves the data into the database If the operation is successful, a message is saved into the session, and redirected to the home() action The message is then showed to the user
Next, in step 2, we change the view of the home() action, to add the form This form will be used to insert new question, so it is related to the Question model To bind the form with the Question model, we use the Form helper of CakePHP A form
is created by calling the create() function of the Form helper Two parameters are passed to it: the name of the model to bind, and the name of the action to post the data to Note that the action name is passed in an array; any other required parameter can be passed through this array To create a text input that will be
used to insert the question, we use the text() method of the Form helper Two parameters are passed to it, the name of the field that will be inserted through it, and
an array that contains other options In this case, we passed the name of the class that this text input should use for styling Similarly, we use another call, the text()
function of the Form helper to create the text input to insert the questioner To create
a submit button, we use the submit() function of the Form helper Lastly, we call
$form->end() to close the form
Similarly, in step 3 and 4, we create a form in the show() action to insert a new answer To get a more clearer idea of what the Form helper creates, check out the source of the HTML that is generated An important thing to understand here is how we access the Answer model By default, a controller only loads the model that has the singular name of the controller So, the Questions controller will load the
Question model by default But we can also access other models that are related
to the loaded model For example, since the Question model is loaded, and it has
hasMany relationship with the Answer model, we can access the Answer model by the call $this->Question->Answer
Next in step 5, we add validation rules for the Question model If no validation rules are added, users can submit the form empty, and the empty data will be saved as a new question This is something that we do not want To make sure the user cannot enter empty question or name, we add two validation rules to the Question model All validation rules for a model must be added in an array named $validate In the validation array of Question model, we add two validation rules, one for each field: question and questioner Both have similar rules applied The minimum length of both must be 1, they both are required fields, and none of them can be empty
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 9Chapter 9
[ 223 ]
The validation rule defined above will not allow to save data that will not pass the validation rule To show the error messages, in step 6, we added two lines to the view of the action Again, we use the Form helper to do so The error() function of the Form helper shows the error message of a particular field if there is any We use this function to show an error message if an error is present
Similarly in step 7 and 8, we add validation rules for the Answers model
Summary
This was the first chapter of section C, which took us through all the effort that it takes to make a complete CakePHP application Through out this section we saw how to enhance and build an application that we called Quickwall We started the chapter by understanding what Quickwall is all about After quickly setting up Cake for Quickwall, we went through the process of creating and connecting the Quickwall database with the application We then created two models, and defined relationship between them After that, we created the controller actions and their corresponding views Adding custom layout was the natural next step We saw how
we can add our own layout and styles to Cake applications We discussed the basics
of how to add layouts and how views get rendered into them Also discussed was how we can add CSS files to Cake applications We ended the chapter, by adding forms to insert new data The Form helper was used extensively, and we saw how
it helped to bind models with forms Adding validation rules to models were also discussed, along with how to show error messages if there is a validation error.All in all, this chapter went through the creation of a simple but functional web application In the following chapters, we will extend this application by adding more useful functionalities to it And, in the process, we learn how easy and quick it
is to make a web application using CakePHP Read on!
Trang 11Quickwall: User Authentication
In the last chapter, we managed to make a very simple version of Quickwall Though
it was simple, it was a working web application that made it quite usable More importantly, it will be the base from where we can add more functionalities to it
In this chapter, we are going to add user authentication to our Quickwall
User authentication is something that is needed in almost all web applications
And whether you like it or not, you have to spend time to make sure the user
authentication system is working properly It is also one of the most important aspect
of any web application, because a lot of other functionalities depend on it
We will see in this chapter, that adding user authentication in CakePHP, like many other stuff, is very easy and quick So without any delay, let's see the things that we are going to do in this chapter:
Create the User ModelBuild a simple user sign-up processAdd email activation to sign upIntegrate the Authenticating process into the applicationRemembering user with cookie
Trang 12Quickwall: User Authentication
in the database After that, we are going to create the User model, along with some validation We are also going to create the skeleton of the Users controller
Time for Action
1 Create a table in our quickwall database with the name users Use the following SQL to do so:
CREATE TABLE users (
id INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , username VARCHAR( 255 ) NOT NULL ,
password VARCHAR( 40 ) NOT NULL , email VARCHAR( 255 ) NOT NULL , created DATETIME NOT NULL , modified DATETIME NOT NULL );
2 Next, we create a corresponding model for this table In the /app/models
directory, we need to create a file named user.php, with the following code inside:
<?php class User extends AppModel { var $name = 'User';
} ?>
3 We do not want an empty username and password to be saved Also, we would like to make sure that the email entered is a valid email For this purpose, we add the following validation code to the User model:
<?php class User extends AppModel { var $name = 'User';
var $validate = array(
'username' => array(
'rule' => array('minLenght', 1),
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 13Chapter 10
[ 227 ]
'required' => true, 'allowEmpty' => false, 'message' => 'Please enter a user name' ),
'password' => array(
'rule' => array('minLenght', 1), 'required' => true,
'allowEmpty' => false, 'message' => 'Please enter a password' ),
'email' => array(
'rule' => 'email', 'required' => true, 'allowEmpty' => false, 'message' => 'Please enter a valid email' )
);
} ?>
4 Now, let's create the Users controller In the /app/controllers directory, create a file with the name users_controller.php, and add the following code to it:
<?php class UsersController extends AppController { var $name = 'Users';
} ?>
5 To test if our User model and its validation rules are working properly, let's scaffold and check To do so, add the following line into the Users controller:
<?php class UsersController extends AppController { var $name = 'Users';
var $scaffold;
} ?>
6 Make sure we clear the cache To clear the cache, go to the directory /app/tmp/cache There are three directories named models, persistent, and
views Delete all the files in these three directories
Trang 14Quickwall: User Authentication
[ 228 ]
7 Now to check the validation rules, point the web browser to
http://localhost/quickwall/users/add We will see a page as shown
in the following screenshot Try giving empty user name, password, and invalid emails, to check
What Just Happened?
In this section, we first added the users table into our quickwall database The fields that were included were: id, username, password, email, created, and
modified Every user who will be added to the application will have a unique id The username will be the name that will be used through out the app to identify the user This will also be a unique value The email field will contain the email address
of the user We will be using this later to send email notification to the user And as usual, the created field will record the time when the user account was created The
modified field will record the time when the account was last modified
Next, we added the User model This model will automatically represent the users table in the database, as per Cake's convention We went on adding validation rules for username, password, and email For username and password, we do not want them to be empty So, we used the built-in validation rule minLenght(), and
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 15up the cache, after any changes, or sometimes it may result in some unexpected and weird issues We used the Users controller to check whether the model and its validation rules were working fine For this, we used scaffolding To make a controller use scaffolding, the only thing that we need to do is to add the line var
$scaffold; into the controller Lastly, we tested the model by using scaffolding
Making the User Sign Up Process
In this section, we are going to create the process by which a user can sign up to Quickwall We will start by creating an action in the Users controller that will handle the sign-up of a new user We will then move to create its view The sign-up process will also require the use of special validation rules for situations such as to check if the username is unique, and the re-entered password is similar to the first one This section will also see the use of the Auth component The Auth component is a
built-in component of CakePHP that makes the process of authenticating very simple and easy Lastly, we will configure the Cake router to make more meaningful URL for the sign-up process
Time for Action
1 First, let's remove the scaffolding option that we added at the end of the last section
2 Next, we will need to add the Auth component to the Users controller To do
so, add the following line to the Users controller:
<?php class UsersController extends AppController { var $name = 'Users';
var $components = array('Auth');
} ?>
Trang 16Quickwall: User Authentication
[ 230 ]
3 After adding the Auth component, let's add an action named signup into the
Users controller Add the following code to the action:
<?php class UsersController extends AppController { var $name = 'Users';
var $components = array('Auth');
function signup(){
if (!empty($this->data)) { if(isset($this->data['User']['password2'])) $this->data['User']['password2hashed'] = $this-> Auth->password($this->data['User']['password2']); $this->User->create();
if ($this->User->save($this->data)) { $this->Session->setFlash('Congratulations! You have signed up!'); $this->redirect(array('controller' => 'questions', 'action'=>'home')); } else {
$this->Session->setFlash('There was an error signing
up Please, try again.'); $this->data = null;
} } }
} ?>
4 We will then need to add a function called beforeFilter() to the Users
controller Add the following code to this function:
<?php class UsersController extends AppController { var $name = 'Users';
var $components = array('Auth');
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com