Skip to content
Caution: You are browsing the legacy symfony 1.x part of this website.

Trabalhando com Doctrine

Language

Quer experimentar o symfony 1.1? Primeiramente vamos ter que configurar um novo projeto e instalar o sfDoctrine para o symfony 1.1. Execute os comandos abaixo e continue lendo:

$ mkdir symfony1.1Doctrine
$ cd symfony1.1Doctrine
$ /path/to/symfony generate:project symfony1.1Doctrine
$ svn co http://svn.symfony-project.com/plugins/sfDoctrinePlugin/trunk plugins/sfDoctrinePlugin
$ php symfony cc

Agora, digite o comando abaixo para listar tudo que o sfDoctrinePlugin oferece. Você vai perceber que o comando vai listar os mesmos comandos do sfPropelPlugin e muitos outros.

$ php symfony list doctrine
Available tasks for the "doctrine" namespace:
  :build-all                   Generates Doctrine model, SQL and initializes the database (doctrine-build-all)
  :build-all-load              Generates Doctrine model, SQL, initializes database, and load data (doctrine-build-all-load)
  :build-all-reload            Generates Doctrine model, SQL, initializes database, and load data (doctrine-build-all-reload)
  :build-all-reload-test-all   Generates Doctrine model, SQL, initializes database, load data and run all test suites (doctrine-build-all-reload-test-all)
  :build-db                    Creates database for current model (doctrine-build-db)
  :build-forms                 Creates form classes for the current model (doctrine-build-forms)
  :build-model                 Creates classes for the current model (doctrine-build-model)
  :build-schema                Creates a schema.xml from an existing database (doctrine-build-schema)
  :build-sql                   Creates SQL for the current model (doctrine-build-sql)
  :data-dump                   Dumps data to the fixtures directory (doctrine-dump-data)
  :data-load                   Loads data from fixtures directory (doctrine-load-data)
  :dql                         Execute a DQL query and view the results (doctrine-dql)
  :drop-db                     Drops database for current model (doctrine-drop-db)
  :generate-crud               Generates a Doctrine CRUD module (doctrine-generate-crud)
  :generate-migration          Generate migration class (doctrine-generate-migration)
  :generate-migrations-db      Generate migration classes from existing database connections (doctrine-generate-migrations-db, doctrine-gen-migrations-from-db)
  :generate-migrations-models  Generate migration classes from an existing set of models (doctrine-generate-migrations-models, doctrine-gen-migrations-from-models)
  :init-admin                  Initializes a Doctrine admin module (doctrine-init-admin)
  :insert-sql                  Inserts SQL for current model (doctrine-insert-sql)
  :migrate                     Migrates database to current/specified version (doctrine-migrate)
  :rebuild-db                  Creates database for current model (doctrine-rebuild-db)

O sfDoctrinePlugin atualmente necessita de pelo menos uma aplicação configurada, então, vamos instanciar a aplicação frontend.

$ php symfony generate:app frontend

Agora vamos configurar nosso banco de dados em config/databases.yml. Abra o arquivo no seu editor predileto e utilize o YAML abaixo. Para esse teste, estamos simplesmente utilizando um banco de dados SQLite. O Doctrine é capaz de criar o banco de dados em config/doctrine.db.

all:
  doctrine:
    class:    sfDoctrineDatabase
    param:
      dsn:    sqlite:///<?php echo dirname(__FILE__); ?>/doctrine.db

Agora que nós temos nosso banco de dados configurado, vamos definir nosso schema em config/doctrine/schema.yml. Nesse exemplo nós estamos configurando o modelo BlogPost que hasMany (possui diversas) , Tags.

---
BlogPost:
  actAs:
    Sluggable:
      fields: [title]
    Timestampable:
  columns:
    title: string(255)
    body: clob
    author: string(255)
  relations:
    Tags:
      class: Tag
      refClass: BlogPostTag
      foreignAlias: BlogPosts
 
BlogPostTag:
  columns:
    blog_post_id:
      type: integer
      primary: true
    tag_id:
      type: integer
      primary: true
 
Tag:
  actAs: [Timestampable]
  columns:
    name: string(255)

Agora que nos temos nosso schema definido, vamos criar uma massa de teste em data/fixtures/data.yml. Abra o arquivo, e cole o YAML abaixo.

---
BlogPost:
  BlogPost_1:
    title:  symfony + Doctrine
    body:   symfony and Doctrine are great!
    author: Jonathan H. Wage
    Tags:   [symfony, doctrine, php]
 
Tag:
  symfony:
    name: symfony
  doctrine:
    name: doctrine
  php:
    name: php

Ok, vamos para parte legal. Nós temos nosso schema, e temos também nossa massa, então vamos rodar uma única fez o comando do Doctrine abaixo para criar nosso banco de dados, gerar os modelos, criar as tabelas e carregar a massa de teste.

$ php symfony doctrine-build-all-reload frontend
>> doctrine  Are you sure you wish to drop your databases? (y/n)
y
>> doctrine  Successfully dropped database f...1.1Doctrine/config/doctrine.db"
>> doctrine  Successfully created database f...1.1Doctrine/config/doctrine.db"
>> doctrine  Generated models successfully
>> doctrine  Created tables successfully
>> doctrine  Data was successfully loaded

Agora nosso banco de dados SQLite doctrine.db foi criado, todas as tabelas do nosso schema foram criadas e populadas. Agora vamos começar a brincar com os dados e ver como nós podemos utilizar o Doctrine Query Language para trazer as informações do banco.

$ php symfony doctrine:dql frontend "FROM BlogPost p, p.Tags t"
>> doctrine  executing: "FROM BlogPost p, p.Tags t" ()
>> doctrine  - 
>> doctrine    id: 1
>> doctrine    title: symfony + Doctrine
>> doctrine    body: symfony and Doctrine are great!
>> doctrine    author: Jonathan H. Wage
>> doctrine    slug: symfony-doctrine
>> doctrine    created_at: 2008-06-16 12:28:57
>> doctrine    updated_at: 2008-06-16 12:28:57
>> doctrine    Tags: 
>> doctrine      - 
>> doctrine        id: 1
>> doctrine        name: symfony
>> doctrine        created_at: 2008-06-16 12:28:57
>> doctrine        updated_at: 2008-06-16 12:28:57
>> doctrine      - 
>> doctrine        id: 2
>> doctrine        name: doctrine
>> doctrine        created_at: 2008-06-16 12:28:57
>> doctrine        updated_at: 2008-06-16 12:28:57
>> doctrine      - 
>> doctrine        id: 3
>> doctrine        name: php
>> doctrine        created_at: 2008-06-16 12:28:57
>> doctrine        updated_at: 2008-06-16 12:28:57

Agora, vamos explicar um pouco os resultados obtidos. Como você pode ver, nos modelos nós temos as colunas created_at, updated_at and slug que não foram definidas no schema. Essas colunas são adicionadas pelo behavior anexado ao schema dentro da configuração actAs. As colunas created_at e updated_at são automaticamente atualizadas onInsert e onUpdate, e a coluna do slug é uma string criada baseada na coluna name para ser utilizada na url(url amigável). O Doctrine tem alguns behaviors que são incluídos no core como Sluggable e Timestampable, mas o sistema de behavior é feito para permitir que qualquer pessoa escreva novos behaviors para os modelos e serem reutilizados.

Agora que nós temos nossa base configurada e populada, vamos fazer alguns testes utilizando o admin generator para manipular os posts e tags do blog.

$ php symfony doctrine:init-admin frontend blog_posts BlogPost
$ php symfony doctrine:init-admin frontend tags Tag

Nota Os templates do admin generator para sfDoctrinePlugin ainda não foram totalmente atualizados para o symfony 1.1, então vamos precisar ativar a opção compat_10 em apps/frontend/config/settings.yml. Eles vão ser atualizados antes do lançamento da versão estável do symfony 1.1.

Agora vamos abrir nosso browser e verificar a aplicação frontend e os módulos blog_posts e tags. Eles devem ser localizados numas urls parecida com essas

$ http://localhost/symfony1.1Doctrine/web/frontend_dev.php/blog_posts
$ http://localhost/symfony1.1Doctrine/web/frontend_dev.php/tags

blog posts

Agora, com um pouco de configuração no admin generator do blog_post, nós podemos controlar o relacionamento entre blog_post e tags marcando checkboxes quando editando um post. Abra o arquivo apps/frontend/modules/blog_posts/config/generator.yml e troque o conteúdo pelo YAML abaixo:

generator:
  class:              sfDoctrineAdminGenerator
  param:
    model_class:      BlogPost
    theme:            default
    list:
      display:        [=title, author]
      object_actions:
        _edit:        -
        _delete:      -
    edit:
      display:        [author, title, body, Tags]
      fields:
        author:
          type:       input_tag
        title:
          type:       input_tag
        body:
          type:       textarea_tag
          params:     size=50x10
        Tags:
          type:       doctrine_admin_check_list
          params:     through_class=BlogPostTag

Agora atualize (f5) seu browser para listar os posts do blog. Você vai ver tudo de uma maneira mais limpa. Edite um post clicando no ícone ou no título. Veja abaixo como você pode marcar as tags associadas ao post.

edit blog posts

99% das ferramentas que você vê funcionando no Propel, você pode ver também no Doctrine. Então, é fácil entender e aplicar. O sfDoctrinePlugin implementa todas as funcionalidades que o sfPropelPlugin e algumas mais. Nos links abaixo você pode obter mais informação sobre o que o Doctrine suporta.

  • Behaviors - Easily create reusable behaviors for your Doctrine models.
  • Migrations - Deploy database schema changes to your production environment through a programmatic interface.
  • Doctrine Query Language - Build your database queries through a fluent OO interface
  • Validators - Turn on column validators for both database and code level validation.
  • Hierarchical Data - Turn your models in to nested sets easily with the flip of a switch.
  • Caching - Tune performance by caching your DQL query parsing and the result sets of queries.

Se esse pequeno tutorial despertou seu interesse no Doctrine, você pode encontrar mais informações do Doctrine abaixo e aprender um pouco mais sobre ele:

This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.