Development

Documentation/ja_JP/book/1.0/04-The-Basics-of-Page-Creation (diff)

You must first sign up to be able to contribute.

Changes from Version 1 of Documentation/ja_JP/book/1.0/04-The-Basics-of-Page-Creation

Show
Ignore:
Author:
heihachiro (IP: 125.100.73.82)
Timestamp:
02/08/07 12:26:51 (11 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/ja_JP/book/1.0/04-The-Basics-of-Page-Creation

    v0 v1  
     1 
     2{{{ 
     3#!WikiMarkdown 
     4Chapter 4 - The Basics Of Page Creation 
     5======================================= 
     6 
     7Curiously, the first tutorial that programmers follow when learning a new language or a framework is the one that displays "Hello, world!" on the screen. It is strange to think of the computer as something that can greet the whole world, since every attempt in the artificial intelligence field has so far resulted in poor conversational abilities. But symfony isn't dumber than any other program, and the proof is, you can create a page that says "Hello, `<Your Name Here>`" with it. 
     8 
     9This chapter will teach you how to create a module, which is a structural element that groups pages. You will also learn how to create a page, which is divided into an action and a template, because of the MVC pattern. Links and forms are the basic web interactions; you will see how to insert them in a template and handle them in an action. 
     10 
     11Creating a Module Skeleton 
     12-------------------------- 
     13 
     14As Chapter 2 explained, symfony groups pages into modules. Before creating a page, you need to create a module, which is initially an empty shell with a file structure that symfony can recognize. 
     15 
     16The symfony command line automates the creation of modules. You just need to call the `in`it-module task with the application name and the module name as arguments. In the previous chapter, you created a `myapp` application. To add a `mymodule` module to this application, type the following commands: 
     17 
     18    > cd ~/myproject 
     19    > symfony init-module myapp mymodule 
     20 
     21    >> dir+      ~/myproject/apps/myapp/modules/mymodule 
     22    >> dir+      ~/myproject/apps/myapp/modules/mymodule/actions 
     23    >> file+     ~/myproject/apps/myapp/modules/mymodule/actions/actions.class.php 
     24    >> dir+      ~/myproject/apps/myapp/modules/mymodule/config 
     25    >> dir+      ~/myproject/apps/myapp/modules/mymodule/lib 
     26    >> dir+      ~/myproject/apps/myapp/modules/mymodule/templates 
     27    >> file+     ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php 
     28    >> dir+      ~/myproject/apps/myapp/modules/mymodule/validate 
     29    >> file+     ~/myproject/test/functional/myapp/mymoduleActionsTest.php 
     30    >> tokens    ~/myproject/test/functional/myapp/mymoduleActionsTest.php 
     31    >> tokens    ~/myproject/apps/myapp/modules/mymodule/actions/actions.class.php 
     32    >> tokens    ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php 
     33 
     34Apart from the actions/, config/, lib/, templates/, and validate/ directories, this command created only three files. The one in the test/ folder concerns unit tests, and you don't need to bother with it until Chapter 15. The `actions.class.php` (shown in Listing 4-1) forwards to the default module congratulation page. The `templates/indexSuccess.php` file is empty. 
     35 
     36Listing 4-1 - The Default Generated Action, in `actions/actions.class.php` 
     37 
     38    [php] 
     39    <?php 
     40 
     41    class mymoduleActions extends sfActions 
     42    { 
     43      public function executeIndex() 
     44      { 
     45        $this->forward('default', 'module'); 
     46      } 
     47    } 
     48 
     49>**NOTE** 
     50>If you look at an actual `actions.class.php` file, you will find more than these few lines, including a lot of comments. This is because symfony recommends using PHP comments to document your project and prepares each class file to be compatible with the phpDocumentor tool (`http://www.phpdoc.org/`). 
     51 
     52For each new module, symfony creates a default `index` action. It is composed of an action method called `executeIndex` and a template file called `indexSuccess.php`. The meanings of the `execute` prefix and `Success` suffix will be explained in Chapters 6 and 7, respectively. In the meantime, you can consider that this naming is a convention. You can see the corresponding page (reproduced in Figure 4-1) by browsing to the following URL: 
     53 
     54    http://localhost/myapp_dev.php/mymodule/index 
     55 
     56The default `index` action will not be used in this chapter, so you can remove the `executeIndex()` method from the `actions.class.php` file, and delete the `indexSuccess.php` file from the `templates/` directory. 
     57 
     58>**NOTE* 
     59>Symfony offers other ways to initiate a module than the command line. One of them is to create the directories and files yourself. In many cases, actions and templates of a module are meant to manipulate data of a given table. As the necessary code to create, retrieve, update, and delete records from a table is often the same, symfony provides a mechanism called scaffolding to generate this code for you. Refer to Chapter 14 for more information about this technique. 
     60 
     61![][7] 
     62 
     63   [7]: 
     64 
     65Figure 4-1 - The default generated index page 
     66 
     67Adding a Page 
     68------------- 
     69 
     70In symfony, the logic behind pages is stored in the action, and the presentation is in templates. Pages without logic (still) require an empty action. 
     71 
     72### Adding an Action 
     73 
     74The "Hello, world!" page will be accessible through a `myAction` action. To create it, just add an `executeMyAction` method to the `mymoduleActions` class, as shown in Listing 4-2. 
     75 
     76Listing 4-2 - Adding an Action Is Like Adding an Execute Method to the Action Class 
     77 
     78    [php] 
     79    <?php 
     80 
     81    class mymoduleActions extends sfActions 
     82    { 
     83      public function executeMyAction() 
     84      { 
     85      } 
     86    } 
     87 
     88The name of the action method is always `execute``Xxx``()`, where the second part of the name is the action name with the first letter capitalized. 
     89 
     90Now, if you request the following URL: 
     91 
     92    http://localhost/myapp_dev.php/mymodule/myAction 
     93 
     94symfony will complain that the `myActionSuccess.php` template is missing. That's normal; in symfony, a page is always made of an action and a template. 
     95 
     96>**CAUTION** 
     97>URLs (not domain names) are case-sensitive, and so is symfony (even though the method names are case-insensitive in PHP). This means that if you add an `executemyaction()` method, or an `executeMyaction()`, and then you call `myAction` with the browser, symfony will return a 404 error. 
     98 
     99>**SIDEBAR** 
     100>URLs are part of the response 
     101> 
     102>Symfony contains a routing system that allows you to have a complete separation between the actual action name and the form of the URL needed to call it. This allows for custom formatting of the URL as if it were part of the response. You are no longer limited by the file structure nor by the request parameters; the URL for an action can look like the phrase you want. For instance, the call to the index action of a module called article usually looks like this: 
     103> 
     104>    http://localhost/myapp_dev.php/article/index?id=123 
     105> 
     106>This URL retrieves a given article from a database. In this example, it retrieves an article (with `id=123`) in the Europe section that specifically discusses finance in France. But the URL can be written in a completely different way with a simple change in the `routing.yml` configuration file: 
     107> 
     108>    http://localhost/articles/europe/france/finance.html 
     109> 
     110>Not only is the resulting URL search engine-friendly, it is also significant for the user, who can then use the address bar as a pseudo command line to do custom queries, as in the following: 
     111> 
     112>    http://localhost/articles/tagged/finance+france+euro 
     113> 
     114>Symfony knows how to parse and generate smart URLs for the user. The routing system automatically peels the request parameters from a smart URL and makes them available to the action. It also formats the hyperlinks included in the response so that they look "smart." You will learn more about this feature in Chapter 9. 
     115> 
     116>Overall, this means that the way you name the actions of your applications should not be influenced by the way the URL used to call them should look, but by the actions' functions in the application. An action name explains what the action actually does, and it's often a verb in the infinitive form (like `show`, `list`, `edit`, and so on). Action names can be made totally invisible to the end user, so don't hesitate to use explicit action names (like `listByName` or `showWithComments`). You will economize on code comments to explain your action function, plus the code will be much easier to read. 
     117 
     118### Adding a Template 
     119 
     120The action expects a template to render itself. A template is a file located in the `templates/` directory of a module, named by the action and the action termination. The default action termination is a "success," so the template file to be created for the `myAction` action is to be called `myActionSuccess.php`. 
     121 
     122Templates are supposed to contain only presentational code, so keep as little PHP code in them as possible. As a matter of fact, a page displaying "Hello, world!" can have a template as simple as the one in Listing 4-3. 
     123 
     124Listing 4-3 - The `mymodule/templates/myActionSuccess.php` Template 
     125 
     126    [php] 
     127    <p>Hello, world!</p> 
     128 
     129If you need to execute some PHP code in the template, you should avoid using the usual PHP syntax, as shown in Listing 4-4. Instead, write your templates using the PHP alternative syntax, as shown in Listing 4-5, to keep the code understandable for non-PHP programmers. Not only will the final code be correctly indented, but it will also help you keep the complex PHP code in the action, because only control statements (`if`, `foreach`, `while`, and so on) have an alternative syntax. 
     130 
     131Listing 4-4 - The Usual PHP Syntax, Good for Actions, But Bad for Templates 
     132 
     133    [php] 
     134    <p>Hello, world!</p> 
     135    <?php 
     136 
     137    if ($test) 
     138    { 
     139      echo "<p>".time()."</p>"; 
     140    } 
     141 
     142    ?> 
     143 
     144Listing 4-5 - The Alternative PHP Syntax, Good for Templates 
     145 
     146    [php] 
     147    <p>Hello, world!</p> 
     148    <?php if ($test): ?> 
     149    <p><?php echo time(); ?></p> 
     150    <?php endif; ?> 
     151 
     152>**TIP** 
     153>A good rule of thumb to check if the template syntax is readable enough is that the file should not contain HTML code echoed by PHP or curly brackets. And most of the time, when opening a `<?php`, you will close it with `?>` in the same line. 
     154 
     155### Passing Information from the Action to the Template 
     156 
     157The job of the action is to do all the complicated calculation, data retrieval, and tests, and to set variables for the template to be echoed or tested. Symfony makes the attributes of the action class (accessed via `$this->variableName` in the action) directly accessible to the template in the global namespace (via `$variableName`). Listings 4-6 and 4-7 show how to pass information from the action to the template. 
     158 
     159Listing 4-6 - Setting an Action Attribute in the Action to Make It Available to the Template 
     160 
     161    [php] 
     162    <?php 
     163 
     164    class mymoduleActions extends sfActions 
     165    { 
     166      public function executeMyAction() 
     167      { 
     168        $today = getdate(); 
     169        $this->hour = $today['hours']; 
     170      } 
     171    } 
     172 
     173Listing 4-7 - The Template Has Direct Access to the Action Attributes 
     174 
     175    [php] 
     176    <p>Hello, world!</p> 
     177    <?php if ($hour >= 18): ?> 
     178    <p>Or should I say good evening? It's already <?php echo $hour ?>.</p> 
     179    <?php endif; ?> 
     180 
     181>**NOTE** 
     182>The template already has access to a few pieces of data without the need of any variable setup in the action. Every template can call methods of the `$sf_context`, `$sf_request`, `$sf_params`, and `$sf_user` objects. They contain data related to the current context, request, request parameters, and session. You will soon learn how to use them efficiently. 
     183 
     184Gathering Information from the User with Forms 
     185---------------------------------------------- 
     186 
     187Forms are a good way to get information from the user. Writing form and form elements in HTML can sometimes be cumbersome, especially when you want to be XHTML-compliant. You could include form elements in symfony templates the usual way, as shown in Listing 4-8, but symfony provides helpers that make this task easier. 
     188 
     189Listing 4-8 - Templates Can Include Usual HTML Code 
     190 
     191    [php] 
     192    <p>Hello, world!</p> 
     193    <?php if ($hour >= 18): ?> 
     194    <p>Or should I say good evening? It's already <?php echo $hour ?>.</p> 
     195    <?php endif; ?>      
     196    <form method="post" target="/myapp_dev.php/mymodule/anotherAction"> 
     197      <label for="name">What is your name?</label> 
     198      <input type="text" name="name" id="name" value="" /> 
     199      <input type="submit" value="Ok" /> 
     200    </form> 
     201 
     202A helper is a PHP function defined by symfony that is meant to be used within templates. It outputs some HTML code and is faster to use than writing the actual HTML code by yourself. Using symfony helpers, you can have the same result as in Listing 4-8 with the code shown in Listing 4-9. 
     203 
     204Listing 4-9 - It Is Faster and Easier to Use Helpers Than to Use HTML Tags 
     205 
     206    [php] 
     207    <p>Hello, world!</p> 
     208    <?php if ($hour >= 18): ?> 
     209    <p>Or should I say good evening? It's already <?php echo $hour ?>.</p> 
     210    <?php endif; ?> 
     211    <?php echo form_tag('mymodule/anotherAction') ?> 
     212      <?php echo label_for('name', 'What is your name?') ?> 
     213      <?php echo input_tag('name') ?> 
     214      <?php echo submit_tag('Ok') ?> 
     215    </form> 
     216 
     217>**SIDEBAR** 
     218>Helpers are here to help you 
     219> 
     220>If, in the example in Listing 4-9, you think the helper version is not really faster to write than the HTML one, consider this one: 
     221> 
     222> 
     223>    [php] 
     224>    <?php 
     225>    $card_list = array( 
     226>      'VISA' => 'Visa', 
     227>      'MAST' => 'MasterCard', 
     228>      'AMEX' => 'American Express', 
     229>      'DISC' => 'Discover'); 
     230>    echo select_tag('cc_type', options_for_select($card_list, 'AMEX')); 
     231>    ?> 
     232> 
     233> 
     234>This outputs the following HTML: 
     235> 
     236> 
     237>    [php] 
     238>    <select name="cc_type" id="cc_type"> 
     239>      <option value="VISA">Visa</option> 
     240>      <option value="MAST">MasterCard</option> 
     241>      <option value="AMEX" selected="selected">American Express</option> 
     242>      <option value="DISC">Discover</option> 
     243>    </select> 
     244> 
     245> 
     246>The benefit of helpers in templates is raw speed of coding, clarity of code, and concision. The only price to pay is the time to learn them, which will end when you finish this book, and the time to write <?php echo ?>, for which you should already have a shortcut in your favorite text editor. So you could not use the symfony helpers in templates and write HTML the way you always did, but this would be a great loss and much less fun. 
     247 
     248Note that the use of the short opening tags (`<?=`, equivalent to `<?php echo`) is not recommended for professional web applications, since your production web server may be able to understand more than one scripting language and consequently get confused. Besides, the short opening tags do not work with the default PHP configuration and need server tweaking to be activated. Ultimately, when you have to deal with XML and validation, it falls short because `<?` has a special meaning in XML. 
     249 
     250Form manipulation deserves a whole chapter of its own, since symfony provides many tools, mostly helpers, to make it easier. You will learn more about these helpers in Chapter 10. 
     251 
     252Linking to Another Action 
     253------------------------- 
     254 
     255You already know that there is a total decoupling between an action name and the URL used to call it. So if you create a link to `anotherAction` in a template as in Listing 4-10, it will only work with the default routing. If you later decide to change the way the URLs look, then you will need to review all templates to change the hyperlinks. 
     256 
     257Listing 4-10 - Hyperlinks, the Classic Way 
     258 
     259    [php] 
     260    <a href="/myapp_dev.php/mymodule/anotherAction?name=anonymous"> 
     261      I never say my name 
     262    </a> 
     263 
     264To avoid this hassle, you should always use the `link_to()` helper to create hyperlinks to your application's actions. Listing 4-11 demonstrates the use of the hyperlink helper. 
     265 
     266Listing 4-11 - The `link_to()` Helper 
     267 
     268    [php] 
     269    <p>Hello, world!</p> 
     270    <?php if ($hour >= 18): ?> 
     271    <p>Or should I say good evening? It's already <?php echo $hour ?>.</p> 
     272    <?php endif; ?> 
     273    <?php echo form_tag('mymodule/anotherAction') ?> 
     274      <?php echo label_for('name', 'What is your name?') ?> 
     275      <?php echo input_tag('name') ?> 
     276      <?php echo submit_tag('Ok') ?> 
     277      <?php echo link_to('I never say my name','mymodule/anotherAction?name=anonymous') ?> 
     278    </form> 
     279 
     280The resulting HTML will be the same as previously, except that when you change your routing rules, all the templates will behave correctly and reformat the URLs accordingly. 
     281 
     282The `link_to()` helper, like many other helpers, accepts another argument for special options and additional tag attributes. Listing 4-12 shows an example of an option argument and the resulting HTML. The option argument is either an associative array or a simple string showing `key=value` couples separated by blanks. 
     283 
     284Listing 4-12 - Most Helpers Accept an Option Argument 
     285 
     286    [php] 
     287    // Option argument as an associative array 
     288    <?php echo link_to('I never say my name', 'mymodule/anotherAction?name=anonymous', 
     289      array( 
     290        'class'    => 'special_link', 
     291        'confirm'  => 'Are you sure?', 
     292        'absolute' => true 
     293    )) ?> 
     294 
     295    // Option argument as a string 
     296    <?php echo link_to('I never say my name', 'mymodule/anotherAction?name=anonymous', 
     297      'class=special_link confirm=Are you sure? absolute=true') ?> 
     298 
     299    // Both calls output the same 
     300     => <a class="special_link" onclick="return confirm('Are you sure?');" 
     301        href="http://localhost/myapp_dev.php/mymodule/anotherAction/name/anonymous"> 
     302        I never say my name</a> 
     303 
     304Whenever you use a symfony helper that outputs an HTML tag, you can insert additional tag attributes (like the `class` attribute in the example in Listing 4-12) in the option argument. You can even write these attributes in the "quick-and-dirty" HTML 4.0 way (without double quotes), and symfony will output them in nicely formatted XHTML. That's another reason why helpers are faster to write than HTML. 
     305 
     306>**NOTE* 
     307>Because it requires an additional parsing and transformation, the string syntax is a little slower than the array syntax. 
     308 
     309Like the form helpers, the link helpers are numerous and have many options. Chapter 9 will describe them in detail. 
     310 
     311Getting Information from the Request 
     312------------------------------------ 
     313 
     314Whether the user sends information via a form (usually in a POST request) or via the URL (GET request), you can retrieve the related data from the action with the `getRequestParameter()` method of the `sfActions` object. Listing 4-13 shows how, in `anotherAction`, you retrieve the value of the `name` parameter. 
     315 
     316Listing 4-13 - Getting Data from the Request Parameter in the Action 
     317 
     318    [php] 
     319    <?php 
     320 
     321    class mymoduleActions extends sfActions 
     322    { 
     323      ... 
     324 
     325      public function executeAnotherAction() 
     326      { 
     327        $this->name = $this->getRequestParameter('name'); 
     328      } 
     329    } 
     330 
     331If the data manipulation is simple, you don't even need to use the action to retrieve the request parameters. The template has access to an object called `$sf_params`, which offers a `get`() method to retrieve the request parameters, just like the getRequestParameter() in the action. 
     332 
     333If `executeAnotherAction()` were empty, Listing 4-14 shows how the `anotherActionSuccess.php` template would retrieve the same `name` parameter. 
     334 
     335Listing 4-14 - Getting Data from the Request Parameter Directly in the Template 
     336 
     337    [php] 
     338    <p>Hello, <?php echo $sf_params->get('name') ?>!</p> 
     339 
     340>**NOTE** 
     341>Why not use the `$_POST`, `$_GET`, or `$_REQUEST` variables instead? Because then your URLs will be formatted differently (as in `http://localhost/articles/europe/france/finance.html`, without `?` nor `=`), the usual PHP variables won't work anymore, and only the routing system will be able to retrieve the request parameters. And you may want to add input filtering to prevent malicious code injection, which is only possible if you keep all request parameters in one clean parameter holder. 
     342 
     343The `$sf_params` object is more powerful than just giving a getter equivalent to an array. For instance, if you only want to test the existence of a request parameter, you can simply use the `$sf_params->has()` method instead of testing the actual value with `get()`, as in Listing 4-15. 
     344 
     345Listing 4-15 - Testing the Existence of a Request Parameter in the Template 
     346 
     347    [php] 
     348    <?php if ($sf_params->has('name')): ?> 
     349      <p>Hello, <?php echo $sf_params->get('name') ?>!</p> 
     350    <?php else: ?> 
     351      <p>Hello, John Doe!</p> 
     352    <?php endif; ?> 
     353 
     354You may have already guessed that this can be written in a single line. As with most getter methods in symfony, both the `getRequestParameter()` method in the action and the `$sf_params->get()` method in the template (which, as a matter of fact, calls the same method on the same object) accept a second argument: the default value to be used if the request parameter is not present. 
     355 
     356    [php] 
     357    <p>Hello, <?php echo $sf_params->get('name', 'John Doe') ?>!</p> 
     358 
     359Summary 
     360------- 
     361 
     362In symfony, pages are composed of an action (a method in the `actions/actions.class.php` file prefixed with `execute`) and a template (a file in the `templates/` directory, usually ending with `Success.php`). They are grouped in modules, according to their function in the application. Writing templates is facilitated by helpers, which are functions provided by symfony that return HTML code. And you need to think of the URL as a part of the response, which can be formatted as needed, so you should refrain for using any direct reference to the URL in action naming or request parameter retrieval. 
     363 
     364Once you know these basic principles, you can already write a whole web application with symfony. But it would take you way too long, since almost every task you will have to achieve during the course of the application development is facilitated one way or another by some symfony feature . . . which is why the book doesn't stop now. 
     365 
     366}}} 
     367 
     368---- 
     369[wiki:Documentation/ja_JP/ 目次]