Symfony form and page implementation skills

Source: Internet
Author: User
Tags php foreach php template
This article mainly introduces the symfony form and page implementation skills. The example analyzes the symfony form and page implementation methods and related precautions, for more information about how to implement symfony forms and pages, see the example in this article. Share it with you for your reference. The details are as follows:

Symfony development is concise, but the number of features is still very lacking. Now it is time for some askeet sites to interact with users. The root of HTML interaction-except the starting link-is the form.

Here, we aim to allow users to log on and read through the problem list on the home page. This is very fast for development and allows us to recall the previous content.

Login form

There are users in the test data, but the program cannot perform verification. Next we will add a login form on every page of the program. Open the global layout file askeet/apps/frontend/templates/layout. php, and add the following code line before connecting to the about:

The code is as follows:

  • <? Php echo link_to ('sign in', 'user/login')?>
  • The current layout places these links after the web Debugging toolbar. To see these links, click the 'SF 'icon to fold the debugging toolbar.

    Create a user module. The question module was born in the second generation. this time we just called symfony to create the module framework, and we will write the code ourselves.

    The code is as follows:

    $ Symfony init-module frontend user

    This framework contains a default index action and an indexSuccess. php template. Delete them because we don't need them.

    Create user/login actions

    The code is as follows:

    In the user/actions/action. class. php file, add the following logon action:

    Public function executeLogin ()
    {
    $ This-> getRequest ()-> setAttribute ('referer', $ this-> getRequest ()-> getReferer ());

    Return sfView: SUCCESS;
    }

    This action saves the referer in the request attributes. This attribute can be stored in a hidden area for the module, so that the target action of the form can be redirected to the original referer after successful login.

    Statement return sfView: SUCCESS transmits the action execution result to the loginSuccess. php module. This statement is implemented in an action that does not contain the returned statement. This is why the default module of an action is called actionnameSuccess. php.

    Before starting more work, let's take a look at the module.

    Create the loginSuccess. php module

    Many forms are used for human-computer interaction on the web, and Symfony organizes the creation and management of forms by providing a form helper set.

    In the askeet/apps/frontend/modules/user/templates/directory, create the following loginSuccess. php module:

    The code is as follows:

    <? Php echo form_tag ('user/login')?>




    Nickname:
    <? Php echo input_tag ('nickname', $ sf_params-> get ('nickname')?>




    Password:
    <? Php echo input_password_tag ('password')?>





    <? Php echo input_hidden_tag ('referer', $ sf_request-> getAttribute ('referer')?>
    <? Php echo submit_tag ('sign in')?>

    This module is the first time we use the form helper. These Symfony functions help us to automatically write form labels. Form_tag () open this label, use POST as the default action, and point to the action passed as a parameter. The input_tag () helper generatesTag, and an id attribute is automatically added based on the first parameter passed. the default value is obtained by the second parameter. We can find more information about the form helper and the HTML code they generate in the relevant sections of Symfony.

    The essence here is that this action is called when the form is submitted. So let's take a look at this action.

    Process form submission

    Use the following code to replace the login action we just compiled:

    The code is as follows:

    Public function executeLogin ()
    {
    If ($ this-> getRequest ()-> getMethod ()! = SfRequest: POST)
    {
    // Display the form
    $ This-> getRequest ()-> setAttribute ('referer', $ this-> getRequest ()-> getReferer ());
    }
    Else
    {
    // Handle the form submission
    $ Nickname = $ this-> getRequestParameter ('nickname ');

    $ C = new Criteria ();
    $ C-> add (UserPeer: NICKNAME, $ nickname );
    $ User = UserPeer: doSelectOne ($ c );

    // Nickname exists?
    If ($ user)
    {
    // Password is OK?
    If (true)
    {
    $ This-> getUser ()-> setAuthenticated (true );
    $ This-> getUser ()-> addCredential ('subscriber ');

    $ This-> getUser ()-> setAttribute ('subscriber _ id', $ user-> getId (), 'subscriber ');
    $ This-> getUser ()-> setAttribute ('nickname', $ user-> getNickname (), 'subscriber ');

    // Redirect to last page
    Return $ this-> redirect ($ this-> getRequestParameter ('referer', '@ homepage '));
    }
    }
    }
    }

    The login action can be used to display and process the login form at the same time. Correspondingly, he must know the called environment. If this action is not called in POST mode (because it is requested by a link): This is exactly what we discussed earlier. If the request is in POST mode, the form will call this action and process it accordingly.

    This action gets the value of the nickname field from the request parameter and queries the User table to check whether the User exists in the database.

    In the future, a password control will assign creden。 to the user. But now, all this action does is store the user's id and nick name attributes in a session attribute. Finally, this action is redirected to the hidden original referer field in the form, which is passed as a request parameter. If this field is empty, the default value is used.

    Here we need to note the difference between the two types of attribute sets in this example: request attributes ($ this-> getRequest ()-> setAttribute () is saved by the template, in addition, as long as the answer is sent to the referer, it will be forgotten. Session attributes ($ this-> getUser ()-> setAttribute () is saved throughout the user's session life, and other actions can be accessed in the future. If you want to learn more about attributes, you can refer to the parameter saveder section in Symfony.

    Assign permissions

    It is a good thing that users can log on to the askeet website. Post a new question, express interest in a question, and comment on a comment. Other actions will be made available to non-login users.

    To set a user as verified, call the-> setAuthenticated () method of the sfUser object. This object also provides a certificate mechanism (-> addCredential () to restrict access by configuring. The user certificate section in Symfony explains this in detail.

    This is the purpose of the following two rows:

    The code is as follows:

    $ This-> getContext ()-> getUser ()-> setAuthenticated (true );
    $ This-> getContext ()-> getUser ()-> addCredential ('subscriber ');

    When nickname is identified, not only is the user data stored in the session attribute, but the user is also assigned access permissions for restricted part of the website. Tomorrow we will see how to restrict access to authenticated users.

    Add user/logout action

    The-> setAttribute () method also has the last tip: the last parameter (subscriber in the above example) defines the namespace for storing attributes. A namespace not only allows a name that exists in another namespace to be specified to an attribute, but also allows you to use a command to quickly remove all these attributes:

    The code is as follows:

    Public function executeLogout ()
    {
    $ This-> getUser ()-> setAuthenticated (false );
    $ This-> getUser ()-> clearCredentials ();

    $ This-> getUser ()-> getAttributeHolder ()-> removeNamespace ('subscriber ');

    $ This-> redirect ('@ homepage ');
    }

    Using namespace saves us the trouble of removing these attributes one by one: this is just a line of statements.

    Update layout

    The current layout displays a 'login' link even if the user has logged in. Let's fix this. In the askeet/apps/frontend/templates/layout. php file, modify the code we modified at the beginning of today's guide:

    The code is as follows:

    <? Php if ($ sf_user-> isAuthenticated ():?>

  • <? Php echo link_to ('sign out', 'user/logout')?>

  • <? Php echo link_to ($ sf_user-> getAttribute ('nickname', '', 'subscriber '). 'Profile', 'user/profile ')?>

  • <? Php else:?>
  • <? Php echo link_to ('sign in/register ', 'user/login')?>

  • <? Php endif?>

    Now it is time to perform the test. we can display any page of the program, click the 'login' link, enter an available nickname ('anonus us' as an example), and perform verification. If 'login' at the top of the window changes to 'sign out', everything we do is correct. Finally, try to log out to check whether the 'login' link appears again.

    Problem organization

    As thousands of Symfony fans visit the askeet website, problems on the home page will gradually increase. To avoid slow requests, you must read the problem column at will.

    Symfony provides an object for this purpose: sfPropelPager. It encapsulates the request to the data, and then only queries the records displayed on the current page. For example, if only 10 problems are displayed on each page during page initialization, requests to data will be limited to 10 results, and an offset will be set for matching on the page.

    Modify the question/list action

    In the previous exercise, we saw the display action of the problem module:

    The code is as follows:

    Public function executeList ()
    {
    $ This-> questions = QuestionPeer: doSelect (new Criteria ());
    }

    We will modify this action to pass an sfPropelPager to the template instead of an array. At the same time, we will sort the questions based on the number of interest:

    The code is as follows:

    Public function executeList ()
    {
    $ Pager = new sfPropelPager ('question', 2 );
    $ C = new Criteria ();
    $ C-> addDescendingOrderByColumn (QuestionPeer: INTERESTED_USERS );
    $ Pager-> setCriteria ($ c );
    $ Pager-> setPage ($ this-> getRequestParameter ('page', 1 ));
    $ Pager-> setPeerMethod ('doselectjoinuser ');
    $ Pager-> init ();

    $ This-> question_pager = $ pager;
    }

    The initialization of the sfPropelPager object specifies the object class it contains and the maximum number of objects that can be placed on a page (2 in this example ). -> The setPage () method uses a request parameter to set the current page. For example, if the value of this page parameter is 2, sfPropelPager will return 3 to 5 results. If the value of the page request parameter changes to 1, the page returns the result from 1 to 2 by default. We can learn more about the sfPropelPager object and its methods in the page section of Symfony.

    Use a default parameter

    It is a good idea to put constants in the configuration file we use. For example, the result of each page (in this example, 2) can be replaced by a parameter in our custom program configuration. Use the following code to change the above sfPropelPager line:

    The code is as follows:

    ..
    $ Pager = new sfPropelPager ('question ', sfConfig: get ('app _ pager_homepage_max '));

    The pager keyword is used as the namespace, which is why the parameter name appears. We can see more about custom configuration and naming of custom parameter rules in the configuration section of Symfony.

    Modify the listSuccess. php template

    In the listSuccess. php template, run the following code line:

    The code is as follows:

    <? Php foreach ($ questions as $ question):?>

    Replace

    The code is as follows:

    <? Php foreach ($ question_pager-> getResults () as $ question):?>

    The result list stored on the page is displayed.

    Add page browsing

    In this template, you also need to do another thing: page browsing. Now, the template only displays the first two questions, but we should add the feature to the next page and return to the previous page. To add these functions, add the following code after the template:

    The code is as follows:


    <? Php if ($ question_pager-> haveToPaginate ():?>
    <? Php echo link_to ('«', 'Question/list? Page = 1')?>
    <? Php echo link_to ('<', 'Question/list? Page = '. $ question_pager-> getPreviousPage ()?>

    <? Php foreach ($ question_pager-> getLinks () as $ page):?>
    <? Php echo link_to_unless ($ page = $ question_pager-> getPage (), $ page, 'Question/list? Page = '. $ page)?>
    <? Php echo ($ page! = $ Question_pager-> getCurrentMaxLink ())? '-': '?>
    <? Php endforeach;?>

    <? Php echo link_to ('>', 'Question/list? Page = '. $ question_pager-> getNextPage ()?>
    <? Php echo link_to ('»', 'Question/list? Page = '. $ question_pager-> getLastPage ()?>
    <? Php endif;?>

    This code uses various methods of the sfPropelPager object and-> haveToPaginate (). This function returns true only when the number of requested results exceeds the page size; the-> getPreviousPage (),-> getNextPage (),-> getLastPage () all have explicit display meaning. the-> getLinks () function provides an array of page numbers; the-> getCurrentMaxLink () function returns the last page number.

    This example also shows a Symfony link helper: link_to_unless () will output a general link_to () when the test as the first parameter is false (), otherwise, a non-link text is output and packaged in a simple way.

    Have we tested this page? We should perform tests. This modification is not completed until we verify it with our own eyes. To perform a test, open the test data file created on the third day, and add some questions for the page browsing to be displayed. Run the import data batch file again, and then request the home page again.

    Add routing rules for subpages

    By default, the page rules are as follows:

    Http: // askeet/frontend_dev.php/question/list/page/XX

    Now, using routing rules to use these pages is easier to understand:

    Http: // askeet/frontend_dev.php/index/XX

    Open the apps/frontend/config/routing. yml file and add the following content at the top:

    The code is as follows:

    Popular_questions:
    Url:/index/: page
    Param: {module: question, action: list}

    Add other routing rules to the logon page:

    The code is as follows:

    Login:
    Url:/login
    Param: {module: user, action: login}

    Reconstruction

    Model

    The question/list action executes model-related code, which is why we need to move the code to the module. Use the following code to replace the question/list action:

    The code is as follows:

    Public function executeList ()
    {
    $ This-> question_pager = QuestionPeer: getHomepagePager ($ this-> getRequestParameter ('page', 1 ));
    }

    Add the following method to the QuestionPeer. php class in lib/model:

    The code is as follows:

    Public static function getHomepagePager ($ page)
    {
    $ Pager = new sfPropelPager ('question ', sfConfig: get ('app _ pager_homepage_max '));
    $ C = new Criteria ();
    $ C-> addDescendingOrderByColumn (self: INTERESTED_USERS );
    $ Pager-> setCriteria ($ c );
    $ Pager-> setPage ($ page );
    $ Pager-> setPeerMethod ('doselectjoinuser ');
    $ Pager-> init ();

    Return $ pager;
    }

    The same idea also applies to the question/show action we wrote yesterday: the usage of the title retrieval question that the Propel object is stripped from should belong to this module. So use the following code to change the question/show action code:

    The code is as follows:

    Public function executeShow ()
    {
    $ This-> question = QuestionPeer: getQuestionFromTitle ($ this-> getRequestParameter ('stripped _ title '));

    $ This-> forward404Unless ($ this-> question );
    }

    Add the following code to the QuestionPeer. php file:

    The code is as follows:

    Public static function getQuestionFromTitle ($ title)
    {
    $ C = new Criteria ();
    $ C-> add (QuestionPeer: STRIPPED_TITLE, $ title );

    Return self: doSelectOne ($ c );
    }

    Template

    The problem list displayed in question/templates/listSuccess. php will be used in some areas in the future. Therefore, we put the template code that shows the problem list in a _ list. php snippet, and use the following simple code to replace the content of listSuccess. php:

    The code is as follows:

    Popular question

    <? Php echo include_partial ('list', array ('question _ pager' => $ question_pager)?>

    I hope this article will help you design the symfony framework program.

    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.