Developing an Application in Symfony 1.3 (Part 2)

Exclusive offer: get 50% off this eBook here
Symfony 1.3 Web Application Development

Symfony 1.3 Web Application Development — Save 50%

Design, develop, and deploy feature-rich, high-performance PHP web applications using the Symfony framework

£14.99    £7.50
by Tim Bowler | September 2009 | MySQL Open Source PHP Web Development

Read Part One of Developing an Application in Symfony 1.3 here.

Building the database

The last step is to create the database and then create all of the tables. I have created my database called milkshake on the CLI using the following command:

$/home/timmy/workspace/milkshake>mysqladmin create milkshake -u root -p

Now that we have created the database, we need to generate the SQL that will create our tables. Again, we are going to use a Symfony task for this. Just like creating the ORM layer, the task will build the SQL based on the schema.xml file. From the CLI, execute the following task:

$/home/timmy/workspace/milkshake>symfony propel:build-sql

This has now generated a SQL file that contains all of the SQL statements needed to build the tables in our database. This file is located in the data/sql folder within the project folder. Looking at the generated lib.model.schema.sql file in this folder, you can view the SQL. Next, we need to insert the SQL into the database. Again using a Symfony task, execute the following on the CLI:

$/home/timmy/workspace/milkshake>symfony propel:insert-sql

During the execution of the task, you will be prompted to enter a y or N as to whether you want to delete the existing data. As this command will delete your existing tables and then create new tables, enter y. During development, the confirmation can become tiring. To get around this you can append the no-confirmation switch to the end as shown here:

>symfony propel:insert-sql --no-confirmation

Afterwards, check in your database and you should see all of the tables created as shown in the following screenshot:

Symfony 1.3 Web Application Development

I have showed you how to execute each of the tasks in order to build everything. But there is a simpler way to do this, and that is with yet another Symfony task which executes all of the above tasks:

$/home/timmy/workspace/milkshake>symfony propel:build-all

or

$/home/timmy/workspace/milkshake>symfony propel:build-all --no-confirmation

Our application is now all set up with a database and the ORM layer configured. Next, we can start on the application logic and produce a wireframe.

Creating the application modules

In Symfony, all requests are initially handled by a front controller before being passed to an action. The actions then implement the application logic before returning the presentation template that will be rendered.

Our application will initially contain four areas—home, location, menu, and vacancies. These areas will essentially form modules within our frontend application. A module is similar to an application, which is the place to group all application logic and is self contained. Let's now create the modules on the CLI by executing the following tasks:

$/home/timmy/workspace/milkshake>symfony generate:module frontend home
$/home/timmy/workspace/milkshake>symfony generate:module frontend location
$/home/timmy/workspace/milkshake>symfony generate:module frontend menu
$/home/timmy/workspace/milkshake>symfony generate:module frontend vacancies

Executing these tasks will create all of the modules' folder structures along with default actions, templates, and tests in our frontend application. You will see the following screenshot when running the first task:

Symfony 1.3 Web Application Development

Let's examine the folder structure for a module:

Folder

Description

actions

This folder contains the actions class and components class for a module

templates

All modules templates are stored in this folder

Now browse to http://milkshake/frontend_dev.php/menu and you will see Symfony's default page for our menu module. Notice that this page also provides useful information on what to do next. This information, of course, is to render our template rather than have Symfony forward the request.

Symfony 1.3 Web Application Development

Handling the routing

We have just tested our menu module and Symfony was able to handle this request without us having to set anything. This is because the URL was interpreted as http://milkshake/module/action/:params. If the action is missing, Symfony will automatically append index and execute the index action if one exists in the module. Looking at the URL for our menu module, we can use either http://milkshake/frontend_dev.php/menu or http://milkshake/frontend_dev.php/menu/index for the moment. Also, if you want to pass variables from the URL, then we can just add them to the end of the URL. For example, if we wanted to also pass page=1 to the menu module, the URL would be http://milkshake/frontend_dev.php/menu/index/page/1. The problem here is that we must also specify the name of the action, which doesn't leave much room for customizing a URL.

Mapping the URL to the application logic is called routing. In the earlier example, we browsed to http://milkshake/frontend_dev.php/menu and Symfony was able to route that to our menu module without us having to configure anything. First, let's take a look at the routing file located at apps/frontend/config/routing.yml.

# default rules
homepage:
URL: /
param: { module: default, action: index }
default_index:
URL: /:module
param: { action: index }
default:
URL: /:module/:action/*

This is the default routing file that was generated for us. Using the home page routing rules as an example, the route is broken down into three parts:

  • A unique label: homepage
  • A URL pattern: URL: /
  • An array of request parameters: param: { module: menu, action: index }

We refer to each one of the rules within the routing file using a unique label. A URL pattern is what Symfony uses to map the URL to a rule, and the array of parameters is what maps the request to the module and the action. By using a routing file, Symfony caters for complicated URLs, which can restrict parameter types, request methods, and associate parameters to our Propel ORM layer. In fact, Symfony includes an entire framework that handles the routing for us.

The application logic

As we have seen, Symfony routes all requests to an action within a module. So let's open the actions class for our menu module, which is located at apps/frontend/modules/menu/actions/actions.class.php.

class menuActions extends sfActions
{
/**
* Executes index action
*
* @param sfRequest $request A request object
*/
public function executeIndex(sfWebRequest $request)
{
$this->forward('default', 'module');
}
}

This menuActions class contains all of the menu actions and as you can see, it extends the sfActions base class. This class was generated for us along with a default 'index' action (method). The default index action simply forwards the request to Symfony's default module, which in turn generates the default page that we were presented with.

All of the actions follow the same naming convention, that is, the action name must begin with the word execute followed by the action name starting with a capital letter. Also, the request object is passed to the action, which contains all of the parameters that are in the request.

Let's begin by modifying the default behavior of the menu module to display our own template. Here we need the application logic to return the template name that needs to be rendered. To do this, we simply replace the call to the forward function with a return statement that has the template name:

public function executeIndex(sfWebRequest $request)
{
return sfView::SUCCESS;
}

A default index template was also generated for us in the templates folder, that is, apps/frontend/modules/menu/templates/indexSuccess.php. Returning the sfView::SUCCESS constant will render this template for us. The template rendered will depend on the returned string from the action. All templates must also follow the naming convention of actionNameReturnString.php. Therefore, our action called index returns the sfView constant SUCCESS, meaning that the indexSuccess.php template needs to be present within the templates folder for our menu module. We can return other strings, such as these:

  • return sfView::ERROR: Looks for the indexError.php template
  • return myTemplate: Looks for the indexmyTemplate.php template
  • return sfView::NONE: Will not return a template and, therefore, bypass the view layer; this could be used as an example for an AJAX request

However, just removing the $this->forward('default', 'module') function will also return indexSuccess.php by default. It is worth adding the return value for ease in reading. Now that we have rendered the menu template, go ahead and do the same for the home, locations, and vacancies modules.

Symfony 1.3 Web Application Development Design, develop, and deploy feature-rich, high-performance PHP web applications using the Symfony framework
Published: September 2009
eBook Price: £14.99
Book Price: £24.99
See more
Select your format and quantity:

Rendering the template

The final step is to create the needed XHTML to render the template. Views (or templates as they are known) form the presentation layer. Although I am discussing a template as one whole entity, it is not entirely true. Just like all good template frameworks (Smarty, for example), a template can consist of reusable components. As with Symfony, there is no exception.

In a nutshell, as the template is rendered, it pulls in all other modules as they are called (with the exception of slots) and then decorates the template with a wrapper layout template.

Although developers are free to use PHP code in the templates, PHP should be kept to an absolute minimum, and serve only for presentation logic.

There are two folders where we can keep templates—the moduleName/templates folder or the apps/templates folder. The former holds all templates for your module and the latter is where all your global templates reside. If you look inside the global template folder, you will see the global layout template—layout.php. This global template contains all of the code for the outer shell of the module template. This wrapper template is where we have things such as the HTML starting tags, meta tags, title tags, and others, along with the main XHTML closing tags.

Let's look at the main layout template in apps/frontend/templates/layout.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<?php include_http_metas() ?>
<?php include_metas() ?>
<?php include_title() ?>
<link rel="shortcut icon" href="/favicon.ico" />
<?php include_stylesheets() ?>
<?php include_javascripts() ?>
</head>
<body>
<?php echo $sf_content ?>
</body>
</html>

It is worth noting how the meta tags and title tags are included in the first part of the template. These are all passed in either from a view configuration file or by the action as follows:

<?php include_http_metas() ?>
<?php include_metas() ?>
<?php include_title() ?>

The second part is how our module template is included in the global template. In this case, the layout template is rending the raw format of the generated module template. Symfony has a few escaping settings, meaning that it will turn certain characters into their HTML equivalents.

As this layout is a part of the overall template and, therefore, generally present as part of all templates, we are going to add the navigation to this template. But before we do so, we need to add our routing rules so that we can add the navigation links.

Adding our routing rules

At the moment, Symfony is able to find our pages by module/action and because we use the default index action, Symfony will render our template. Now we need to add links to our application. We could just create the links that point to module/action, but this will soon get complicated as the site scales upwards. Besides, there is also a production and development controller involved. So instead of just creating links, we will create the routing rules. Our links will reference the routing rules and, therefore, will generate the URLs for us. Open up the routing.yml file in the apps/frontend/config folder and add the following:

# default rules
homepage:
URL: /
param: { module: default, action: index }
menu:
URL: /menu
param: { module: menu, action: index }
locations:
URL: /locations
param: { module: location, action: index }
vacancies:
URL: /vacancies
param: { module: vacancies, action: index }
default_index:
URL: /:module
param: { action: index }
default:
URL: /:module/:action/*

As you can see, we have followed the same pattern as the default rules. We first added a label and then defined the URL pattern, followed by the module and action. Now let's go back to our layout template.

Make sure your rules are above the default and default_index rules.

To access these routes from within, the template Symfony provides these helpers—link_to() and url_for(). Essentially, a helper is a function that returns HTML. In the case of these two helpers, they will return an HTML link tag. We are going to add the following four links to our layout:

<?php echo link_to('Home', '@home') ?>
<?php echo link_to('Menu', '@menu') ?>
<?php echo link_to('Store Locations', '@locations
<?php echo link_to('Vacancies', '@vacancies

The first parameter passed to the helper is the text that will be displayed as the link. The second parameter references a rule in the routing; we simply start with the @ symbol followed by the routing label. When you look at the final page a little later, you will see that Symfony has correctly inserted the URL for us. Depending on what controller we are using, the correct controller will also be inserted as a part of the URL.

Configuring template parameters

We need to set the page titles in the HTML. As mentioned earlier, templates can be configured in a few ways. Here we are going to set the page title in the template configuration file. To do this, we must create a folder named config within each of the modules that we have already created, and create a view.yml file within the config folder. The view.yml configuration file will contain all of the meta and title descriptions, along with any other template-specific variables. There are many more options that we can set, but for now we will only need to set the basic settings. After you have created both the config folder and the view.yml file within the folder for the menu module, open your view.yml file and add the following:

indexSuccess:
metas:
title: Our Menu

The first parameter references the template by the file name. Our template is indexSuccess.php and so we use the filename minus the extension. Now we would like to set the page title within the metas. This file can now be copied to all the other config folders that you have created; of course, you just have to amend the title. Being able to configure all templates within a module forces a tightly coded application. This file is great if we don't need the title to be dynamic.

After copying this file to all the other modules and changing the titles, you are all done!

Styling the pages

The last step is to add a little CSS to give the pages an initial wireframe feeling. On my layout template, I have added the inline styling which sets the page up.

This is the layout.php template. The highlighted lines indicate where I have added the final CSS:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<?php include_http_metas() ?>
<?php include_metas() ?>
<?php include_title() ?>
<link rel="shortcut icon" href="/favicon.ico" />
<style type="text/css">
body{margin:0; padding:0;font-family: Arial, Verdana, sans-serif;
font-size: 11px;}
a img,:link img,:visited img { border: none; color: #000000; }
</style>
</head>
<body>
<div style="width: 786px; border: 1px solid #000000; margin: auto;">
<div style="height: 100px;">
<div style="text-align: center"><h1>Top Banner</h1></div>
</div>

<div style="width: 192px; float: left; ">
<div style="width: 100%; text-align: left;">
<ul style="list-style-type:none;margin:0;padding:0;">
<li style="margin:0;padding:0.25em 0.5em 0.25em 0.5em;
width: 150px; border-bottom: 1px solid #000000;
border-right: 1px solid #000000; ;
border-top: 1px solid #000000; ">
<?php echo link_to('Home', '@homepage') ?></li>
<li style="margin:0;padding:0.25em 0.5em 0.25em 0.5em;
width: 150px; border-bottom: 1px solid #000000;
border-right: 1px solid #000000; ">
<?php echo link_to('Menu', '@menu') ?></li>
<li style="margin:0;padding:0.25em 0.5em 0.25em 0.5em;
width: 150px; border-bottom: 1px solid #000000;
border-right: 1px solid #000000; ">
<?php echo link_to('Store Locations', '@locations') ?></li>
<li style="margin:0;padding:0.25em 0.5em 0.25em 0.5em;
width: 150px; border-bottom: 1px solid #000000;
border-right: 1px solid #000000; ">
<?php echo link_to('Vacancies', '@vacancies') ?></li>
</ul>
</div>
</div>

<div style="margin-left: 208px">
<div style="min-height: 100px">
<?php echo $sf_data->getRaw('sf_content') ?>
</div>
</div>

<div style="text-align: center"><h1>Footer</h1></div>
<div style="clear:both"></div>
</div>
</body>
</html>

With the result HTML added to our layout, we now get a nice wire frame that resembles the site:

Symfony 1.3 Web Application Development

Debugging:
When developing and trying to troubleshoot, it is important to use the frontend_dev.php controller. Otherwise, the errors will not be revealed as Symfony hides them in a production environment.
Using the development controller means we can use the debug bar at the top of the window to see what is happening. Also, there are log files available to us in the log folder that can be used for troubleshooting.

Common installation problems

When first starting out, there are a few potential problems that you can encounter. Below are a few of the main errors that you might come across.

Web server 404 error page

The requested URL /index.php file was not found on this server.

This is because you haven't created an application. So, on the command line enter:

>symfony app frontend

This will create the application, along with the controllers, index.php and frontend_dev.php.

A symfony 'Oop! An error occurred'

One thing to remember is this page is in fact the default Symfony 500 error page, and not a web server 500 error page. While developing, you should always use the development controller (app_dev.php). The development controller lets you see the exact problem. The production controller (index.php) hides the problem away from the users.

Pages and debug bar do not render correctly

Another common problem is that when you configure your virtual hosts, you will often leave an important line out and therefore will be left seeing a page with no CSS.

Symfony 1.3 Web Application Development

As you can see the above page has lost all CSS styling. This is caused by not including an alias directive in you virtual host configuration file. Include the following in virtual host configuration file:

#Set symfony alias
Alias /sf /usr/share/php/data/symfony/web/sf

On some Linux installations, you need to also include:

<Directory "/usr/share/php/data/symfony/web/sf ">
Allow from all
</Directory >

Summary

By using Symfony's CLI to create a project, a developer can spend more time coding. Also, the initial overview of the controllers, routing, application logic, applications, and modules show how tight and modular Symfony can be to develop with. This enforces that developers adhere to standards that make refactoring, debugging, and extending others' code easy. Also, it helps developers to code in an agile way.

We have covered the basics that have allowed us to get a wireframe version of our milkshake application up and ready. We have used some of the Symfony tasks to generate the majority of files and code, and have added a few little tweaks to get the pages linking and working. Also, we have configured the framework to use the Propel plugin and have the database ready.

 

If you have read this article you may be interested to view :

Symfony 1.3 Web Application Development Design, develop, and deploy feature-rich, high-performance PHP web applications using the Symfony framework
Published: September 2009
eBook Price: £14.99
Book Price: £24.99
See more
Select your format and quantity:

About the Author :


Tim Bowler

Tim Bowler has a Bachelor's Degree in Computer Science, a Masters Degree in Internet Technologies and E-Commerce, and is currently studying for his PhD part time. He has over 10 years of experience in web application development and project management. His experience and determination has gained him membership in the Institute of Engineering and Technology and he is a Chartered IT Professional. Tim started his career developing web applications in PHP4 for a digital media agency in London. Later he introduced agile and scrum into the development process along with Symfony. Tim is now the Managing Director of Agile Labs which is a web application development and agile coaching company.

Books From Packt

jQuery 1.3 with PHP
jQuery 1.3 with PHP

Ext JS 3.0 Cookbook
Ext JS 3.0 Cookbook

PHP Team Development
PHP Team Development

Matplotlib for Python Developers
Matplotlib for Python Developers

Apache MyFaces Trinidad 1.2: A Practical Guide
Apache MyFaces Trinidad 1.2: A Practical Guide

3D Game Development with Microsoft Silverlight 3: Beginner's Guide
3D Game Development with Microsoft Silverlight 3: Beginner's Guide

Zend Framework 1.8 Web Application Development
Zend Framework 1.8 Web Application Development

Joomla! 1.5x Customization: Make Your Site Adapt to Your Needs
Joomla! 1.5x Customization: Make Your Site Adapt to Your Needs

 

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software