Day 10-use Ajax forms to modify data

Source: Internet
Author: User
Tags php foreach php template
Through yesterday's review of known technologies, we are already familiar with the use of interaction. Displaying the problem and list of rich formats, or even pagination, is not enough to make a program alive. The core of askeet is to allow any registered user to ask a new question, and any user can answer an existing question. Now is the time for implementation.

Add a new question

The Sidebar we created on the seventh day contains a link to add a new question. It links to the question/Add action, which is exactly what we will develop.

Restrict access to registered users

First, only registered users can add a new question. To restrict access to the question/Add action, create a security. yml file in the askeet/apps/frontend/modules/question/config/directory:

Add:
Is_secure: On
Credentials: subscriber

ALL:
Is_secure: Off

 
When a non-registered user tries to access a Restricted action, symfony redirects it to the login action. This action must be defined in the program settings, after the keyword login_module and login_action:

ALL:
. Actions:
Login_module: User
Login_action: Login

For more information about the limits of Action access, see the security chapter in symfony.

Addsuccess. php Template

The question/Add action displays both the form and Processing Form. This means that to display the form, we only need an empty action. In addition, if a form verification error occurs, the form is displayed again:

Public Function executeadd ()
{
}
 
Public Function handleerroradd ()
{
Return sfview: success;
}

All actions will output the addsuccess. php template:

<? PHP use_helper ('validation ')?>
 
<? PHP echo form_tag ('@ add_question')?>
 
<Fieldset>
 
<Div class = "form-row">
<? PHP echo form_error ('title')?>
<Label for = "title"> question title: </label>
<? PHP echo input_tag ('title', $ sf_params-> get ('title')?>
</Div>
 
<Div class = "form-row">
<? PHP echo form_error ('body')?>
<Label for = "label"> your question in details: </label>
<? PHP echo textarea_tag ('body', $ sf_params-> get ('body')?>
</Div>
 
</Fieldset>
 
<Div class = "Submit-row">
<? PHP echo submit_tag ('Ask it')?>
</Div>
</Form>

Both the title and body controls have a default value (the second parameter of the form helper), and its value is defined by the form parameter of the request. Why? Because we need to add a verification file for the form. If verification fails, the form is displayed again, and the preceding user entity is still in the request parameters. They can be used as the default values of form elements.

The preceding entity is not lost because form verification fails. This is our minimum requirement for a user-friendly program.

However, for this purpose, we need a form verification file.

Form Verification

Create a validate/directory under the question module and add an add. yml verification file:

Methods:
Post: [Title, body]

Names:
Title:
Required: Yes
Required_msg: You must give a title to your question

Body:
Required: Yes
Required_msg: You must provide a brief context for your question
Validators: bodyvalidator

Bodyvalidator:
Class: sfstringvalidator
Param:
Min: 10
Min_error: Please, give some more details

If you want to learn more about form verification, go back to 6th days or read the Form Verification chapter in symfony.

Process Form submission

Now edit the question/Add action to process form submission:

Public Function executeadd ()
{
If ($ this-> getrequest ()-> getmethod () = sfrequest: Post)
{
// Create Question
$ User = $ this-> getuser ()-> getsubscriber ();
 
$ Question = new question ();
$ Question-> settitle ($ this-> getrequestparameter ('title '));
$ Question-> setbody ($ this-> getrequestparameter ('body '));
$ Question-> setuser ($ user );
$ Question-> Save ();
 
$ User-> isinterestedin ($ question );
 
Return $ this-> redirect ('@ question? Stripped_title = '. $ question-> getstrippedtitle ());
}
}

Remember, the-> settitle () side will also set stripped_title, while the-> setbody () method will also set the html_body field, because we are in question. these two methods are rewritten in the PHP module class. Users who create problems will be declared interested. This is to avoid problems that no one is interested in. It is so sad.

The action end contains a-> redirect () method to redirect to the detailed page for creating a problem. Compared with the-> forward () method, the biggest advantage is that if you refresh the detailed problem page later, the form will not be submitted again. In addition, the 'back' button also works as expected. This is a common rule: we do not use the-> forward () method to end the form submission processing action.

It is best if the form is not in post mode, the action can still display the form. It is like the empty action we wrote earlier. Return sfview: success and start the addsuccess. php template.

Do not forget to create the isinterestedin () method in the user module:

Public Function isinterestedin ($ question)
{
$ Interest = new interest ();
$ Interest-> setquestion ($ question );
$ Interest-> setuserid ($ this-> GETID ());
$ Interest-> Save ();
}

As a refactoring, we can use this method in the user/interested action to replace the code for the same thing. Now you can perform the test. To use a test user, we can add a question.

Add a new answer

The answer is added in a slightly different way. There is no need to use a form to redirect users to a new page, but to another page to display the answer. Therefore, the new answer form should be in Ajax format, and the new answer should be immediately displayed on the question details page.

Add an Ajax form

Use the following code to change the end of the modules/question/templates/showsuccess. php template:

...
<Div id = "answers">
<? PHP foreach ($ question-> getanswers () as $ answer):?>
<Div class = "Answer">
<? PHP include_partial ('answer/answer', array ('answer' => $ answer)?>
</Div>
<? PHP endforeach;?>
 
<? PHP echo use_helper ('user')?>
 
<Div class = "Answer" id = "add_answer">
<? PHP echo form_remote_tag (Array (
'Url' => '@ add_answer ',
'Update' => array ('success' => 'add _ ancer '),
'Loading' => "element. Show ('indicator ')",
'Complete' => "element. Hide ('indicator');". visual_effect ('highlight ', 'add _ answer '),
)?>
 
<Div class = "form-row">
<? PHP if ($ sf_user-> isauthenticated ():?>
<? PHP echo $ sf_user-> getnickname ()?>
<? PHP else:?>
<? PHP echo 'anonus us coward '?>
<? PHP echo link_to_login ('login')?>
<? PHP endif;?>
</Div>
 
<Div class = "form-row">
<Label for = "label"> your answer: </label>
<? PHP echo textarea_tag ('body', $ sf_params-> get ('body')?>
</Div>
 
<Div class = "Submit-row">
<? PHP echo input_hidden_tag ('Question _ id', $ question-> GETID ()?>
<? PHP echo submit_tag ('answer it')?>
</Div>
</Form>
</Div>
 
</Div>

Reconstruction

The link_to_login () function must be added to the userhelper. php helper:

Function link_to_login ($ name, $ uri = NULL)
{
If ($ URI & sfcontext: getinstance ()-> getuser ()-> isauthenticated ())
{
Return link_to ($ name, $ URI );
}
Else
{
Return link_to_function ($ name, visual_effect ('blind _ low', 'login', array ('duration' => 0.5 )));
}
}

What this function does is what we have seen in other user help tools: if the user has been authorized, a link to the action will be displayed. If the user is not authorized, this link points to the Ajax login form. So in the link_to_user_interested () and link_to_user_relevancy () functions, use link_to_login () to replace link_to_function. Do not forget the link to @ add_question in modules/sidebar/templatetes/defaultsuccess. php. Yes, this is refactoring.

Process Form submission

Although he is still calling code snippets, the method we choose here to process Ajax requests is slightly different from what we described on the last day. This is because we want the result of Form submission to actually replace the form. This is why the update parameter in the form_remote_tag () helper points to the container of the form rather than to the outer space. _ Answer. php fragment will be included in the result of the answer adding action, so the final result looks like the following:

...
<Div id = "answers">
<! -- Answer 1 -->
<! -- Answer 2 -->
<! -- Answer 3 -->
...
</Div>
 
<Div class = "Answer" id = "add_answer">
<! -- The New answer -->
</Div>

Maybe we have already guessed how form_remote_tag () JavaScript works: It submits the form to the specified action in the URL parameter through an XMLHTTPRequest object. The result of the Action replaces the element specified in the update parameter. In addition, like the link_to_remote () helper in the last day, it activates the activity indicator to be visible and makes it unmailed based on request submission, in addition, the updated part is highlighted at the end of the Ajax transaction.

Here we will talk about several users associated with a new question. As we mentioned earlier, the answer must be linked to a user. If the user has been verified, his user_id will be used for the new answer. Otherwise, anonymous will be used unless the user chooses to log on. The link_to_login () helper in the globalhelper. php helper activates the hidden form in the layout. We can visit the askeet source friends to view their code.

Answer/Add action

The @ add_answer rule pointing to answer/Add action as the URL parameter of the Ajax form:

Add_answer:
URL:/add_anwser
Param: {module: Answer, Action: Add}

The following is the action content:

Public Function executeadd ()
{
If ($ this-> getrequest ()-> getmethod () = sfrequest: Post)
{
If (! $ This-> getrequestparameter ('body '))
{
Return sfview: none;
}
 
$ Question = questionpeer: retrievebypk ($ this-> getrequestparameter ('Question _ id '));
$ This-> forward404unless ($ question );
 
// User or anonymous coward
$ User = $ this-> getuser ()-> isauthenticated ()? $ This-> getuser ()-> getsubscriber (): userpeer: retrivebynickname ('anonus us ');
 
// Create answer
$ This-> answer = new answer ();
$ This-> answer-> setquestion ($ question );
$ This-> answer-> setbody ($ this-> getrequestparameter ('body '));
$ This-> answer-> setuser ($ user );
$ This-> answer-> Save ();
 
Return sfview: success;
}
 
$ This-> forward404 ();
}
First, if this action is not called in post mode, it means some people enter it in the address bar of the browser. The action is not set for this type, so in this case, a 404 error is returned.

To determine the user to be set as the answer author, the action checks whether the current user has been authorized. If this is not the case, the new: retrievebynickname () method of the userpeer class uses the 'Anonymous coward 'user. If we still have doubts about this method, we can check its source code.

In this way, everything is ready to create a new problem and send the request to the addsuccess. php template. As we expected, this template only contains one line of code:

<? PHP include_partial ('answer', array ('answer' => $ answer)?>

We also need to disable the layout of this action in frontend/modules/answer/config/view. yml:

Addsuccess:
Has_layout: Off

Finally, if the user submits an empty answer, we do not store it. Therefore, the data is processed slightly, and the action does not return any content. This will simply clear the page. We have processed the data in the Ajax form, but this should put the form itself in another segment, and it is not worth doing so now.

Test

This completes? It is now that AJAX forms are ready for use, clean, and secure. Now we can perform a test to display a list of answers to a question and add a new question. This page does not need to be refreshed, but the new answer is displayed at the bottom of the previous list. This is simple, isn't it?

Tomorrow

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.