scribble

Xujiajun Blog

About Blog Email GitHub

27 May 2014
Databases and Propel [第9天]

One of the most common and challenging tasks for any application involves persisting and reading information to and from a database. Symfony2 does not come integrated with any ORMs but the Propel integration is easy. To install Propel, read Working With Symfony2 on the Propel documentation.

A Simple Example: A Product¶

In this section, you’ll configure your database, create a Product object, persist it to the database and fetch it back out.

Tips:

Code along with the Example If you want to follow along with the example in this chapter, create an AcmeStoreBundle via:

$ php app/console generate:bundle --namespace=Acme/StoreBundle

Configuring the Database¶

Before you can start, you’ll need to configure your database connection information. By convention, this information is usually configured in an app/config/parameters.yml file:

# app/config/parameters.yml
parameters:
    database_driver:   mysql
    database_host:     localhost
    database_name:     test_project
    database_user:     root
    database_password: password
    database_charset:  UTF8

Tips:

Defining the configuration via parameters.yml is just a convention. The parameters defined in that file are referenced by the main configuration file when setting up Propel:

These parameters defined in parameters.yml can now be included in the configuration file (config.yml):

propel:
    dbal:
        driver:   "%database_driver%"
        user:     "%database_user%"
        password: "%database_password%"
        dsn:      "%database_driver%:host=%database_host%;dbname=%database_name%;charset=%database_charset%"

Now that Propel knows about your database, Symfony2 can create the database for you:

$ php app/console propel:database:create

Tips:

In this example, you have one configured connection, named default. If you want to configure more than one connection, read the PropelBundle configuration section.

Creating a Model Class¶

In the Propel world, ActiveRecord classes are known as models because classes generated by Propel contain some business logic.

Tips:

For people who use Symfony2 with Doctrine2, models are equivalent to entities.

Suppose you’re building an application where products need to be displayed. First, create a schema.xml file inside the Resources/config directory of your AcmeStoreBundle:

<?xml version="1.0" encoding="UTF-8" ?>
<database name="default"
    namespace="Acme\StoreBundle\Model"
    defaultIdMethod="native"
>
    <table name="product">
        <column name="id"
            type="integer"
            required="true"
            primaryKey="true"
            autoIncrement="true"
        />
        <column name="name"
            type="varchar"
            primaryString="true"
            size="100"
        />
        <column name="price"
            type="decimal"
        />
        <column name="description"
            type="longvarchar"
        />
    </table>
</database>

Building the Model¶

After creating your schema.xml, generate your model from it by running:

$ php app/console propel:model:build

This generates each model class to quickly develop your application in the Model/ directory of the AcmeStoreBundle bundle.

Creating the Database Tables/Schema¶

Now you have a usable Product class and all you need to persist it. Of course, you don’t yet have the corresponding product table in your database. Fortunately, Propel can automatically create all the database tables needed for every known model in your application. To do this, run:

$ php app/console propel:sql:build
$ php app/console propel:sql:insert --force

Your database now has a fully-functional product table with columns that match the schema you’ve specified.

Tips:

You can run the last three commands combined by using the following command: php app/console propel:build –insert-sql.

Persisting Objects to the Database¶

Now that you have a Product object and corresponding product table, you’re ready to persist data to the database. From inside a controller, this is pretty easy. Add the following method to the DefaultController of the bundle:

// src/Acme/StoreBundle/Controller/DefaultController.php

// ...
use Acme\StoreBundle\Model\Product;
use Symfony\Component\HttpFoundation\Response;

public function createAction()
{
    $product = new Product();
    $product->setName('A Foo Bar');
    $product->setPrice(19.99);
    $product->setDescription('Lorem ipsum dolor');

    $product->save();

    return new Response('Created product id '.$product->getId());
}

In this piece of code, you instantiate and work with the $product object. When you call the save() method on it, you persist it to the database. No need to use other services, the object knows how to persist itself.

Tips:

If you’re following along with this example, you’ll need to create a route that points to this action to see it in action.

Fetching Objects from the Database¶

Fetching an object back from the database is even easier. For example, suppose you’ve configured a route to display a specific Product based on its id value:

// ...
use Acme\StoreBundle\Model\ProductQuery;

public function showAction($id)
{
    $product = ProductQuery::create()
        ->findPk($id);

    if (!$product) {
        throw $this->createNotFoundException(
            'No product found for id '.$id
        );
    }

    // ... do something, like pass the $product object into a template
}

Til next time,
Xujiajun at 08:37

scribble

About Blog Email GitHub