Development

Changeset 7362

You must first sign up to be able to contribute.

Changeset 7362

Show
Ignore:
Timestamp:
02/06/08 09:28:31 (10 months ago)
Author:
fabien
Message:

doc: updated URLs for symfony 1.0 tutorials

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • doc/branches/1.0/tutorial/my-first-project.txt

    r6759 r7362  
    22======================== 
    33 
    4 So, you want to try it on? Let's build together a fully-functional web app in one hour. You name it. A bookseller application? Ok, another idea. A weblog! That's a good one. Let's go. 
    5  
    6 We'll assume that you are working with apache/PHP5 installed and launched on your localhost. You will also need the SQLite extension, which is bundled and compiled by default in PHP5. However, since PHP 5.1.0 you need to manually activate the extension in `php.ini` (see how [here](http://fr3.php.net/manual/en/ref.sqlite.php)). 
     4So, you want to try it on? Let's build together a fully-functional web app in one hour. You name it. A bookseller 
     5application? Ok, another idea. A weblog! That's a good one. Let's go. 
     6 
     7We'll assume that you are working with apache/PHP5 installed and launched on your localhost. You will also need the SQLite 
     8extension, which is bundled and compiled by default in PHP5. However, since PHP 5.1.0 you need to manually activate the 
     9extension in `php.ini` (see how [here](http://fr3.php.net/manual/en/ref.sqlite.php)). 
    710 
    811Install symfony and initialize the project 
    912------------------------------------------ 
    1013 
    11 To go fast, we will use the symfony sandbox (you can also download the [final source code](http://www.symfony-project.com/downloads/my_first_project.tgz)). It is an empty symfony project where all the required libraries are already included, and where the basic configuration is already done. The great advantage of the sandbox over other types of installation is that you can start experimenting with symfony immediately. 
    12  
    13 Get it here: [sf_sandbox.tgz](http://www.symfony-project.com/get/sf_sandbox.tgz), and unpack it in your root web directory. Refer to the included readme file for more information. The resulting file structure should look like: 
     14To go fast, we will use the symfony sandbox (you can also download the [final source 
     15code](http://www.symfony-project.org/downloads/my_first_project.tgz)). It is an empty symfony project where all the 
     16required libraries are already included, and where the basic configuration is already done. The great advantage of the 
     17sandbox over other types of installation is that you can start experimenting with symfony immediately. 
     18 
     19Get it here: [sf_sandbox.tgz](http://www.symfony-project.org/get/sf_sandbox.tgz), and unpack it in your root web 
     20directory. Refer to the included readme file for more information. The resulting file structure should look like: 
    1421 
    1522    www/ 
     
    3340          js/ 
    3441 
    35 This shows a `sf_sandbox` **project** containing a `frontend` **application**. Test the sandbox by requesting the following URL: 
     42This shows a `sf_sandbox` **project** containing a `frontend` **application**. Test the sandbox by requesting the 
     43following URL: 
    3644 
    3745    http://localhost/sf_sandbox/web/index.php/ 
     
    4149![Congratulations](/images/tutorials/first_congrats.gif) 
    4250 
    43 You can also install symfony in a custom folder and setup your web server with a Virtual Host or an Alias. The symfony book contains detailed chapters about [symfony installation](http://www.symfony-project.com/book/trunk/03-Running-Symfony) and the [symfony directory structure](http://www.symfony-project.com/book/trunk/02-Exploring-Symfony-s-Code). 
     51You can also install symfony in a custom folder and setup your web server with a Virtual Host or an Alias. The symfony 
     52book contains detailed chapters about [symfony installation](http://www.symfony-project.org/book/1_0/03-Running-Symfony) 
     53and the [symfony directory structure](http://www.symfony-project.org/book/1_0/02-Exploring-Symfony-s-Code). 
    4454 
    4555Initialize the data model 
    4656------------------------- 
    4757 
    48 So, the weblog will handle posts, and you will enable comments on them. Create a `schema.yml` file in `sf_sandbox/config/` and paste the following data model: 
     58So, the weblog will handle posts, and you will enable comments on them. Create a `schema.yml` file in `sf_sandbox/config/` 
     59and paste the following data model: 
    4960 
    5061    propel: 
     
    6576        created_at: 
    6677 
    67 This configuration file uses the YAML syntax. It's a very simple language that allows XML-like tree structures described by indentation. Furthermore, it is faster to read and write than XML. The only thing is, the indentation has a meaning and tabulations are forbidden, so remember to use spaces for indentation. You will find more about YAML and the symfony configuration in the [configuration chapter](http://www.symfony-project.com/book/trunk/05-Configuring-Symfony). 
    68      
    69 This schema describes the structure of two the tables needed for the weblog. `Post` and `Comment` are the names of the related classes to be generated. Save the file, open a command line, browse to the `sf_sandbox/` directory and type: 
     78This configuration file uses the YAML syntax. It's a very simple language that allows XML-like tree structures described 
     79by indentation. Furthermore, it is faster to read and write than XML. The only thing is, the indentation has a meaning and 
     80tabulations are forbidden, so remember to use spaces for indentation. You will find more about YAML and the symfony 
     81configuration in the [configuration chapter](http://www.symfony-project.org/book/1_0/05-Configuring-Symfony). 
     82 
     83This schema describes the structure of two the tables needed for the weblog. `Post` and `Comment` are the names of the 
     84related classes to be generated. Save the file, open a command line, browse to the `sf_sandbox/` directory and type: 
    7085 
    7186    $ php symfony propel-build-model 
     
    7388>**Note**: Make sure to be at the root of your project (`sf_sandbox/`) when you call the `symfony` command. 
    7489 
    75 A few classes are created in the `sf_sandbox/lib/model/` directory. These are the classes of the object-relational mapping, who allow us to have access to a relational database from within an object-oriented code without writing a single SQL query. Symfony uses the Propel library for this purpose. We will call theses objects the **model** (find more in the [model chapter](http://www.symfony-project.com/book/trunk/08-Inside-the-Model-Layer)). 
     90A few classes are created in the `sf_sandbox/lib/model/` directory. These are the classes of the object-relational 
     91mapping, who allow us to have access to a relational database from within an object-oriented code without writing a single 
     92SQL query. Symfony uses the Propel library for this purpose. We will call theses objects the **model** (find more in the 
     93[model chapter](http://www.symfony-project.org/book/1_0/08-Inside-the-Model-Layer)). 
    7694 
    7795Now type in the command line: 
     
    7997    $ php symfony propel-build-sql 
    8098 
    81 A `lib.model.schema.sql` file is created in `sf_sandbox/data/sql/`. This SQL query can be used to initialize a database with the same table structure. You could create a database in MySQL with the command line or a web interface (as described in the [model chapter](http://www.symfony-project.com/book/trunk/08-Inside-the-Model-Layer)). Luckily, the symfony sandbox is configured to work out of the box with a simple SQLite file, so no database initialization is required. By default, the `sf_sandbox` project will use a database called `sandbox.db` located in `sf_sandbox/data/`. To build the table structure based on the the SQL file, type: 
     99A `lib.model.schema.sql` file is created in `sf_sandbox/data/sql/`. This SQL query can be used to initialize a database 
     100with the same table structure. You could create a database in MySQL with the command line or a web interface (as described 
     101in the [model chapter](http://www.symfony-project.org/book/1_0/08-Inside-the-Model-Layer)). Luckily, the symfony sandbox 
     102is configured to work out of the box with a simple SQLite file, so no database initialization is required. By default, the 
     103`sf_sandbox` project will use a database called `sandbox.db` located in `sf_sandbox/data/`. To build the table structure 
     104based on the the SQL file, type: 
    82105 
    83106    $ php symfony propel-insert-sql 
    84107 
    85 >**Note**: Don't worry if there is a warning at that point, it is normal. The `insert-sql` command removes existing tables before adding the ones of your `lib.model.schema.sql`, and there is no table to remove at that time. 
     108>**Note**: Don't worry if there is a warning at that point, it is normal. The `insert-sql` command removes existing tables 
     109>before adding the ones of your `lib.model.schema.sql`, and there is no table to remove at that time. 
    86110 
    87111Create the application scaffolding 
    88112---------------------------------- 
    89113 
    90 The basic features of a weblog are to be able to Create, Retrieve, Update and Delete (CRUD) posts and comments. As you are new to symfony, you will not create symfony code from scratch, but rather let it create a scaffolding that you may use and modify as needed. Symfony can interpret the data model to generate the CRUD interface automatically: 
     114The basic features of a weblog are to be able to Create, Retrieve, Update and Delete (CRUD) posts and comments. As you are 
     115new to symfony, you will not create symfony code from scratch, but rather let it create a scaffolding that you may use and 
     116modify as needed. Symfony can interpret the data model to generate the CRUD interface automatically: 
    91117 
    92118    $ php symfony propel-generate-crud frontend post Post 
     
    98124    $ chmod 777 data/sandbox.db 
    99125 
    100 You now have two modules (`post` and `comment`) that will let you manipulate objects of the `Post` and `Comment` classes. A **module** usually represents a page or a group of pages with a similar purpose. Your new modules are located in the `sf_sandbox/apps/frontend/modules/` directory, and they are accessible by the URLs: 
     126You now have two modules (`post` and `comment`) that will let you manipulate objects of the `Post` and `Comment` classes. 
     127A **module** usually represents a page or a group of pages with a similar purpose. Your new modules are located in the 
     128`sf_sandbox/apps/frontend/modules/` directory, and they are accessible by the URLs: 
    101129 
    102130    http://localhost/sf_sandbox/web/frontend_dev.php/post 
     
    107135![post CRUD](/images/tutorials/first_crud.gif) 
    108136 
    109 Find more about [scaffolding](http://www.symfony-project.com/book/trunk/14-Generators) and the explanation of symfony projects [structure](http://www.symfony-project.com/book/trunk/04-The-Basics-of-Page-Creation) (project, application, module). 
    110  
    111 >**Note**: In the URLs above, the name of the main script - called *front controller* in symfony - was changed from `index.php` to `frontend_dev.php`. The two scripts access the same application (`frontend`), but in different environments. With `frontend_dev.php`, you access the application in the **development environment**, which provides handy development tools like the debug toolbar on the top right of the screen and the live configuration engine. That's why the processing of each page is slower than when using `index.php`, which is the front controller of the **production environment**, optimized for speed. If you want to keep on using the production environment, replace `frontend_dev.php/` by `index.php/` in the following URLs, but don't forget to clear the cache before watching the changes: 
     137Find more about [scaffolding](http://www.symfony-project.org/book/1_0/14-Generators) and the explanation of symfony 
     138projects [structure](http://www.symfony-project.org/book/1_0/04-The-Basics-of-Page-Creation) (project, application, 
     139module). 
     140 
     141>**Note**: In the URLs above, the name of the main script - called *front controller* in symfony - was changed from 
     142>`index.php` to `frontend_dev.php`. The two scripts access the same application (`frontend`), but in different 
     143>environments. With `frontend_dev.php`, you access the application in the **development environment**, which provides handy 
     144>development tools like the debug toolbar on the top right of the screen and the live configuration engine. That's why the 
     145>processing of each page is slower than when using `index.php`, which is the front controller of the **production 
     146>environment**, optimized for speed. If you want to keep on using the production environment, replace `frontend_dev.php/` 
     147>by `index.php/` in the following URLs, but don't forget to clear the cache before watching the changes: 
    112148> 
    113149>     $ php symfony clear-cache 
     
    115151>     http://localhost/sf_sandbox/web/index.php/ 
    116152 
    117 Find more about [environments](http://www.symfony-project.com/book/trunk/05-Configuring-Symfony#Environments). 
     153Find more about [environments](http://www.symfony-project.org/book/1_0/05-Configuring-Symfony#Environments). 
    118154 
    119155Modify the layout 
     
    145181![post CRUD in layout](/images/tutorials/first_crud_layout.gif) 
    146182 
    147 While you are at it, you can change the title of your pages. Edit the view configuration file of the application (`sf_sandbox/apps/frontend/config/view.yml`), locate the line showing the `title` key and change it to: 
     183While you are at it, you can change the title of your pages. Edit the view configuration file of the application 
     184(`sf_sandbox/apps/frontend/config/view.yml`), locate the line showing the `title` key and change it to: 
    148185 
    149186    default: 
     
    158195      language:     en 
    159196 
    160 The home page itself needs to be changed. It uses the default template of the `default` module, which is kept in the framework but not in your application directory. To override it, you have to create a custom `main` module: 
     197The home page itself needs to be changed. It uses the default template of the `default` module, which is kept in the 
     198framework but not in your application directory. To override it, you have to create a custom `main` module: 
    161199 
    162200    $ php symfony init-module frontend main 
    163201 
    164 By default, the `index` action shows a default congratulations screen. To remove it, edit the `sf_sandbox/apps/frontend/modules/main/actions/actions.class.php` and remove the content of the `executeIndex()` method as follows: 
     202By default, the `index` action shows a default congratulations screen. To remove it, edit the 
     203`sf_sandbox/apps/frontend/modules/main/actions/actions.class.php` and remove the content of the `executeIndex()` method as 
     204follows: 
    165205 
    166206    [php] 
     
    175215    <p>You are the <?php echo rand(1000,5000) ?>th visitor today.</p> 
    176216 
    177 Now, you must tell symfony which action to execute when the homepage is requested. To that extend, edit the `sf_sandbox/apps/frontend/config/routing.yml` and change the `homepage` rule as follows: 
     217Now, you must tell symfony which action to execute when the homepage is requested. To that extend, edit the 
     218`sf_sandbox/apps/frontend/config/routing.yml` and change the `homepage` rule as follows: 
    178219 
    179220    [yml] 
     
    190231Go ahead, start using your new web app: Create a new test post, and a test comment for your this post. 
    191232 
    192 Find more about [views and templates](http://www.symfony-project.com/book/trunk/07-Inside-the-View-Layer). 
     233Find more about [views and templates](http://www.symfony-project.org/book/1_0/07-Inside-the-View-Layer). 
    193234 
    194235Pass data from the action to the template 
    195236----------------------------------------- 
    196237 
    197 That was fast, wasn't it? Now it is time to mix the `comment` module into the `post` one to get comments displayed below posts. 
    198  
    199 First, you need to make the post comments available for the post display template. In symfony, this kind of logic is kept in **actions**. Edit the actions file `sf_sandbox/apps/frontend/modules/post/actions/actions.class.php` and change the `executeShow()` method by adding the 4 last lines: 
     238That was fast, wasn't it? Now it is time to mix the `comment` module into the `post` one to get comments displayed below 
     239posts. 
     240 
     241First, you need to make the post comments available for the post display template. In symfony, this kind of logic is kept 
     242in **actions**. Edit the actions file `sf_sandbox/apps/frontend/modules/post/actions/actions.class.php` and change the 
     243`executeShow()` method by adding the 4 last lines: 
    200244 
    201245    [php] 
     
    211255    } 
    212256 
    213 The `Criteria` and `-Peer` objects are part of Propel's object-relational mapping. Basically, these four lines will handle a SQL query to the `Comment` table to get the comments related to the current `Post` (the one designated by the URL parameter `id`). The `$this->comments` line in the action will give access to a `$comments` variable in the corresponding template. Now, modify the post display template `sf_sandbox/apps/frontend/modules/post/templates/showSuccess.php` by adding at the end: 
     257The `Criteria` and `-Peer` objects are part of Propel's object-relational mapping. Basically, these four lines will handle 
     258a SQL query to the `Comment` table to get the comments related to the current `Post` (the one designated by the URL 
     259parameter `id`). The `$this->comments` line in the action will give access to a `$comments` variable in the corresponding 
     260template. Now, modify the post display template `sf_sandbox/apps/frontend/modules/post/templates/showSuccess.php` by 
     261adding at the end: 
    214262 
    215263    [php] 
     
    228276    <?php endif; ?> 
    229277 
    230 This page uses new PHP functions (`format_date()` and `simple_format_text()`) provided by symfony, and called 'helpers' because they do some tasks for you that would normally require more time and code. Create a new comment for your first post, then check again the first post, either by clicking on its number in the list, or by typing directly: 
     278This page uses new PHP functions (`format_date()` and `simple_format_text()`) provided by symfony, and called 'helpers' 
     279because they do some tasks for you that would normally require more time and code. Create a new comment for your first 
     280post, then check again the first post, either by clicking on its number in the list, or by typing directly: 
    231281 
    232282    http://localhost/sf_sandbox/web/frontend_dev.php/post/show?id=1 
     
    236286This is getting good. 
    237287 
    238 Find more about the [naming conventions](http://www.symfony-project.com/book/trunk/07-Inside-the-View-Layer) linking an action to a template. 
     288Find more about the [naming conventions](http://www.symfony-project.org/book/1_0/07-Inside-the-View-Layer) linking an 
     289action to a template. 
    239290 
    240291Add a record relative to another table 
    241292-------------------------------------- 
    242293 
    243 When adding a comment, you can choose the `id` of the related post. That's not very user-friendly. Let's change this, and make sure that the user comes back to the post he was looking at after adding a comment. 
     294When adding a comment, you can choose the `id` of the related post. That's not very user-friendly. Let's change this, and 
     295make sure that the user comes back to the post he was looking at after adding a comment. 
    244296 
    245297First, in the still fresh `modules/post/templates/showSuccess.php` template, add a line at the bottom: 
     
    248300    <?php echo link_to('Add a comment', 'comment/create?post_id='.$post->getId()) ?> 
    249301     
    250 The `link_to()` helper creates a hyperlink pointing to the `create` action of the `comment` module, so you can add a comment directly from the post details page. Next, open the `modules/comment/templates/editSuccess.php` and replace the following lines: 
     302The `link_to()` helper creates a hyperlink pointing to the `create` action of the `comment` module, so you can add a 
     303comment directly from the post details page. Next, open the `modules/comment/templates/editSuccess.php` and replace the 
     304following lines: 
    251305 
    252306    [php] 
     
    270324    <?php endif; ?> 
    271325     
    272 The form in the `comment/create` page points to a `comment/update` action, which redirects to `comment/show` when submitted (this is the default behaviour in generated CRUDs). For the weblog, that means that after adding a comment to a post, the detail of the comment is displayed. It is better to display the post with the comments at that point. So open the `modules/comment/actions/actions.class.php` and look for the `executeUpdate()` method. Note that the `created_at` field is not defined by the action: symfony knows that a field named `created_at` has to be set to the system time when a record is created. The final redirect of the action has to be modified to point to the correct action. Change it to: 
     326The form in the `comment/create` page points to a `comment/update` action, which redirects to `comment/show` when 
     327submitted (this is the default behaviour in generated CRUDs). For the weblog, that means that after adding a comment to a 
     328post, the detail of the comment is displayed. It is better to display the post with the comments at that point. So open 
     329the `modules/comment/actions/actions.class.php` and look for the `executeUpdate()` method. Note that the `created_at` 
     330field is not defined by the action: symfony knows that a field named `created_at` has to be set to the system time when a 
     331record is created. The final redirect of the action has to be modified to point to the correct action. Change it to: 
    273332 
    274333    [php] 
     
    298357Users can now add comments to a post and come back to the post afterwards. You wanted a weblog? You have a weblog. 
    299358 
    300 Find more about [actions](http://www.symfony-project.com/book/trunk/06-Inside-the-Controller-Layer). 
     359Find more about [actions](http://www.symfony-project.org/book/1_0/06-Inside-the-Controller-Layer). 
    301360 
    302361Form Validation 
    303362--------------- 
    304363 
    305 Visitors can enter comments, but what if they submit the form without any data in it? You will have a dirty database. To avoid that, create a file called `update.yml` in the `sf_sandbox/apps/frontend/modules/comment/validate/` directory (you also have to create the directory) and write in: 
     364Visitors can enter comments, but what if they submit the form without any data in it? You will have a dirty database. To 
     365avoid that, create a file called `update.yml` in the `sf_sandbox/apps/frontend/modules/comment/validate/` directory (you 
     366also have to create the directory) and write in: 
    306367 
    307368    methods: 
     
    330391        email_error:  The email address is not valid. 
    331392 
    332 >**Note**: Beware that you don't copy 4 extra spaces at the beginning of each line, since the YAML parser would fail in that case. The first letter of this file must be the 'm' of 'methods'. 
    333  
    334 The `fillin` activation enables the repopulation of the form with the value previously entered by the user in case of failed validation. The `names` declarations set the validation rules for each input of the form. 
    335  
    336 By itself, the controller will redirect the user to a `updateError.php` template if an error is detected. It would be better to display the form again with an error message. To do that, add a `handleErrorUpdate` method to the action class of the `modules/comment/actions/actions.class.php` file: 
     393>**Note**: Beware that you don't copy 4 extra spaces at the beginning of each line, since the YAML parser would fail in 
     394>that case. The first letter of this file must be the 'm' of 'methods'. 
     395 
     396The `fillin` activation enables the repopulation of the form with the value previously entered by the user in case of 
     397failed validation. The `names` declarations set the validation rules for each input of the form. 
     398 
     399By itself, the controller will redirect the user to a `updateError.php` template if an error is detected. It would be 
     400better to display the form again with an error message. To do that, add a `handleErrorUpdate` method to the action class 
     401of the `modules/comment/actions/actions.class.php` file: 
    337402 
    338403    [php] 
     
    360425![Form validation](/images/tutorials/first_form_validation.gif) 
    361426 
    362 Find more about [form validation](http://www.symfony-project.com/book/trunk/10-Forms). 
     427Find more about [form validation](http://www.symfony-project.org/book/1_0/10-Forms). 
    363428 
    364429Change the URL aspect 
    365430--------------------- 
    366431 
    367 Did you notice the way the URLs are rendered? You can make them more user and search engine-friendly. Let's use the post title as an URL for posts.  
    368  
    369 The problem is that post titles can contain special characters like spaces. If you just escape them, the URL will show some ugly `%20` kind of things, so you'd better extend the model to add a new method to the `Post` object to get a clean, stripped title. To do that, edit the file `Post.php` located in the `sf_sandbox/lib/model/` directory, and add the following method: 
     432Did you notice the way the URLs are rendered? You can make them more user and search engine-friendly. Let's use the post 
     433title as an URL for posts. 
     434 
     435The problem is that post titles can contain special characters like spaces. If you just escape them, the URL will show 
     436some ugly `%20` kind of things, so you'd better extend the model to add a new method to the `Post` object to get a clean, 
     437stripped title. To do that, edit the file `Post.php` located in the `sf_sandbox/lib/model/` directory, and add the 
     438following method: 
    370439 
    371440    [php] 
     
    387456    } 
    388457 
    389 Now you can create a `permalink` action for the `post` module. Add the following method to the `modules/post/actions/actions.class.php`: 
     458Now you can create a `permalink` action for the `post` module. Add the following method to the 
     459`modules/post/actions/actions.class.php`: 
    390460 
    391461    [php] 
     
    407477    } 
    408478 
    409 The post list can call this `permalink` action instead of the `show` one for each post. In `modules/post/templates/listSuccess.php`, delete the `id` table header and cell, and change the `Title` cell from: 
     479The post list can call this `permalink` action instead of the `show` one for each post. In 
     480`modules/post/templates/listSuccess.php`, delete the `id` table header and cell, and change the `Title` cell from: 
    410481 
    411482    [php] 
     
    417488    <td><?php echo link_to($post->getTitle(), 'post/permalink?title='.$post->getStrippedTitle()) ?></td> 
    418489 
    419 Just one more step: Edit the `routing.yml` located in the `sf_sandbox/apps/frontend/config/` directory and add these rules at the top: 
     490Just one more step: Edit the `routing.yml` located in the `sf_sandbox/apps/frontend/config/` directory and add these rules 
     491at the top: 
    420492 
    421493    list_of_posts: 
     
    431503![Routed URLs](/images/tutorials/first_routing.gif) 
    432504 
    433 Find more about [smart URLs](http://www.symfony-project.com/book/trunk/09-Links-and-the-Routing-System). 
     505Find more about [smart URLs](http://www.symfony-project.org/book/1_0/09-Links-and-the-Routing-System). 
    434506 
    435507Cleanup in the frontend 
    436508----------------------- 
    437509 
    438 Well, if this is a weblog, then everybody has the right to post. This isn't exactly what you thought about, right? Ok, let's clean up our templates a bit. 
     510Well, if this is a weblog, then everybody has the right to post. This isn't exactly what you thought about, right? Ok, 
     511let's clean up our templates a bit. 
    439512 
    440513In the template `modules/post/templates/showSuccess.php`, get rid of the 'edit' link by removing the line: 
     
    460533------------------------- 
    461534 
    462 For you to write posts, let's create a backend application by typing in the command line (still from the `sf_sandbox` project directory): 
     535For you to write posts, let's create a backend application by typing in the command line (still from the `sf_sandbox` 
     536project directory): 
    463537 
    464538    $ php symfony init-app backend 
     
    466540    $ php symfony propel-init-admin backend comment Comment 
    467541     
    468 This time, we use the [admin generator](http://www.symfony-project.com/book/trunk/14-Generators). It offers much more features and customization than the very basic CRUD generator. 
    469  
    470 Just like you did for the `frontend` application, edit the layout (`apps/backend/templates/layout.php`) to add global navigation: 
     542This time, we use the [admin generator](http://www.symfony-project.org/book/1_0/14-Generators). It offers much more 
     543features and customization than the very basic CRUD generator. 
     544 
     545Just like you did for the `frontend` application, edit the layout (`apps/backend/templates/layout.php`) to add global 
     546navigation: 
    471547 
    472548    <div id="navigation"> 
     
    518594            created_at:   { type: input_date_tag, params: rich=on } 
    519595 
    520 Note that among the existing columns of the `Post` table, the admin will look for a `nb_comments`. There is no associated getter yet, but it is simple to add to the `sf_sandbox/lib/model/Post.php`: 
     596Note that among the existing columns of the `Post` table, the admin will look for a `nb_comments`. There is no associated 
     597getter yet, but it is simple to add to the `sf_sandbox/lib/model/Post.php`: 
    521598 
    522599    [php] 
     
    546623    $ php symfony init-module backend security 
    547624 
    548 This new module will be used to handle the login form and the request. Edit the `apps/backend/modules/security/templates/indexSuccess.php` to create the login form: 
     625This new module will be used to handle the login form and the request. Edit the 
     626`apps/backend/modules/security/templates/indexSuccess.php` to create the login form: 
    549627 
    550628    [php] 
     
    565643    </form> 
    566644 
    567 Add the `login` action that is called by the form to the `security` module (in the `apps/backend/modules/security/actions/actions.class.php` file): 
     645Add the `login` action that is called by the form to the `security` module (in the 
     646`apps/backend/modules/security/actions/actions.class.php` file): 
    568647 
    569648    [php] 
     
    591670    } 
    592671 
    593 The last thing to do is to set the `security` module as the default module to handle login actions. To do that, open the `apps/backend/config/settings.yml` configuration file and add: 
     672The last thing to do is to set the `security` module as the default module to handle login actions. To do that, open the 
     673`apps/backend/config/settings.yml` configuration file and add: 
    594674 
    595675    all: 
     
    602682![login form](/images/tutorials/first_login.gif) 
    603683 
    604 Find more about [security](http://www.symfony-project.com/book/trunk/06-Inside-the-Controller-Layer#Action%20Security). 
     684Find more about [security](http://www.symfony-project.org/book/1_0/06-Inside-the-Controller-Layer#Action%20Security). 
    605685 
    606686Conclusion 
     
    612692    backend:    http://localhost/sf_sandbox/web/backend.php/ 
    613693 
    614 At this point, if you meet an error, it might be because you changed the model after some actions were put in cache (cache isn't activated in the development environment). To clear the cache, simply type: 
     694At this point, if you meet an error, it might be because you changed the model after some actions were put in cache (cache 
     695isn't activated in the development environment). To clear the cache, simply type: 
    615696 
    616697    $ php symfony cc 
    617698 
    618 See, the application is fast and runs smoothly. Pretty darn cool, isn't it? Feel free to explore the code, add new modules, and change the design of pages.  
     699See, the application is fast and runs smoothly. Pretty darn cool, isn't it? Feel free to explore the code, add new 
     700modules, and change the design of pages. 
    619701 
    620702And don't forget to mention your working symfony applications in the symfony Wiki! 
  • doc/branches/1.0/tutorial/symfony-ajax.txt

    r5695 r7362  
    55-------- 
    66 
    7 Symfony has Ajax helpers that make programming an elaborate interface a piece of cake. This tutorial will show you step-by-step how to create an Ajax-powered symfony application in minutes. 
     7Symfony has Ajax helpers that make programming an elaborate interface a piece of cake. This tutorial will show you 
     8step-by-step how to create an Ajax-powered symfony application in minutes. 
    89 
    910Introduction 
    1011------------ 
    1112 
    12 Real lazy folks that can't stand reading long documentation are advised to watch the [online screencast](http://downloads.symfony-project.com/demo/cart/cart.mov) that demonstrates exactly what is written below. 
    13  
    14 Adding items to a shopping cart in common e-commerce applications isn't very close to the actual "add to cart" metaphor, since it requires clicking an "add to cart" button, watch a new page (the shopping cart), and then go back to the shop or checkout with buttons. 
    15  
    16 Ajax allows to get closer to the cart metaphor, by enabling drag-and-drop interactions and giving immediate visual feedback, without leaving the shop. 
    17  
    18 The target application of this tutorial will be a symfony ported version of the shopping cart demo published by [script.aculo.us](http://script.aculo.us/demos/shop) in [Rails](http://www.rubyonrails.com). It uses the [prototype](http://prototype.conio.net/) JavaScript framework (bundled with symfony) and some [script.aculo.us](http://script.aculo.us/) JavaScript that is the core of the JavaScript helpers. 
     13Real lazy folks that can't stand reading long documentation are advised to watch the [online 
     14screencast](http://www.symfony-project.org/screencast/cart) that demonstrates exactly what is written below. 
     15 
     16Adding items to a shopping cart in common e-commerce applications isn't very close to the actual "add to cart" metaphor, 
     17since it requires clicking an "add to cart" button, watch a new page (the shopping cart), and then go back to the shop or 
     18checkout with buttons. 
     19 
     20Ajax allows to get closer to the cart metaphor, by enabling drag-and-drop interactions and giving immediate visual 
     21feedback, without leaving the shop. 
     22 
     23The target application of this tutorial will be a symfony ported version of the shopping cart demo published by 
     24[script.aculo.us](http://script.aculo.us/demos/shop) in [Rails](http://www.rubyonrails.com). It uses the 
     25[prototype](http://prototype.conio.net/) JavaScript framework (bundled with symfony) and some 
     26[script.aculo.us](http://script.aculo.us/) JavaScript that is the core of the JavaScript helpers. 
    1927 
    2028Application Setup 
     
    3038    $ symfony init-module app cart 
    3139 
    32 Setup your web server to be able to access this new application (whether using a virtual host or an alias, as described in the [web server setup](http://www.symfony-project.com/cookbook/1_0/web_server) chapter of the documentation). For this example, let's assume that this module is accessible via a localhost: 
     40Setup your web server to be able to access this new application (whether using a virtual host or an alias, as described in 
     41the [web server setup](http://www.symfony-project.org/cookbook/1_0/web_server) chapter of the documentation). For this 
     42example, let's assume that this module is accessible via a localhost: 
    3343 
    3444    http://localhost/cart/ 
     
    3646Congratulations, it says. 
    3747 
    38 Your app must have access to the symfony JavaScript libraries. If your app doesn't work, check you can access these libraries within your browser (test `http://localhost/sf/prototype/js/prototype.js` for example). If not, you have 3 different ways to fix this problem: 
     48Your app must have access to the symfony JavaScript libraries. If your app doesn't work, check you can access these 
     49libraries within your browser (test `http://localhost/sf/prototype/js/prototype.js` for example). If not, you have 3 
     50different ways to fix this problem: 
    3951 
    4052* configure Apache with the following `Alias`: 
     
    5668------------- 
    5769 
    58 First, you need to create a list of items to be purchased. To keep the project simple, the element list is accessed via a simple `getProducts()` method of the `cart` actions class. The shopping cart is a simple parameter of the `sfUser` object, set with the Attribute [parameter holder](http://www.symfony-project.com/content/book/page/parameter_holder.html). Modify the `sfdemo/apps/app/modules/cart/actions/actions.class.php` to: 
     70First, you need to create a list of items to be purchased. To keep the project simple, the element list is accessed via a 
     71simple `getProducts()` method of the `cart` actions class. The shopping cart is a simple parameter of the `sfUser` object, 
     72set with the Attribute [parameter holder](http://www.symfony-project.org/book/1_0/02-Exploring-Symfony-s-Code#Parameter%20Holders). Modify 
     73the `sfdemo/apps/app/modules/cart/actions/actions.class.php` to: 
    5974 
    6075    [php] 
     
    7388    } 
    7489 
    75 The main page of the `cart` module will contain a list of items, and a zone to drag items to. This zone is the shopping cart. So open the template `sfdemo/apps/app/modules/cart/templates/indexSuccess.php` and write in: 
     90The main page of the `cart` module will contain a list of items, and a zone to drag items to. This zone is the shopping 
     91cart. So open the template `sfdemo/apps/app/modules/cart/templates/indexSuccess.php` and write in: 
    7692 
    7793    [php] 
     
    98114    </div> 
    99115 
    100 You can see that products are shown as images. Use the images available in [this archive](http://www.symfony-project.com/downloads/demo/cart/products.tgz), and put them in the `sfdemo/web/images/` directory. In addition, part of the styling was done for you, so it is recommended that you upload [this stylesheet](http://www.symfony-project.com/downloads/demo/cart/cart.css) to the `sfdemo/web/css/` directory and add a `view.yml` in the `sfdemo/apps/app/modules/cart/config/` directory with the following content: 
     116You can see that products are shown as images. Use the images available in [this 
     117archive](http://www.symfony-project.org/downloads/demo/cart/products.tgz), and put them in the `sfdemo/web/images/` 
     118directory. In addition, part of the styling was done for you, so it is recommended that you upload [this 
     119stylesheet](http://www.symfony-project.org/downloads/demo/cart/cart.css) to the `sfdemo/web/css/` directory and add a 
     120`view.yml` in the `sfdemo/apps/app/modules/cart/config/` directory with the following content: 
    101121 
    102122    all: 
     
    110130----------------- 
    111131 
    112 The cart content will change as you drag items to it. This means that the content of the cart in the template must be in an independent file. Use the `include_partial()` helper for that. The items in the shopping cart will be stored in divs with `float:left` style, so a clearing div is necessary after the container. So change the end of the `indexSuccess.php` template to: 
     132The cart content will change as you drag items to it. This means that the content of the cart in the template must be in 
     133an independent file. Use the `include_partial()` helper for that. The items in the shopping cart will be stored in divs 
     134with `float:left` style, so a clearing div is necessary after the container. So change the end of the `indexSuccess.php` 
     135template to: 
    113136 
    114137    [php] 
     
    124147    </div> 
    125148 
    126 The `include_partial()` helper will include a `_cart.php` file, and look for this file in the `sfdemo/apps/app/modules/cart/templates/` directory. Create it with the following content: 
     149The `include_partial()` helper will include a `_cart.php` file, and look for this file in the 
     150`sfdemo/apps/app/modules/cart/templates/` directory. Create it with the following content: 
    127151 
    128152    [php] 
     
    144168    <?php endif; ?>  
    145169 
    146 If the cart contains items, they appear as images, as many times as they are added; the quantity is be displayed after each series. 
     170If the cart contains items, they appear as images, as many times as they are added; the quantity is be displayed after 
     171each series. 
    147172 
    148173Now watch again the shopping cart at: 
     
    171196    <?php endforeach; ?> 
    172197 
    173 This adds a 'draggable' behavior to each of the images of the list of products. The `revert` option will make images go back to their origin position when released (unless received by a receiving element). 
    174  
    175 Now, define the cart as a receiving element. You just need to define which part of the template will have to be updated when the event occurs, which action will be called for its content, and which type of draggable elements can be dragged into it. Use the `drop_receiving_elements` JavaScript helper for that: 
     198This adds a 'draggable' behavior to each of the images of the list of products. The `revert` option will make images go 
     199back to their origin position when released (unless received by a receiving element). 
     200 
     201Now, define the cart as a receiving element. You just need to define which part of the template will have to be updated 
     202when the event occurs, which action will be called for its content, and which type of draggable elements can be dragged 
     203into it. Use the `drop_receiving_elements` JavaScript helper for that: 
    176204 
    177205    [php] 
     
    182210    )) ?> 
    183211 
    184 Now try again, and move the products to the cart: it works. When a draggable item is dragged to the receiving element, an XMLHTTPRequest is sent to the `add` action, and the result is displayed in the `items` div. The thing is, the `add` action of the `cart` module is not defined yet... 
     212Now try again, and move the products to the cart: it works. When a draggable item is dragged to the receiving element, an 
     213XMLHTTPRequest is sent to the `add` action, and the result is displayed in the `items` div. The thing is, the `add` action 
     214of the `cart` module is not defined yet... 
    185215 
    186216Define the Updating Action 
     
    210240This action looks for the parameter sent by the JavaScript (the id of the dragged item) and adds it to the cart. 
    211241 
    212 The result of the `add` action will be the `addSuccess.php` template. It is a simple inclusion of the `_cart.php` partial, but this time it is necessary to pass the products as a parameter : 
     242The result of the `add` action will be the `addSuccess.php` template. It is a simple inclusion of the `_cart.php` partial, 
     243but this time it is necessary to pass the products as a parameter : 
    213244 
    214245    [php] 
    215246    <?php include_partial('cart', array('products' => $products)) ?> 
    216247 
    217 This template must not use the global layout, so edit the `view.yml` in the `sfdemo/apps/app/modules/cart/config/` directory, and write in: 
     248This template must not use the global layout, so edit the `view.yml` in the `sfdemo/apps/app/modules/cart/config/` 
     249directory, and write in: 
    218250 
    219251    addSuccess: 
     
    229261------------------ 
    230262 
    231 You could stop now, but this shopping cart has a big default: while the cart is updated, the interface doesn't change and the user might be disoriented. This is a general issue of asynchronous requests: an indicator zone has to be added to show that the request is being processed. In addition, nothing tells the user when the dragged item is considered accepted by the cart, so the `hover` style of the `cart` div also has to be defined. 
     263You could stop now, but this shopping cart has a big default: while the cart is updated, the interface doesn't change and 
     264the user might be disoriented. This is a general issue of asynchronous requests: an indicator zone has to be added to show 
     265that the request is being processed. In addition, nothing tells the user when the dragged item is considered accepted by 
     266the cart, so the `hover` style of the `cart` div also has to be defined. 
    232267 
    233268To do that, edit the `indexSuccess.php` template and write in: 
     
    240275    </div> 
    241276 
    242 Save the 'indicator.gif' [image file](http://www.symfony-project.com/downloads/demo/cart/indicator.gif) to your `sfdemo/web/images/` directory. 
    243  
    244 Now, modify the `drop_receiving_element()` JavaScript helper call in the same template to show this new indicator while requests are processed and declare the hover style: 
     277Save the 'indicator.gif' [image file](http://www.symfony-project.org/downloads/demo/cart/indicator.gif) to your 
     278`sfdemo/web/images/` directory. 
     279 
     280Now, modify the `drop_receiving_element()` JavaScript helper call in the same template to show this new indicator while 
     281requests are processed and declare the hover style: 
    245282 
    246283    [php] 
     
    258295---------- 
    259296 
    260 The complete source of the demo can be [downloaded](http://www.symfony-project.com/downloads/demo/cart/project.tgz) and is available [online](http://www.symfony-project.com/demo/cart.html). You will notice a few minor differences with the code described in this tutorial (including a trash box), but the core behaviors are the same. 
    261  
    262 Until the full documentation of the JavaScript helpers is released, you can find more information about them in the [script.aculo.us documentation](http://wiki.script.aculo.us/scriptaculous/list?category=Controls). 
     297The complete source of the demo can be [downloaded](http://www.symfony-project.org/downloads/demo/cart/project.tgz) and is 
     298available [online](http://www.symfony-project.org/demo/cart.html). You will notice a few minor differences with the code 
     299described in this tutorial (including a trash box), but the core behaviors are the same. 
     300 
     301Until the full documentation of the JavaScript helpers is released, you can find more information about them in the 
     302[script.aculo.us documentation](http://wiki.script.aculo.us/scriptaculous/list?category=Controls).