The definitive guide of Symfony 1.0

1.2. Fundamental Concepts

Before you get started with symfony, you should understand a few basic concepts. Feel free to skip ahead if you already know the meaning of OOP, ORM, RAD, DRY, KISS, TDD, YAML, and PEAR.

1.2.1. PHP 5

Symfony is developed in PHP 5 (php.net) and dedicated to building web applications with the same language. Therefore, a solid understanding of PHP 5 is required to get the most out of the framework.

Developers who already know PHP 4 but not PHP 5 should mainly focus on the language's new object-oriented model.

1.2.2. Object-Oriented Programming (OOP)

Object-oriented programming (OOP) will not be explained in this chapter. It needs a whole book itself! Because symfony makes extensive use of the object-oriented mechanisms available as of PHP 5, OOP is a prerequisite to learning symfony.

Wikipedia explains OOP as follows:

"The idea behind object-oriented programming is that a computer program may be seen as comprising a collection of individual units, or objects, that act on each other, as opposed to a traditional view in which a program may be seen as a collection of functions, or simply as a list of instructions to the computer."

PHP 5 implements the object-oriented paradigms of class, object, method, inheritance, and much more. Those who are not familiar with these concepts are advised to read the related PHP documentation, available at php.net/manual/en/language.oop5.basic.php.

1.2.3. Magic Methods

One of the strengths of PHP's object capabilities is the use of magic methods. These are methods that can be used to override the default behavior of classes without modifying the outside code. They make the PHP syntax less verbose and more extensible. They are easy to recognize, because the names of the magic methods start with two underscores (__).

For instance, when displaying an object, PHP implicitly looks for a __toString() method for this object to see if a custom display format was defined by the developer:

$myObject = new myClass();
echo $myObject;
// Will look for a magic method
echo $myObject->__toString();

Symfony uses magic methods, so you should have a thorough understanding of them. They are described in the PHP documentation (php.net/manual/en/language.oop5.magic.php).

1.2.4. PHP Extension and Application Repository (PEAR)

PEAR is "a framework and distribution system for reusable PHP components". PEAR allows you to download, install, upgrade, and uninstall PHP scripts. When using a PEAR package, you don't need to worry about where to put scripts, how to make them available, or how to extend the command-line interface (CLI).

PEAR is a community-driven project written in PHP and shipped with standard PHP distributions.

Tip The PEAR website, pear.php.net, provides documentation and packages grouped by categories.

PEAR is the most professional way to install vendor libraries in PHP. Symfony advises the use of PEAR to keep a central installation point for use across multiple projects. The symfony plug-ins are PEAR packages with a special configuration. The symfony framework itself is available as a PEAR package.

You don't need to know all about the PEAR syntax to use symfony. You just need to understand what it does and have it installed. You can check that PEAR is installed in your computer by typing the following in a CLI:

> pear info pear

This command will return the version number of your PEAR installation.

The symfony project has its own PEAR repository, or channel. Note that channels are available only since version 1.4.0 of PEAR, so you should upgrade if your version is older. To upgrade your version of PEAR, issue the following command:

> pear upgrade PEAR

1.2.5. Object-Relational Mapping (ORM)

Databases are relational. PHP 5 and symfony are object-oriented. In order to access the database in an object-oriented way, an interface translating the object logic to the relational logic is required. This interface is called an object-relational mapping, or ORM.

An ORM is made up of objects that give access to data and keep business rules within themselves.

One benefit of an object/relational abstraction layer is that it prevents you from using a syntax that is specific to a given database. It automatically translates calls to the model objects to SQL queries optimized for the current database.

This means that switching to another database system in the middle of a project is easy. Imagine that you have to write a quick prototype for an application, but the client has not decided yet which database system would best suit his needs. You can start building your application with SQLite, for instance, and switch to MySQL, PostgreSQL, or Oracle when the client is ready to decide. Just change one line in a configuration file, and it works.

An abstraction layer encapsulates the data logic. The rest of the application does not need to know about the SQL queries, and the SQL that accesses the database is easy to find. Developers who specialize in database programming also know clearly where to go.

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:

public function getName()
{
  return $this->getFirstName().' '.$this->getLastName();
}

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:

public function getTotal()
{
  $total = 0;
  foreach ($this->getItems() as $item)
  {
    $total += $item->getPrice() * $item->getQuantity();
  }
  return $total;
}

And that's it. Imagine how long it would have required to write a SQL query doing the same thing!

Propel, another open source project, is currently one of the best object/relational abstraction layers for PHP 5. Symfony integrates Propel seamlessly into the framework, so most of the data manipulation described in this book follows the Propel syntax. This book will describe how to use the Propel objects, but for a more complete reference, a visit to the Propel website (propel.phpdb.org/trac/) is recommended.

1.2.6. Rapid Application Development (RAD)

Programming web applications has long been a tedious and slow job. Following the usual software engineering life cycles (like the one proposed by the Rational Unified Process, for instance), the development of web applications could not start before a complete set of requirements was written, a lot of Unified Modeling Language (UML) diagrams were drawn, and tons of preliminary documentation were produced. This was due to the general speed of development, to the lack of versatility of programming languages (you had to build, compile, restart, and who knows what else before actually seeing your program run), and most of all, to the fact that clients were quite reasonable and didn't change their minds constantly.

Today, business moves faster, and clients tend to constantly change their minds in the course of the project development. Of course, they expect the development team to adapt to their needs and modify the structure of an application quickly. Fortunately, the use of scripting languages like Perl and PHP makes it easy to apply other programming strategies, such as rapid application development (RAD) or agile software development.

One of the ideas of these methodologies is to start developing as soon as possible so that the client can review a working prototype and offer additional direction. Then the application gets built in an iterative process, releasing increasingly feature-rich versions in short development cycles.

The consequences for the developer are numerous. A developer doesn't need to think about the future when implementing a feature. The method used should be as simple and straightforward as possible. This is well illustrated by the maxim of the KISS principle: Keep It Simple, Stupid.

When the requirements evolve or when a feature is added, existing code usually has to be partly rewritten. This process is called refactoring, and happens a lot in the course of a web application development. Code is moved to other places according to its nature. Duplicated portions of code are refactored to a single place, thus applying the Don't Repeat Yourself (DRY) principle.

And to make sure that the application still runs when it changes constantly, it needs a full set of unit tests that can be automated. If well written, unit tests are a solid way to ensure that nothing is broken by adding or refactoring code. Some development methodologies even stipulate writing tests before coding--that's called test-driven development (TDD).

Note There are many other principles and good habits related to agile development. One of the most effective agile development methodologies is called Extreme Programming (abbreviated as XP), and the XP literature will teach you a lot about how to develop an application in a fast and effective way. A good starting place is the XP series books by Kent Beck (Addison-Wesley).

Symfony is the perfect tool for RAD. As a matter of fact, the framework was built by a web agency applying the RAD principle for its own projects. This means that learning to use symfony is not about learning a new language, but more about applying the right reflexes and the best judgment in order to build applications in a more effective way.

The symfony project website proposes a step-by-step tutorial illustrating the development of an application in an agile way. It is called askeet (symfony-project.org/askeet), and is recommended reading for those who want to learn more about agile development.

1.2.7. YAML

According to the official YAML website (yaml.org), YAML is "a straightforward machine parsable data serialization format designed for human readability and interaction with scripting languages". Put another way, YAML is a very simple language used to describe data in an XML-like way but with a much simpler syntax. It is especially useful to describe data that can be translated into arrays and hashes, like this:

$house = array(
  'family' => array(
    'name'     => 'Doe',
    'parents'  => array('John', 'Jane'),
    'children' => array('Paul', 'Mark', 'Simone')
  ),
  'address' => array(
    'number'   => 34,
    'street'   => 'Main Street',
    'city'     => 'Nowheretown',
    'zipcode'  => '12345'
  )
);

This PHP array can be automatically created by parsing the YAML string:

house:
  family:
    name:     Doe
    parents:
      - John
      - Jane
    children:
      - Paul
      - Mark
      - Simone
  address:
    number: 34
    street: Main Street
    city: Nowheretown
    zipcode: "12345"

In YAML, structure is shown through indentation, sequence items are denoted by a dash, and key/value pairs within a map are separated by a colon. YAML also has a shorthand syntax to describe the same structure with fewer lines, where arrays are explicitly shown with [] and hashes with {}. Therefore, the previous YAML data can be written in a shorter way, as follows:

house:
  family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] }
  address: { number: 34, street: Main Street, city: Nowheretown, zipcode: "12345" }

YAML is an acronym for "YAML Ain't Markup Language" and pronounced "yamel". The format has been around since 2001, and YAML parsers exist for a large variety of languages.

Tip The specifications of the YAML format are available at yaml.org.

As you can see, YAML is much faster to write than XML (no more closing tags or explicit quotes), and it is more powerful than .ini files (which don't support hierarchy). That is why symfony uses YAML as the preferred language to store configuration. You will see a lot of YAML files in this book, but it is so straightforward that you probably don't need to learn more about it.