Changeset 9465
- Timestamp:
- 06/08/08 21:57:41 (5 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
doc/branches/1.1/book/02-Exploring-Symfony-s-Code.txt
r9380 r9465 9 9 Symfony is based on the classic web design pattern known as the MVC architecture, which consists of three levels: 10 10 11 * The model represents the information on which the application operates--its business logic.12 * The view renders the model into a web page suitable for interaction with the user.13 * The controller responds to user actions and invokes changes on the model or view as appropriate.11 * The Model represents the information on which the application operates--its business logic. 12 * The View renders the model into a web page suitable for interaction with the user. 13 * The Controller responds to user actions and invokes changes on the model or view as appropriate. 14 14 15 15 Figure 2-1 illustrates the MVC pattern. … … 106 106 // Requiring the view 107 107 require('view.php'); 108 109 ?>110 108 111 109 The HTML code, containing template-like PHP syntax, is stored in a view script, as shown in Listing 2-3. … … 132 130 </html> 133 131 134 A good rule of thumb to determine whether the view is clean enough is that it should contain only a minimum amount of PHP code, in order to be understood by an HTML designer without PHP knowledge. The most common statements in views are echo, if/endif, foreach/endforeach, and that's about all. Also, there should not be PHP code echoing HTML tags.132 A good rule of thumb to determine whether the view is clean enough is that it should contain only a minimum amount of PHP code, in order to be understood by an HTML designer without PHP knowledge. The most common statements in views are `echo`, `if/endif`, `foreach/endforeach`, and that's about all. Also, there should not be PHP code echoing HTML tags. 135 133 136 134 All the logic is moved to the controller script, and contains only pure PHP code, with no HTML inside. As a matter of fact, you should imagine that the same controller could be reused for a totally different presentation, perhaps in a PDF file or an XML structure. … … 167 165 } 168 166 169 ?>170 171 167 The revised controller is presented in Listing 2-5. 172 168 … … 184 180 // Requiring the view 185 181 require('view.php'); 186 187 ?>188 182 189 183 The controller becomes easier to read. Its sole task is to get the data from the model and pass it to the view. In more complex applications, the controller also deals with the request, the user session, the authentication, and so on. The use of explicit names for the functions of the model even makes code comments unnecessary in the controller. … … 253 247 return $posts; 254 248 } 255 256 ?>257 249 258 250 You can check that no database-engine dependent functions can be found in the data access layer, making it database-independent. Additionally, the functions created in the database abstraction layer can be reused for many other model functions that need access to the database. … … 287 279 $content = include('mytemplate.php'); 288 280 289 ?>290 291 281 Listing 2-10 - The Layout Part of the View 292 282 … … 351 341 [php] 352 342 <?php 343 353 344 class weblogActions extends sfActions 354 345 { … … 359 350 } 360 351 361 ?>362 363 352 Listing 2-12 - `list` Template, in `myproject/apps/myapp/modules/weblog/templates/listSuccess.php` 364 353 365 354 [php] 355 <?php slot('title', 'List of Posts') ?> 356 366 357 <h1>List of Posts</h1> 367 358 <table> … … 375 366 </table> 376 367 377 Listing 2-13 - `list` View, in `myproject/apps/myapp/modules/weblog/config/view.yml` 378 379 listSuccess: 380 metas: { title: List of Posts } 381 382 In addition, you will still need to define a layout, as shown in Listing 2-14, but it will be reused many times. 383 384 Listing 2-14 - Layout, in `myproject/apps/myapp/templates/layout.php` 368 In addition, you will still need to define a layout, as shown in Listing 2-13, but it will be reused many times. 369 370 Listing 2-13 - Layout, in `myproject/apps/myapp/templates/layout.php` 385 371 386 372 [php] 387 373 <html> 388 374 <head> 389 < ?php echo include_title() ?>375 <title><?php include_slot('title') ?></title> 390 376 </head> 391 377 <body> 392 <?php echo $sf_ data->getRaw('sf_content')?>378 <?php echo $sf_content ?> 393 379 </body> 394 380 </html> … … 403 389 * `sfRequest` stores all the request elements (parameters, cookies, headers, and so on). 404 390 * `sfResponse` contains the response headers and contents. This is the object that will eventually be converted to an HTML response and be sent to the user. 405 * The context singleton(retrieved by `sfContext::getInstance()`) stores a reference to all the core objects and the current configuration; it is accessible from everywhere.391 * The context (retrieved by `sfContext::getInstance()`) stores a reference to all the core objects and the current configuration; it is accessible from everywhere. 406 392 407 393 You will learn more about these objects in Chapter 6. … … 430 416 >If this represents too many levels for a beginning project, it is very easy to group all actions into one single module, so that the file structure can be kept simple. When the application gets more complex, it will be time to organize actions into separate modules. As mentioned in Chapter 1, rewriting code to improve its structure or readability (but preserving its behavior) is called refactoring, and you will do this a lot when applying RAD principles. 431 417 432 Figure 2-3 shows a sample code organization for a weblog project, in a project/ application/module/action structure. But be aware that the actual file tree structure of the project will differ from the setup shown in the figure.418 Figure 2-3 shows a sample code organization for a weblog project, in a project/application/module/action structure. But be aware that the actual file tree structure of the project will differ from the setup shown in the figure. 433 419 434 420 Figure 2-3 - Example of code organization … … 458 444 frontend/ 459 445 backend/ 460 batch/461 446 cache/ 462 447 config/ … … 469 454 plugins/ 470 455 test/ 456 bootstrap/ 471 457 unit/ 472 458 functional/ … … 484 470 ---------- | ------------ 485 471 `apps/` | Contains one directory for each application of the project (typically, `frontend` and `backend` for the front and back office). 486 `batch/` | Contains PHP scripts called from a command line or a scheduler, to run batch processes.487 472 `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. 488 473 `config/` | Holds the general configuration of the project. … … 507 492 templates/ 508 493 layout.php 509 error.php510 error.txt511 494 512 495 Table 2-2 describes the application subdirectories. … … 577 560 `images/` | Contains images with a `.jpg`, `.png`, or `.gif` format. 578 561 `js/` | Holds JavaScript files with a `.js` extension. 579 `uploads/` | Mustcontain 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.562 `uploads/` | Can 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 563 581 564 >**NOTE** … … 589 572 ### Parameter Holders 590 573 591 Many of the symfony classes contain a parameter holder. It is a convenient way to encapsulate attributes with clean getter and setter methods. For instance, the sfRequest class holds a parameter holder that you can retrieve by calling the `getParameterHolder()` method. Each parameter holder stores data the same way, as illustrated in Listing 2-15.592 593 Listing 2-1 5- Using the `sfRequest` Parameter Holder574 Many of the symfony classes contain a parameter holder. It is a convenient way to encapsulate attributes with clean getter and setter methods. For instance, the `sfRequest` class holds a parameter holder that you can retrieve by calling the `getParameterHolder()` method. Each parameter holder stores data the same way, as illustrated in Listing 2-14. 575 576 Listing 2-14 - Using the `sfRequest` Parameter Holder 594 577 595 578 [php] … … 598 581 => 'bar' 599 582 600 Most of the classes using a parameter holder provide proxy methods to shorten the code needed for get/set operations. This is the case for the `sfRequest` object, so you can do the same as in Listing 2-1 5 with the code of Listing 2-16.601 602 Listing 2-1 6- Using the `sfRequest` Parameter Holder Proxy Methods583 Most of the classes using a parameter holder provide proxy methods to shorten the code needed for get/set operations. This is the case for the `sfRequest` object, so you can do the same as in Listing 2-14 with the code of Listing 2-15. 584 585 Listing 2-15 - Using the `sfRequest` Parameter Holder Proxy Methods 603 586 604 587 [php] … … 607 590 => 'bar' 608 591 609 The parameter holder getter accepts a default value as a second argument. This provides a useful fallback mechanism that is much more concise than possible with a conditional statement. See Listing 2-1 7for an example.610 611 Listing 2-1 7- Using the Attribute Holder Getter's Default Value592 The parameter holder getter accepts a default value as a second argument. This provides a useful fallback mechanism that is much more concise than possible with a conditional statement. See Listing 2-16 for an example. 593 594 Listing 2-16 - Using the Attribute Holder Getter's Default Value 612 595 613 596 [php] … … 631 614 => default 632 615 633 Some symfony core classes also use a parameter holder that support namespaces (thanks to the `sfNamespacedParameterHolder` class). If you specify a third argument to a setter or a getter, it is used as a namespace, and the parameter will be defined only within that namespace. Listing 2-1 8shows an example.634 635 Listing 2-1 8- Using the `sfUser` Parameter Holder Namespace616 Some symfony core classes also use a parameter holder that support namespaces (thanks to the `sfNamespacedParameterHolder` class). If you specify a third argument to a setter or a getter, it is used as a namespace, and the parameter will be defined only within that namespace. Listing 2-17 shows an example. 617 618 Listing 2-17 - Using the `sfUser` Parameter Holder Namespace 636 619 637 620 [php] … … 643 626 => 'bar2' 644 627 645 Of course, you can add a parameter holder to your own classes to take advantage of its syntax facilities. Listing 2-1 9shows how to define a class with a parameter holder.646 647 Listing 2-1 9- Adding a Parameter Holder to a Class628 Of course, you can add a parameter holder to your own classes to take advantage of its syntax facilities. Listing 2-18 shows how to define a class with a parameter holder. 629 630 Listing 2-18 - Adding a Parameter Holder to a Class 648 631 649 632 [php] … … 666 649 ### Constants 667 650 668 Surprisingly, you will find very few constants in symfony. This is because constants have a major drawback in PHP: you can't change their value once they are defined. So symfony uses its own configuration object, called sfConfig, which replaces constants. It provides static methods to access parameters from everywhere. Listing 2-20 demonstrates the use of sfConfigclass methods.669 670 Listing 2- 20- Using the `sfConfig` Class Methods Instead of Constants651 Surprisingly, you will not find any constant in symfony. This is because constants have a major drawback in PHP: you can't change their value once they are defined. So symfony uses its own configuration object, called `sfConfig`, which replaces constants. It provides static methods to access parameters from everywhere. Listing 2-19 demonstrates the use of `sfConfig` class methods. 652 653 Listing 2-19 - Using the `sfConfig` Class Methods Instead of Constants 671 654 672 655 [php] … … 696 679 Symfony will then look for a `MyClass` definition in all files ending with `php` in one of the project's `lib/` directories. If the class definition is found, it will be included automatically. 697 680 698 So if you store all your classes in lib/directories, you don't need to include classes anymore. That's why the symfony projects usually do not contain any `include` or `require` statements.681 So if you store all your classes in `lib/` directories, you don't need to include classes anymore. That's why the symfony projects usually do not contain any `include` or `require` statements. 699 682 700 683 >**NOTE** doc/branches/1.1/book/03-Running-Symfony.txt
r8283 r9465 167 167 168 168 apps/ 169 batch/170 169 cache/ 171 170 config/ doc/branches/1.1/book/05-Configuring-Symfony.txt
r8340 r9465 249 249 > symfony/ # Private area 250 250 > apps/ 251 > batch/252 251 > cache/ 253 252 > ... doc/branches/1.1/book/19-Mastering-Symfony-s-Configuration-Files.txt
r9460 r9465 347 347 symfony/ # Private area 348 348 apps/ 349 batch/350 349 cache/ 351 350 ...