Changeset 3372
- Timestamp:
- 01/30/07 09:50:09 (2 years ago)
- Files:
-
- doc/branches/1.0/book/01-Introducing-Symfony.txt (modified) (2 diffs)
- doc/branches/1.0/book/02-Exploring-Symfony-s-Code.txt (modified) (4 diffs)
- doc/branches/1.0/book/04-The-Basics-of-Page-Creation.txt (modified) (5 diffs)
- doc/branches/1.0/book/05-Configuring-Symfony.txt (modified) (4 diffs)
- doc/branches/1.0/book/06-Inside-the-Controller-Layer.txt (modified) (1 diff)
- doc/branches/1.0/book/07-Inside-the-View-Layer.txt (modified) (5 diffs)
- doc/branches/1.0/book/08-Inside-the-Model-Layer.txt (modified) (8 diffs)
- doc/branches/1.0/book/09-Links-and-the-Routing-System.txt (modified) (3 diffs)
- doc/branches/1.0/book/10-Forms.txt (modified) (2 diffs)
- doc/branches/1.0/book/11-Ajax-Integration.txt (modified) (3 diffs)
- doc/branches/1.0/book/12-Caching.txt (modified) (8 diffs)
- doc/branches/1.0/book/13-I18n-and-L10n.txt (modified) (3 diffs)
- doc/branches/1.0/book/14-Generators.txt (modified) (5 diffs)
- doc/branches/1.0/book/15-Unit-and-Functional-Testing.txt (modified) (3 diffs)
- doc/branches/1.0/book/16-Application-Management-Tools.txt (modified) (5 diffs)
- doc/branches/1.0/book/19-Mastering-Symfony-s-Configuration-Files.txt (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
doc/branches/1.0/book/01-Introducing-Symfony.txt
r3348 r3372 163 163 Using objects instead of records, and classes instead of tables, has another benefit: you can add new accessors to your tables. For instance, if you have a table called `Client` with two fields, `FirstName` and `LastName`, you might like to be able to require just a `Name`. In an object-oriented world, this is as easy as adding a new accessor method to the `Client` class, like this: 164 164 165 [php] 165 166 public function getName() 166 167 { … … 170 171 All the repeated data-access functions and the business logic of the data can be maintained within such objects. For instance, consider a class ShoppingCart in which you keep items (which are objects). To retrieve the full amount of the shopping cart for the checkout, you can add a `getTotal()` method, like this: 171 172 173 [php] 172 174 public function getTotal() 173 175 { doc/branches/1.0/book/02-Exploring-Symfony-s-Code.txt
r3348 r3372 483 483 uploads/ 484 484 485 Table 2-1 - describes the contents of these directories. 486 487 Table 2-1. Root Directories 488 Directory Description 489 490 `apps/` 491 492 Contains one directory for each application of the project (typically, `frontend` and `backend` for the front and back office). 493 494 `batch/` 495 496 Contains PHP scripts called from a command line or a scheduler, to run batch processes. 497 498 `cache/` 499 500 Contains the cached version of the configuration, and (if you activate it) the cache version of the actions and templates of the project. The cache mechanism (detailed in Chapter 12) uses these files to speed up the answer to web requests. Each application will have a subdirectory here, containing preprocessed PHP and HTML files. 501 502 `config/` 503 504 Holds the general configuration of the project. 505 506 `data/` 507 508 Here, you can store the data files of the project, like a database schema, a SQL file that creates tables, or even a SQLite database file. 509 510 `doc/` 511 512 Stores the project documentation, including your own documents and the documentation generated by PHPdoc. 513 514 `lib/` 515 516 Dedicated to foreign classes or libraries. Here, you can add the code that needs to be shared among your applications. The `model/` subdirectory stores the object model of the project (described in Chapter 8). 517 518 `log/` 519 520 Stores the applicable log files generated directly by symfony. It can also contain web server log files, database log files, or log files from any part of the project. Symfony creates one log file per application and per environment (log files are discussed in Chapter 16). 521 522 `plugins/` 523 524 Stores the plug-ins installed in the application (plug-ins are discussed in Chapter 17). 525 526 `test/` 527 528 Contains unit and functional tests written in PHP and compatible with the symfony testing framework (discussed in Chapter 15). During the project setup, symfony automatically adds some stubs with a few basic tests. 529 530 `web/` 531 532 The root for the web server. The only files accessible from the Internet are the ones located in this directory. 485 Table 2-1 describes the contents of these directories. 486 487 Table 2-1 - Root Directories 488 489 Directory | Description 490 ---------- | ------------ 491 `apps/` | Contains one directory for each application of the project (typically, `frontend` and `backend` for the front and back office). 492 `batch/` | Contains PHP scripts called from a command line or a scheduler, to run batch processes. 493 `cache/` | Contains the cached version of the configuration, and (if you activate it) the cache version of the actions and templates of the project. The cache mechanism (detailed in Chapter 12) uses these files to speed up the answer to web requests. Each application will have a subdirectory here, containing preprocessed PHP and HTML files. 494 `config/` | Holds the general configuration of the project. 495 `data/` | Here, you can store the data files of the project, like a database schema, a SQL file that creates tables, or even a SQLite database file. 496 `doc/` | Stores the project documentation, including your own documents and the documentation generated by PHPdoc. 497 `lib/` | Dedicated to foreign classes or libraries. Here, you can add the code that needs to be shared among your applications. The `model/` subdirectory stores the object model of the project (described in Chapter 8). 498 `log/` | Stores the applicable log files generated directly by symfony. It can also contain web server log files, database log files, or log files from any part of the project. Symfony creates one log file per application and per environment (log files are discussed in Chapter 16). 499 `plugins/` | Stores the plug-ins installed in the application (plug-ins are discussed in Chapter 17). 500 `test/` | Contains unit and functional tests written in PHP and compatible with the symfony testing framework (discussed in Chapter 15). During the project setup, symfony automatically adds some stubs with a few basic tests. 501 `web/` | The root for the web server. The only files accessible from the Internet are the ones located in this directory. 533 502 534 503 #### Application Tree Structure … … 547 516 error.txtdelete 548 517 549 Table 2-2 - describes the application subdirectories. 550 551 Table 2-2. Application Subdirectories 552 Directory Description 553 554 `config/` 555 556 Holds a hefty set of YAML configuration files. This is where most of the application configuration is, apart from the default parameters that can be found in the framework itself. Note that the default parameters can still be overridden here if needed. You'll learn more about application configuration in the Chapter 5. 557 558 `i18n/` 559 560 Contains files used for the internationalization of the application--mostly interface translation files (Chapter 13 deals with internationalization). You can bypass this directory if you choose to use a database for internationalization. 561 562 `lib/` 563 564 Contains classes and libraries that are specific to the application. 565 566 `modules/` 567 568 Stores all the modules that contain the features of the application. 569 570 `templates/` 571 572 Lists the global templates of the application--the ones that are shared by all modules. By default, it contains a `layout.php` file, which is the main layout in which the module templates are inserted. 518 Table 2-2 describes the application subdirectories. 519 520 Table 2-2 - Application Subdirectories 521 522 Directory | Description 523 ------------ | ----------- 524 `config/` | Holds a hefty set of YAML configuration files. This is where most of the application configuration is, apart from the default parameters that can be found in the framework itself. Note that the default parameters can still be overridden here if needed. You'll learn more about application configuration in the Chapter 5. 525 `i18n/` | Contains files used for the internationalization of the application--mostly interface translation files (Chapter 13 deals with internationalization). You can bypass this directory if you choose to use a database for internationalization. 526 `lib/` | Contains classes and libraries that are specific to the application. 527 `modules/` | Stores all the modules that contain the features of the application. 528 `templates/` | Lists the global templates of the application--the ones that are shared by all modules. By default, it contains a `layout.php` file, which is the main layout in which the module templates are inserted. 573 529 574 530 >**NOTE** … … 595 551 validate/ 596 552 597 Table 2-3 - describes the module subdirectories. 598 599 Table 2-3. Module Subdirectories 600 Directory Description 601 602 `actions/` 603 604 Generally contains a single class file named `actions.class.php`, in which you can store all the actions of the module. You can also write different actions of a module in separate files. 605 606 `config/` 607 608 Can contain custom configuration files with local parameters for the module. 609 610 `lib/` 611 612 Stores classes and libraries specific to the module. 613 614 `templates/` 615 616 Contains the templates corresponding to the actions of the module. A default template, called `indexSuccess.php`, is created during module setup. 617 618 `validate/` 619 620 Dedicated to configuration files used for form validation (discussed in Chapter 10). 553 Table 2-3 describes the module subdirectories. 554 555 Table 2-3 - Module Subdirectories 556 557 Directory | Description 558 ------------ | ------------ 559 `actions/` | Generally contains a single class file named `actions.class.php`, in which you can store all the actions of the module. You can also write different actions of a module in separate files. 560 `config/` | Can contain custom configuration files with local parameters for the module. 561 `lib/` | Stores classes and libraries specific to the module. 562 `templates/` | Contains the templates corresponding to the actions of the module. A default template, called `indexSuccess.php`, is created during module setup. 563 `validate/` | Dedicated to configuration files used for form validation (discussed in Chapter 10). 621 564 622 565 >**NOTE** … … 635 578 Conventionally, the static files are distributed in the directories listed in Table 2-4. 636 579 637 Table 2-4. Typical Web Subdirectories 638 Directory Description 639 640 `css/` 641 642 Contains style sheets with a `.css` extension. 643 644 `images/` 645 646 Contains images with a `.jpg`, `.png`, or `.gif` format. 647 648 `js/` 649 650 Holds JavaScript files with a `.js` extension. 651 652 `uploads/` 653 654 Must contain the files uploaded by the users. Even though the directory usually contains images, it is distinct from the images directory so that the synchronization of the development and production servers does not affect the uploaded images. 580 Table 2-4 - Typical Web Subdirectories 581 582 Directory | Description 583 ---------- | ----------- 584 `css/` | Contains style sheets with a `.css` extension. 585 `images/` | Contains images with a `.jpg`, `.png`, or `.gif` format. 586 `js/` | Holds JavaScript files with a `.js` extension. 587 `uploads/` | Must contain the files uploaded by the users. Even though the directory usually contains images, it is distinct from the images directory so that the synchronization of the development and production servers does not affect the uploaded images. 655 588 656 589 >**NOTE** doc/branches/1.0/book/04-The-Basics-of-Page-Creation.txt
r3348 r3372 53 53 The 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. 54 54 55 >**NOTE* 55 >**NOTE** 56 56 >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. 57 57 … … 94 94 >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. 95 95 96 - 97 96 98 >**SIDEBAR** 97 99 >URLs are part of the response … … 99 101 >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: 100 102 > 101 > http://localhost/myapp_dev.php/article/index?id=123103 > http://localhost/myapp_dev.php/article/index?id=123 102 104 > 103 105 >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: 104 106 > 105 > http://localhost/articles/europe/france/finance.html107 > http://localhost/articles/europe/france/finance.html 106 108 > 107 109 >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: 108 110 > 109 > http://localhost/articles/tagged/finance+france+euro111 > http://localhost/articles/tagged/finance+france+euro 110 112 > 111 113 >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. … … 217 219 >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: 218 220 > 219 > 220 > [php] 221 > <?php 222 > $card_list = array( 223 > 'VISA' => 'Visa', 224 > 'MAST' => 'MasterCard', 225 > 'AMEX' => 'American Express', 226 > 'DISC' => 'Discover'); 227 > echo select_tag('cc_type', options_for_select($card_list, 'AMEX')); 228 > ?> 229 > 221 > [php] 222 > <?php 223 > $card_list = array( 224 > 'VISA' => 'Visa', 225 > 'MAST' => 'MasterCard', 226 > 'AMEX' => 'American Express', 227 > 'DISC' => 'Discover'); 228 > echo select_tag('cc_type', options_for_select($card_list, 'AMEX')); 229 > ?> 230 230 > 231 231 >This outputs the following HTML: 232 232 > 233 > 234 > [php] 235 > <select name="cc_type" id="cc_type"> 236 > <option value="VISA">Visa</option> 237 > <option value="MAST">MasterCard</option> 238 > <option value="AMEX" selected="selected">American Express</option> 239 > <option value="DISC">Discover</option> 240 > </select> 241 > 233 > [php] 234 > <select name="cc_type" id="cc_type"> 235 > <option value="VISA">Visa</option> 236 > <option value="MAST">MasterCard</option> 237 > <option value="AMEX" selected="selected">American Express</option> 238 > <option value="DISC">Discover</option> 239 > </select> 242 240 > 243 241 >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. … … 301 299 Whenever 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. 302 300 303 >**NOTE* 301 >**NOTE** 304 302 >Because it requires an additional parsing and transformation, the string syntax is a little slower than the array syntax. 305 303 doc/branches/1.0/book/05-Configuring-Symfony.txt
r3348 r3372 160 160 * You miss a space between a key and its value: 161 161 162 key1:value1 # A space is missing after the :162 key1:value1 # A space is missing after the : 163 163 164 164 * Keys in a sequence are not indented the same way: 165 165 166 all:167 key1: value1168 key2: value2 # Indentation is not the same as the other sequence members169 key3: value3166 all: 167 key1: value1 168 key2: value2 # Indentation is not the same as the other sequence members 169 key3: value3 170 170 171 171 * There is a reserved YAML character in a key or a value, without string delimiters: 172 172 173 message: tell him: go way # :, [, ], { and } are reserved in YAML174 message: 'tell him: go way' # Correct syntax173 message: tell him: go way # :, [, ], { and } are reserved in YAML 174 message: 'tell him: go way' # Correct syntax 175 175 176 176 * You are modifying a commented line: 177 177 178 # key: value # Will never be taken into account due to the leading #178 # key: value # Will never be taken into account due to the leading # 179 179 180 180 * You set values with the same key name twice at the same level: 181 181 182 key1: value1183 key2: value2184 key1: value3 # key1 is defined twice, the value is the last one defined182 key1: value1 183 key2: value2 184 key1: value3 # key1 is defined twice, the value is the last one defined 185 185 186 186 * You think that the setting takes a special type, while it is always a string, until you convert it: 187 187 188 income: 12,345 # Until you convert it, this is still a string188 income: 12,345 # Until you convert it, this is still a string 189 189 190 190 Overview of the Configuration Files … … 244 244 > 245 245 > 246 > symfony/ # Private area247 > apps/248 > batch/249 > cache/250 > ...251 > www/ # Public area252 > images/253 > css/254 > js/255 > index.php246 > symfony/ # Private area 247 > apps/ 248 > batch/ 249 > cache/ 250 > ... 251 > www/ # Public area 252 > images/ 253 > css/ 254 > js/ 255 > index.php 256 256 > 257 257 > 258 258 >In this case, the root directory is the `symfony/` directory. So the `index.php` front controller simply needs to define the `SF_ROOT_DIR` as follows for the application to work: 259 259 > 260 > define('SF_ROOT_DIR', dirname(__FILE__).'/../symfony');260 > define('SF_ROOT_DIR', dirname(__FILE__).'/../symfony'); 261 261 262 262 Chapter 19 will give you more information about how to tweak symfony to make it work on a specific directory structure. … … 309 309 310 310 >**SIDEBAR** 311 > **Too many files?311 >Too many files? 312 312 > 313 313 >You might be overwhelmed by the number of configuration files present in the application. But please keep the following in mind: … … 350 350 > 351 351 > 352 > http://localhost/myapp_dev.php/mymodule/index353 > _________ _____________354 > server environment352 > http://localhost/myapp_dev.php/mymodule/index 353 > _________ _____________ 354 > server environment 355 355 > 356 356 > doc/branches/1.0/book/06-Inside-the-Controller-Layer.txt
r3348 r3372 430 430 You're familiar with the `getRequestParameter('myparam')` method, used to retrieve the value of a request parameter by its name. As a matter of fact, this method is a proxy for a chain of calls to the request's parameter holder `getRequest()->getParameter('myparam')`. The action class has access to the request object, called `sfWebRequest` in symfony, and to all its methods, via the `getRequest()` method. Table 6-1 lists the most useful `sfWebRequest` methods. 431 431 432 Table 6-1. Methods of the `sfWebRequest` Object 433 Name Function Sample Output 434 Request Information 435 436 `getMethod()` 437 438 Request method 439 440 Returns `sfRequest::GET` or `sfRequest::POST` constants 441 442 `getMethodName()` 443 444 Request method name 445 446 `'POST'` 447 448 `getHttpHeader('Server')` 449 450 Value of a given HTTP header 451 452 `'Apache/2.0.59 (Unix) DAV/2 PHP/5.1.6'` 453 454 `getCookie('foo')` 455 456 Value of a named cookie 457 458 `'bar'` 459 460 `isXmlHttpRequest()`* 461 462 Is it an Ajax request? 463 464 `true` 465 466 `isSecure()` 467 468 Is it an SSL request? 469 470 `true` 471 472 Request Parameters 473 474 `hasParameter('foo')` 475 476 Is a parameter present in the request? 477 478 `true` 479 480 `getParameter('foo')` 481 482 Value of a named parameter 483 484 `'bar'` 485 486 `getParameterHolder()->getAll()` 487 488 Array of all request parameters 489 490 URI-Related Information 491 492 `getUri()` 493 494 Full URI 495 496 `'http://localhost/myapp_dev.php/mymodule/myaction'` 497 498 `getPathInfo()` 499 500 Path info 501 502 `'/mymodule/myaction'` 503 504 `getReferer()`** 505 506 Referrer 507 508 `'http://localhost/myapp_dev.php/'` 509 510 `getHost()` 511 512 Host name 513 514 `'localhost'` 515 516 `getScriptName()` 517 518 Front controller path and name 519 520 `'myapp_dev.php'` 521 522 Client Browser Information 523 524 `getLanguages()` 525 526 Array of accepted languages 527 528 `Array( ` ` [0] => fr ` ` [1] => fr_FR ` ` [2] => en_US ` ` [3] => en )` 529 530 `getCharsets()` 531 532 Array of accepted charsets 533 534 `Array( ` ` [0] => ISO-8859-1 ` ` [1] => UTF-8 ` ` [2] => * )` 535 536 getAcceptableContentType() 537 538 Array of accepted content types 539 540 `Array( [0] => text/xml [1] => text/html` 541 542 *Works only with prototype **Sometimes blocked by proxies 432 Table 6-1 - Methods of the `sfWebRequest` Object 433 434 Name | Function | Sample Output 435 -------------------------------- | -------------------------------------- | ----------------------------------------------------------------------- 436 **Request Information** | | 437 `getMethod()` | Request method | Returns `sfRequest::GET` or `sfRequest::POST` constants 438 `getMethodName()` | Request method name | `'POST'` 439 `getHttpHeader('Server')` | Value of a given HTTP header | `'Apache/2.0.59 (Unix) DAV/2 PHP/5.1.6'` 440 `getCookie('foo')` | Value of a named cookie | `'bar'` 441 `isXmlHttpRequest()`* | Is it an Ajax request? | `true` 442 `isSecure()` | Is it an SSL request? | `true` 443 **Request Parameters** | | 444 `hasParameter('foo')` | Is a parameter present in the request? | `true` 445 `getParameter('foo')` | Value of a named parameter | `'bar'` 446 `getParameterHolder()->getAll()` | Array of all request parameters | 447 **URI-Related Information** | | 448 `getUri()` | Full URI | `'http://localhost/myapp_dev.php/mymodule/myaction'` 449 `getPathInfo()` | Path info | `'/mymodule/myaction'` 450 `getReferer()`** | Referrer | `'http://localhost/myapp_dev.php/'` 451 `getHost()` | Host name | `'localhost'` 452 `getScriptName()` | Front controller path and name | `'myapp_dev.php'` 453 **Client Browser Information** | | 454 `getLanguages()` | Array of accepted languages | `Array( ` ` [0] => fr ` ` [1] => fr_FR ` ` [2] => en_US ` ` [3] => en )` 455 `getCharsets()` | Array of accepted charsets | `Array( ` ` [0] => ISO-8859-1 ` ` [1] => UTF-8 ` ` [2] => * )` 456 getAcceptableContentType() | Array of accepted content types | `Array( [0] => text/xml [1] => text/html` 457 458 * *Works only with prototype* 459 460 ** *Sometimes blocked by proxies* 543 461 544 462 The `sfActions` class offers a few proxies to access the request methods more quickly, as shown in Listing 6-15. doc/branches/1.0/book/07-Inside-the-View-Layer.txt
r3348 r3372 4 4 The view is responsible for rendering the output correlated to a particular action. In symfony, the view consists of several parts, with each part designed to be easily modified by the person who usually works with it. 5 5 6 * Web designers generally work on the templates (the presentation of the current action data) and on the layout (containing the code common to all pages). These are written in HTML with small embedded chunks of PHP, which are mostly calls to helpers. 7 8 * For reusability, developers usually package template code fragments into partials or components. They use slots and component slots to affect more than one zone of the layout. Web designers can work on these template fragments as well. 9 10 * Developers focus on the YAML view configuration file (setting the properties of the response and other interface elements) and on the response object. When dealing with variables in the templates, the risks of cross-site scripting must not be ignored, and a good comprehension of output escaping techniques is required to safely record user data. 6 * Web designers generally work on the templates (the presentation of the current action data) and on the layout (containing the code common to all pages). These are written in HTML with small embedded chunks of PHP, which are mostly calls to helpers. 7 * For reusability, developers usually package template code fragments into partials or components. They use slots and component slots to affect more than one zone of the layout. Web designers can work on these template fragments as well. 8 * Developers focus on the YAML view configuration file (setting the properties of the response and other interface elements) and on the response object. When dealing with variables in the templates, the risks of cross-site scripting must not be ignored, and a good comprehension of output escaping techniques is required to safely record user data. 11 9 12 10 But whatever your role is, you will find useful tools to speed up the tedious job of presenting the results of the action. This chapter covers all of these tools. … … 47 45 } 48 46 49 As a matter of fact, the input_tag() function built into symfony is a little more complicated than that, as it accepts a third parameter to add other attributes to the <input>tag. You can check its complete syntax and options in the online API documentation (http://www.symfony-project.com/api/symfony.html).47 As a matter of fact, the input_tag() function built into symfony is a little more complicated than that, as it accepts a third parameter to add other attributes to the `<input>` tag. You can check its complete syntax and options in the online API documentation (http://www.symfony-project.com/api/symfony.html). 50 48 51 49 Most of the time, helpers carry intelligence and save you long and complex coding: … … 311 309 A component is like an action, except it's much faster. The logic of a component is kept in a class inheriting from `sfComponents`, located in an `action/components.class.php` file. Its presentation is kept in a partial. Methods of the `sfComponents` class start with the word `execute`, just like actions, and they can pass variables to their presentation counterpart in the same way that actions can pass variables. Partials that serve as presentation for components are named by the component (without the leading `execute`, but with an underscore instead). Table 7-1 compares the naming conventions for actions and components. 312 310 313 Table 7-1. Action and Component Naming Conventions 314 Convention Actions Components 315 316 Logic file 317 318 `actions.class.php` 319 320 `components.class.php` 321 322 Logic class extends 323 324 `sfActions` 325 326 `sfComponents` 327 328 Method naming 329 330 `executeMyAction()` 331 332 `executeMyComponent()` 333 334 Presentation file naming 335 336 `myActionSuccess.php` 337 338 `_myComponent.php` 311 Table 7-1 - Action and Component Naming Conventions 312 313 Convention | Actions | Components 314 ------------------------ | --------------------- | ---------------------- 315 Logic file | `actions.class.php` | `components.class.php` 316 Logic class extends | `sfActions` | `sfComponents` 317 Method naming | `executeMyAction()` | `executeMyComponent()` 318 Presentation file naming | `myActionSuccess.php` | `_myComponent.php` 339 319 340 320 >**TIP** … … 460 440 > 461 441 > 462 > myproject/463 > apps/464 > application1/465 > templates/ # Layouts for application 1466 > modules/467 > module1/468 > templates/ # Templates and partials for module 1469 > module2/470 > templates/ # Templates and partials for module 2471 > module3/472 > templates/ # Templates and partials for module 3442 > myproject/ 443 > apps/ 444 > application1/ 445 > templates/ # Layouts for application 1 446 > modules/ 447 > module1/ 448 > templates/ # Templates and partials for module 1 449 > module2/ 450 > templates/ # Templates and partials for module 2 451 > module3/ 452 > templates/ # Templates and partials for module 3 473 453 > 474 454 > … … 713 693 714 694 >**NOTE** 715 >Style sheet and JavaScript inclusions in the response are performed by a filter called sfCommonFilter. It looks for a <head> tag in the response, and adds the <link> and <script>just before the closing `</head>`. This means that the inclusion can't take place if there is no `<head>` tag in your layout or templates.695 >Style sheet and JavaScript inclusions in the response are performed by a filter called sfCommonFilter. It looks for a `<head>` tag in the response, and adds the `<link>` and `<script>` just before the closing `</head>`. This means that the inclusion can't take place if there is no `<head>` tag in your layout or templates. 716 696 717 697 Remember that the configuration cascade principle applies, so any file inclusion defined in the application `view.yml` makes it appear in every page of the application. Listings 7-27, 7-28, and 7-29 demonstrate this principle. doc/branches/1.0/book/08-Inside-the-Model-Layer.txt
r3348 r3372 187 187 But first, let's make sure we share the same vocabulary. Relational and object data model use similar concepts, but they each have their own nomenclature: 188 188 189 Relational Object-Oriented 190 191 Table 192 193 Class 194 195 Row, record 196 197 Object 198 199 Field, column 200 201 Property 189 Relational | Object-Oriented 190 ------------- | --------------- 191 Table | Class 192 Row, record | Object 193 Field, column | Property 202 194 203 195 ### Retrieving the Column Value … … 271 263 The `getArticle()` method returns an object of class `Article`, which benefits from the `getTitle()` accessor. This is much better than doing the join yourself, which may take a few lines of code (starting from the `$comment->getArticleId()` call). 272 264 273 The `$comments` variable in Listing 8-10 contains an array of objects of class `Comment`. You can display the first one with `$comments[0]` or iterate through the collection with `foreach `($comments as $comment)`.265 The `$comments` variable in Listing 8-10 contains an array of objects of class `Comment`. You can display the first one with `$comments[0]` or iterate through the collection with `foreach ($comments as $comment)`. 274 266 275 267 >**NOTE** … … 360 352 >Why use `CommentPeer::AUTHOR` instead of `blog_comment.AUTHOR`, which is the way it will be output in the SQL query anyway? Suppose that you need to change the name of the author field to `contributor` in the database. If you used `blog_comment.AUTHOR`, you would have to change it in every call to the model. On the other hand, by using `CommentPeer::AUTHOR`, you simply need to change the column name in the `schema.yml` file, keep `phpName` as `AUTHOR`, and rebuild the model. 361 353 362 Table 8-1 - compares the SQL syntax with the `Criteria` object syntax. 363 364 Table 8-1. SQL and Criteria Object Syntax 365 SQL Criteria 366 367 `WHERE column = value` 368 369 `->add(column, value);` 370 371 `WHERE column <> value` 372 373 `->add(column, value, Criteria::NOT_EQUAL);` 374 375 Other Comparison Operators 376 377 `> , <` 378 379 `Criteria::GREATER_THAN, Criteria::LESS_THAN` 380 381 `>=, <=` 382 383 `Criteria::GREATER_EQUAL, Criteria::LESS_EQUAL` 384 385 `IS NULL, IS NOT NULL` 386 387 `Criteria::ISNULL, Criteria::ISNOTNULL` 388 389 `LIKE, ILIKE` 390 391 `Criteria::LIKE, Criteria::ILIKE` 392 393 `IN, NOT IN` 394 395 `Criteria::IN, Criteria::NOT_IN` 396 397 Other SQL Keywords 398 399 `ORDER BY column ASC` 400 401 `->addAscendingOrderByColumn(column);` 402 403 `ORDER BY column DESC` 404 405 `->addDescendingOrderByColumn(column);` 406 407 `LIMIT limit` 408 409 `->setLimit(limit)` 410 411 `OFFSET offset` 412 413 `->setOffset(offset) ` 414 415 `FROM table1, table2 WHERE table1.col1 = table2.col2` 416 417 `->addJoin(col1, col2)` 418 419 `FROM table1 LEFT JOIN table2 ON table1.col1 = table2.col2` 420 421 `->addJoin(col1, col2, Criteria::LEFT_JOIN)` 422 423 `FROM table1 RIGHT JOIN table2 ON table1.col1 = table2.col2` 424 425 `->addJoin(col1, col2, Criteria::RIGHT_JOIN)` 354 Table 8-1 compares the SQL syntax with the `Criteria` object syntax. 355 356 Table 8-1 - SQL and Criteria Object Syntax 357 358 SQL | Criteria 359 ------------------------------------------------------------ | ----------------------------------------------- 360 `WHERE column = value` | `->add(column, value);` 361 `WHERE column <> value` | `->add(column, value, Criteria::NOT_EQUAL);` 362 **Other Comparison Operators** | 363 `> , <` | `Criteria::GREATER_THAN, Criteria::LESS_THAN` 364 `>=, <=` | `Criteria::GREATER_EQUAL, Criteria::LESS_EQUAL` 365 `IS NULL, IS NOT NULL` | `Criteria::ISNULL, Criteria::ISNOTNULL` 366 `LIKE, ILIKE` | `Criteria::LIKE, Criteria::ILIKE` 367 `IN, NOT IN` | `Criteria::IN, Criteria::NOT_IN` 368 **Other SQL Keywords** | 369 `ORDER BY column ASC` | `->addAscendingOrderByColumn(column);` 370 `ORDER BY column DESC` | `->addDescendingOrderByColumn(column);` 371 `LIMIT limit` | `->setLimit(limit)` 372 `OFFSET offset` | `->setOffset(offset) ` 373 `FROM table1, table2 WHERE table1.col1 = table2.col2` | `->addJoin(col1, col2)` 374 `FROM table1 LEFT JOIN table2 ON table1.col1 = table2.col2` | `->addJoin(col1, col2, Criteria::LEFT_JOIN)` 375 `FROM table1 RIGHT JOIN table2 ON table1.col1 = table2.col2` | `->addJoin(col1, col2, Criteria::RIGHT_JOIN)` 426 376 427 377 >**TIP** … … 520 470 >For example, imagine the code needed in a blog to retrieve the ten most popular articles for a given tag (passed as request parameter). This code should not be in an action, but in the model. In fact, if you need to display this list in a template, the action should simply look like this: 521 471 > 522 > [php]523 > public function executeShowPopularArticlesForTag()524 > {525 > $tag = TagPeer::retrieveByName($this->getRequestParameter('tag'));526 > $this->foward404Unless($tag);527 > $this->articles = $tag->getPopularArticles(10);528 > }472 > [php] 473 > public function executeShowPopularArticlesForTag() 474 > { 475 > $tag = TagPeer::retrieveByName($this->getRequestParameter('tag')); 476 > $this->foward404Unless($tag); 477 > $this->articles = $tag->getPopularArticles(10); 478 > } 529 479 > 530 480 >The action creates an object of class `Tag` from the request parameter. Then all the code needed to query the database is located in a ->getPopularArticles() method of this class. It makes the action more readable, and the model code can easily be reused in another action. … … 724 674 > 725 675 > 726 > // In config/business-schema.yml727 > propel:728 > blog_article:729 > _attributes: { phpName: Article }730 > id:731 > title: varchar(50)732 > 733 > // In config/stats-schema.yml734 > propel:735 > stats_hit:736 > _attributes: { phpName: Hit }737 > id:738 > resource: varchar(100)739 > created_at:676 > // In config/business-schema.yml 677 > propel: 678 > blog_article: 679 > _attributes: { phpName: Article } 680 > id: 681 > title: varchar(50) 682 > 683 > // In config/stats-schema.yml 684 > propel: 685 > stats_hit: 686 > _attributes: { phpName: Hit } 687 > id: 688 > resource: varchar(100) 689 > created_at: 740 690 > 741 691 > … … 745 695 > 746 696 > 747 > // In config/business-schema.yml748 > propel:749 > blog_article:750 > _attributes: { phpName: Article, package: lib.model.business }751 > id:752 > title: varchar(50)753 > 754 > // In config/stats-schema.yml755 > propel_bis:756 > stats_hit:757 > _attributes: { phpName: Hit, package.lib.model.stat }758 > id:759 > resource: varchar(100)760 > created_at:697 > // In config/business-schema.yml 698 > propel: 699 > blog_article: 700 > _attributes: { phpName: Article, package: lib.model.business } 701 > id: 702 > title: varchar(50) 703 > 704 > // In config/stats-schema.yml 705 > propel_bis: 706 > stats_hit: 707 > _attributes: { phpName: Hit, package.lib.model.stat } 708 > id: 709 > resource: varchar(100) 710 > created_at: 761 711 > 762 712 > … … 983 933 > 984 934 > 985 > propel.database.createUrl = mysql://login:passwd@localhost986 > propel.database.url = mysql://login:passwd@localhost/blog935 > propel.database.createUrl = mysql://login:passwd@localhost 936 > propel.database.url = mysql://login:passwd@localhost/blog 987 937 > 988 938 > … … 990 940 > 991 941 > 992 > // Base classes are autoloaded in symfony993 > // Set this to true to use include_once statements instead994 > // (Small negative impact on performance)995 > propel.builder.addIncludes = false996 > 997 > // Generated classes are not commented by default998 > // Set this to true to add comments to Base classes999 > // (Small negative impact on performance)1000 > propel.builder.addComments = false1001 > 1002 > // Behaviors are not handled by default1003 > // Set this to true to be able to handle them1004 > propel.builder.AddBehaviors = false942 > // Base classes are autoloaded in symfony 943 > // Set this to true to use include_once statements instead 944 > // (Small negative impact on performance) 945 > propel.builder.addIncludes = false 946 > 947 > // Generated classes are not commented by default 948 > // Set this to true to add comments to Base classes 949 > // (Small negative impact on performance) 950 > propel.builder.addComments = false 951 > 952 > // Behaviors are not handled by default 953 > // Set this to true to be able to handle them 954 > propel.builder.AddBehaviors = false 1005 955 > 1006 956 > doc/branches/1.0/book/09-Links-and-the-Routing-System.txt
r3348 r3372 349 349 >You don't need to mention a file extension for an asset. Symfony automatically adds `.png`, `.js`, or `.css` to an image, JavaScript, or style sheet helper call. Also, symfony will automatically look for those assets in the `web/images/`, `web/js/`, and `web/css/` directories. Of course, if you want to include a specific file format or a file from a specific location, just use the full file name or the full file path as an argument. And don't bother to specify an `alt` attribute if your media file has an explicit name, since symfony will determine it for you. 350 350 > 351 > [php]352 > <?php echo image_tag('test') ?>353 > <?php echo image_tag('test.gif') ?>354 > <?php echo image_tag('/my_images/test.gif') ?>355 > => <img href="/images/test.png" alt="Test" />356 > <img href="/images/test.gif" alt="Test" />357 > <img href="/my_images/test.gif" alt="Test" />351 > [php] 352 > <?php echo image_tag('test') ?> 353 > <?php echo image_tag('test.gif') ?> 354 > <?php echo image_tag('/my_images/test.gif') ?> 355 > => <img href="/images/test.png" alt="Test" /> 356 > <img href="/images/test.gif" alt="Test" /> 357 > <img href="/my_images/test.gif" alt="Test" /> 358 358 > 359 359 >To fix the size of an image, use the `size` attribute. It expects a width and a height in pixels, separated by an `x`. 360 360 > 361 > [php]362 > <?php echo image_tag('test', 'size=100x20')) ?>363 > => <img href="/images/test.png" alt="Test" width="100" height="20"/>361 > [php] 362 > <?php echo image_tag('test', 'size=100x20')) ?> 363 > => <img href="/images/test.png" alt="Test" width="100" height="20"/> 364 364 > 365 365 >If you want the asset inclusion to be done in the `<head>` section (for JavaScript files and style sheets), you should use the `use_stylesheet()` and `use_javascript()` helpers in your templates, instead of the `_tag()` versions in the layout. They add the asset to the response, and these assets are included before the `</head>` tag is sent to the browser. … … 393 393 >The `mail_to()` helper takes two parameters: the actual e-mail address and the string that should be displayed. Additional options accept an `encode` parameter to output something pretty unreadable in HTML, which is understood by browsers but not by robots. 394 394 > 395 > [php]396 > <?php echo mail_to('myaddress@mydomain.com', 'contact') ?>397 > => <a href="mailto:myaddress@mydomain.com'>contact</a>398 > <?php echo mail_to('myaddress@mydomain.com', 'contact', 'encode=true') ?>399 > => <a href="ma... om">ct... ess</a>395 > [php] 396 > <?php echo mail_to('myaddress@mydomain.com', 'contact') ?> 397 > => <a href="mailto:myaddress@mydomain.com'>contact</a> 398 > <?php echo mail_to('myaddress@mydomain.com', 'contact', 'encode=true') ?> 399 > => <a href="ma... om">ct... ess</a> 400 400 > 401 401 >Encoded e-mail messages are composed of characters transformed by a random decimal and hexadecimal entity encoder. This trick stops most of the address-harvesting spambots for now, but be aware that the harvesting techniques evolve rapidly. … … 490 490 >A good security guideline for routing is to hide primary keys and replace them with significant strings as much as possible. What if you wanted to give access to articles from their title rather than from their ID? It would make external URLs look like this: 491 491 > 492 > http://www.example.com/article/Finance_in_France492 > http://www.example.com/article/Finance_in_France 493 493 > 494 494 >To that extent, you need to create a new `permalink` action, which will use a `slug` parameter instead of an `id` one, and add a new rule for it: 495 495 > 496 > <