Article
Learn symfony: a Beginner's Tutorial
Generating a Site Administration Panel
We'll use a great feature of the symfony framework called the administration generator to create a site administration panel. The administration generator uses the relational schema as a guideline to create a data manipulation interface. Our site administrator will need to edit data from the Photo class, so let's generate an admin panel for this class:
$ php symfony propel-init-admin frontend photo Photo
Symfony organizes the pages of a project within a hierarchy of applications and modules. Although this structure adds directories to a project's structure, it makes maintenance easier, especially for large sites. So a module contains several pages, an application contains several modules, and a project can contain more than one application. The sandbox that you installed is a symfony project packaged with an empty application called frontend. This means that the command of the above listing reads as: "Create a site administration in the application frontend, in a module called photo, based on the model class Photo". To see what the new module looks like, browse to http://localhost/sf_sandbox/web/frontend_dev.php/photo.

One of the advantages of a generated administration is that it allows you to add data to your database early in the project -- even before coding. A generated administration consists of two pages that we'll call the list view and the edit view. Symfony uses the schema to build tables, forms, and form-handling scripts. Although all the code is generated, you can override it as you like. However, the best way to customize a generated administration is not to write PHP code, but to use the generator.yml file. That's a configuration file that controls the generated module, and adding parameters in this file transforms the list and edit views accordingly. Let's see an example.
By default, the columns of the list view correspond to the columns defined in the schema. The column that corresponds to the primary key (id in this example) bears the hyperlink to the Edit view. But the id column is of no use for an administrator, so we should remove it from the list view. To do so, open the generator.yml file located in apps/frontend/modules/photo/config/ and add at the end the following code:
generator:
class: sfPropelAdminGenerator
param:
model_class: Photo
theme: default
list:
display: [file_path, description, created_at]
object_actions:
_edit:
name: Edit picture properties
Be aware that indentation is meaningful in YAML files, so try to respect the indentation shown here. One important piece of advice is to never use tab characters in YAML files -- always use a double space to indent lines. The display line tells symfony which columns to show in the list, in which order. As for the object_actions key, it manages the buttons that will be shown for each line. The _edit button is predefined, so you don't need to worry about the script it calls. We just customized the button's name here. To see the result, browse to the photo module again and see how the list view changed.

Entering a file path to upload photos is not very useful. The ideal for this photo administration module would be that users would be able to browse their file system to point to a picture file. This is quite easy to do, and requires no code. Modify your generator.yml as follows:
generator:
class: sfPropelAdminGenerator
param:
model_class: Photo
theme: default
list:
display: [file_path, description, created_at]
object_actions:
_edit:
name: Edit picture properties
edit:
display: [file_path, description]
fields:
file_path:
type: admin_input_file_tag
You already know the display key: it controls which fields are displayed in the view. In the Edit view, it controls which fields appear in the form. We got rid of the created_at column in this view for a good reason: symfony handles it on its own. Because of its name, symfony will give to this field the value of the record creation date. If you were to add an updated_at column, symfony would also handle it on its own, updating it every time you change a record.
The second thing to notice in this listing is the fields key, and the fact that the file_path column is set to show an input of type admin_input_file_tag. This tells symfony to use a file input for this column, but also to upload the related file to its web/uploads/ directory. Try using the Edit view to add a few pictures to the photo album.

It would be nice if the module could display the uploaded photos, so you can check whether your uploads succeeded. To do so, we'll use a partial column. A partial column is a piece of PHP code that can be used as a column in a generated administration. Here's how it works. First, edit the generator.yml to add the _photo column to the display key in both views:
generator:
class: sfPropelAdminGenerator
param:
model_class: Photo
theme: default
list:
display: [_photo, description, created_at]
object_actions:
_edit:
name: Edit picture properties
edit:
display: [_photo, file_path, description]
fields:
file_path:
type: admin_input_file_tag
Symfony recognizes the underscore and, instead of using the methods of the Photo object to get the column value, it tries to include a file called _photo.php in the column. Create _photo.php in the /apps/frontend/modules/photo/templates directory, and within the file place only the following line:
<?php echo image_tag('/uploads/'.$photo->getFilePath()) ?>
Before loading this file, symfony puts the current Photo object into the $photo variable. The getFilePath method is among the methods that were automatically generated by symfony based on the schema.yml when you called the propel-build-model command. As you might have guessed, it returns the value of the file_path column that corresponds to the $photo object. Every other column has a corresponding getter and setter method in the generated Photo class. The image_tag function is a symfony helper -- a function that returns HTML code and is meant to be used in templates. This one returns an <img> tag, which is just what we want. Its first parameter must be a file path that's relative to the web/ directory. Check that the images now show up properly by browsing the photo module again.