TRAJOIN is an Application to Translate symfony documents Jointly.
home > 1.2/cookbook/en > doctrine_admin_generators.txt
[1] Edit ↑TOPこの記事ではDoctrineに慣れるためにsymfony1.2で真新しいプロジェクトを始めます。典型的でありふれたコンテンツマネジメントシステムを使います。スキーマは記事、筆者とカテゴリで構成され記事は国際化されています。
最初に symfony1.2で真新しいプロジェクトとbackendアプリケーションを初期化する必要があります。ベータ1版ではDoctrineの機能が含まれていなかったのでsvnから最新のコードを利用していることを確認して下さい。
プロジェクトを生成する
$ mkdir cms
$ cd cms
$ symfony generate:project cms
データベースを設定する
config/databases.ymlを開きDoctrineのために設定内容を次のように置き換えます:
all:
doctrine:
class: sfDoctrineDatabase
param:
dsn: mysql:host=localhost;dbname=dbname
username: root
password: secret
backendアプリケーションを生成する
$ symfony generate:app backend
Doctrineを有効にしてPropelを無効にする必要があります。config/ProjectConfiguration.class.phpを編集して次のコードをsetup()関数に追加します。
public function setup()
{
$this->enablePlugins(array('sfDoctrinePlugin'));
$this->disablePlugins(array('sfPropelPlugin'));
}
Doctrineが有効になったので利用可能なDoctrineのタスクの一覧を表示できます:
$ ./symfony list doctrine
Available tasks for the "doctrine" namespace:
:build-all Doctrineのモデル、SQLを生成し、データベースを初期化する (doctrine-build-all)
:build-all-load Doctrineのモデル、SQLを生成し、データベースを初期化し、データをロードする (doctrine-build-all-load)
:build-all-reload Doctrineのモデル、SQLを生成し、データベースを初期化し、データをロードする (doctrine-build-all-reload)
:build-all-reload-test-all Doctrineのモデル、SQLを生成し、データベースを初期化し、データをロードしテストスイートを実行する (doctrine-build-all-reload-test-all)
:build-db 現在のモデル用のデータベースを作成する (doctrine-build-db)
:build-filters 現在のモデル用のフィルタクラスを生成する
:build-forms 現在のモデル用のフォームクラスを生成する (doctrine-build-forms)
:build-model 現在のモデル用のクラスを生成する (doctrine-build-model)
:build-schema 既存のデータベースからスキーマを作成する (doctrine-build-schema)
:build-sql 現在のモデル用にSQLを作成する (doctrine-build-sql)
:data-dump データをフィクスチャディレクトリにダンプする (doctrine-dump-data)
:data-load フィクスチャディレクトリからデータをロードする (doctrine-load-data)
:dql DQLクエリを実行して結果を閲覧する (doctrine-dql)
:drop-db 現在のモデル用のデータベースをドロップする (doctrine-drop-db)
:generate-admin Doctrineのadminモジュールを生成する
:generate-migration マイグレーションクラスを生成する (doctrine-generate-migration)
:generate-migrations-db 既存のデータベースの接続からマイグレーションクラスを生成する (doctrine-generate-migrations-db, doctrine-gen-migrations-from-db)
:generate-migrations-models 既存のモデルのセットからマイグレーションクラスを生成する (doctrine-generate-migrations-models, doctrine-gen-migrations-from-models)
:generate-module Doctrineモジュールを生成する (doctrine-generate-crud, doctrine:generate-crud)
:generate-module-for-route routeの定義用にDoctrineモジュールを生成する
:insert-sql 現在のモデルのためにSQLをinsertする (doctrine-insert-sql)
:migrate データベースを現在の/指定されたバージョンにマイグレートする (doctrine-migrate)
:rebuild-db 現在のモデル用のデータベースを作成する (doctrine-rebuild-db)
楽しいことが始まります。最初にすべきことは config/doctrine/schema.yml の中でCMSのためのスキーマを定義することです。
---
Article:
actAs:
Timestampable:
I18n:
fields: [title, content]
columns:
author_id: integer
status:
type: enum
values: [Draft, Published]
notnull: true
title:
type: string(255)
notnull: true
content:
type: clob
notnull: true
is_on_homepage: boolean
published_at: timestamp
relations:
Author:
foreignAlias: Articles
Categories:
class: Category
refClass: ArticleCategory
foreignAlias: Articles
Category:
columns:
name:
type: string(255)
notnull: true
Author:
columns:
name:
type: string(255)
notnull: true
about: string(1000)
ArticleCategory:
columns:
article_id: integer
category_id: integer
relations:
Article:
foreignAlias: ArticleCategories
Category:
foreignAlias: ArticleCategories
スキーマがあり、テストするためのデータが必要なので次のYAMLを data/fixtures/data.yml にコピーします。
---
Article:
Article_1:
Author: jwage
status: Published
is_on_homepage: true
published_at: '<?php echo date("Y-m-d h:i:s"); ?>'
Categories: [article, ontheedge]
Translation:
en:
title: symfony 1.2 and Doctrine
content: Article about the new Doctrine integration in symfony 1.2
fr:
title: symfony 1.2 et doctrine
content: Article sur l'intégration de Doctrine dans symfony 1.2
Author:
jwage:
name: Jonathan H. Wage
about: Jonathan is the lead developer of the Doctrine project and is also a core contributor to the symfony project.
Category:
article:
name: Article
tutorial:
name: Tutorial
ontheedge:
name: Living on the edge
スキーマとデータフィクスチャが揃ったので必要なことはデータベース、モデル、フォーム、データその他を初期化することです。これは下記のような極めて簡単なコマンドで行うことができます:
$ ./symfony doctrine:build-all-reload --no-confirmation
>> doctrine dropping databases
>> doctrine creating databases
>> doctrine generating model classes
>> doctrine generating sql for models
>> doctrine generating form classes
>> doctrine generating filter form classes
>> doctrine created tables successfully
>> doctrine loading data fixtures from "/Us...ymfony12doctrine/data/fixtures"
That was too easy, when is this gonna get hard? データが適切にロードされたかどうかを確認するためにDQLでインスペクションを行いましょう。
$ ./symfony doctrine:dql "FROM Article a, a.Author a2, a.Translation t"
>> doctrine executing dql query
DQL: FROM Article a, a.Author a2, a.Translation t
found 1 results
-
id: '1'
author_id: '1'
status: Published
is_on_homepage: true
published_at: '2008-11-06 04:37:11'
created_at: '2008-11-06 16:37:11'
updated_at: '2008-11-06 16:37:11'
Author:
id: '1'
name: 'Jonathan H. Wage'
about: 'Jonathan is the lead developer of the Doctrine project and is also a core contributor to the symfony project.'
Translation:
en:
id: '1'
title: 'symfony 1.2 and Doctrine'
content: 'Article about the new Doctrine integration in symfony 1.2'
lang: en
fr:
id: '1'
title: 'symfony 1.2 et doctrine'
content: 'Article sur l''intégration de Doctrine dans symfony 1.2'
lang: fr
That may be your first taste of the Doctrine Query LanguageもしくはDQLとも知られますが。SQLによく似ているでしょ?口を閉じて。よだれが垂れてますよ。
生のDQL文字列を書きたくない人へ、クエリーをビルドするための十分な機能を持つ Doctrine_Query オブジェクトがあります。
$q = Doctrine_Query::create()
->from('Article a, a.Author a2, a.Translation t');
$articles = $q->execute();
すべてが組み込まれたので、we can start generating some magic with symfony. Lets start first by defining the route collections for managing our articles, authors and categories. Open apps/backend/config/routing.yml in your editor and paste the following routes inside.
articles:
class: sfDoctrineRouteCollection
options:
model: Article
module: articles
prefix_path: articles
with_wildcard_routes: true
categories:
class: sfDoctrineRouteCollection
options:
model: Category
module: categories
prefix_path: categories
with_wildcard_routes: true
authors:
class: sfDoctrineRouteCollection
options:
model: Author
module: authors
prefix_path: authors
with_wildcard_routes: true
These routes will allow us to generate an admin generator module for managing the data through each of the Doctrine models. 3つのモジュールを生成するために次のコマンドを実行します。
$ ./symfony doctrine:generate-admin backend articles
$ ./symfony doctrine:generate-admin backend categories
$ ./symfony doctrine:generate-admin backend authors
backendから categories モジュールにアクセスすると次の画面が表示されます。

Now you may want to slightly customize the articles admin generators to display only a certain set of fields in the list and filters form. You can do so by editing the generator.yml located in apps/backend/modules/articles/config/generator.yml.
config:
list:
display: [title, published_at, is_on_homepage, status]
filter:
class: ArticleFormFilter
display: [author_id, status, is_on_homepage, published_at, categories_list]
他のモジュールを同じ方法でカスタマイズできます。
Now if you change the url to have ?sf_culture=fr in your url the title will show the french version. You should see the following in your browser when you pull up the articles module.

Now how do we go about editing those translations? 古いadminジェネレータでのやり方を覚えていれば、it was pretty much impossible. Now,
it is a matter of adding one line of code to our ArticleForm. 行う必要があるのは ArticleTranslation フォームを埋め込むことです。
This can be done by editing lib/form/doctrine/ArticleForm.class.php と次のコードを configure() に追加します。
public function configure()
{
$this->embedI18n(array('en', 'fr'));
}
Now when you edit an article you will see you have the ability to edit translations directly inside of the article.

Now that is pretty cool but what if you want to edit the Author directly inside of the Article as well and have it create a new Author if it doesn't exist and use the existing Author record if that name does exist. This is simple as well.
上記の機能を追加するために少量のコードを3つの異なる場所に追加する必要があります。 lib/form/doctrine/ArticleForm.class.php を編集して次のコードを追加することで Article に Author フォームを埋め込みます。
public function configure()
{
unset($this['author_id']);
$authorForm = new AuthorForm($this->getObject()->getAuthor());
unset($authorForm['about']);
$this->embedForm('Author', $authorForm);
$this->embedI18n(array('en', 'fr'));
}
Optionally Optimize QueriesNow we can modify the
articlesactions class to join in theAuthorandTranslationinformation so that the data is joined on the main query and not lazily loaded by Doctrine invoking additional queries to the database. This step is optional. Openapps/backend/modules/articles/actions/actions.class.phpand override theexecuteEdit()function.public function executeEdit(sfWebRequest $request) { $this->article = Doctrine_Query::create() ->from('Article a') ->leftJoin('a.Author a2') ->leftJoin('a.Translation t') ->where('a.id = ?', $request->getParameter('id')) ->fetchOne(); $this->form = $this->configuration->getForm($this->article); }
Now when you view the form for editing and creating an Article you will see the embedded form for the Author with the existing information populated.

Now the last step is to tell Doctrine to look for existing Author objects when setting the name so that duplicate Author names are not created. lib/model/doctrine/Author.class.phpを編集し override the name mutator by adding the following code.
public function setName($name)
{
$name = trim($name);
$found = Doctrine_Query::create()
->select('a.id')
->from('Author a')
->where('a.name = ?', $name)
->fetchOne(array(), Doctrine::HYDRATE_ARRAY);
if ($found)
{
$this->assignIdentifier($found['id']);
} else {
$this->_set('name', $name);
}
}
The above code will check if an Author with the passed name already exists, if it does it will assign the identifier of the found record otherwise it does what it normally would do, set the name to the object.
アクセサとミューテータをオーバーライドするときに無限ループを回避するためには_set()と_get()メソッドを使わなければなりません。
翻訳中の部分も含めてリポジトリからコピー完了 (2008-12-29 12:18:11 brtRiver)
Documentation
| $ ./symfony list doct ... | |
| brtRiver(2009-02-09 13:41:47) | |
| >**NOTE** >The `_se ... | |
| brtRiver(2009-02-09 13:40:35) | |
| >**NOTE** >The `_se ... | |
| brtRiver(2008-12-29 12:14:26) | |
| [php] public func ... | |
| brtRiver(2008-12-29 12:14:02) | |
| Now the last step is to t ... | |
| brtRiver(2008-12-29 12:13:52) | |
| ![New Admin Generators Em ... | |
| brtRiver(2008-12-29 12:13:32) | |
| [php] public func ... | |
| brtRiver(2008-12-29 12:13:09) | |
| In order to add the above ... | |
| brtRiver(2008-12-29 12:13:00) | |
| Edit/Add Author --------- ... | |
| brtRiver(2008-12-29 12:12:48) | |
| ![New Admin Generators I1 ... | |
| brtRiver(2008-12-29 12:12:32) | |
| [php] public func ... | |
| brtRiver(2008-12-29 12:12:14) | |
| Now how do we go about ed ... | |
| brtRiver(2008-12-29 12:12:07) | |
| Editing Translations ---- ... | |
| brtRiver(2008-12-29 12:11:37) | |
|  | |
| You can customize the oth ... | |
| brtRiver(2008-12-29 12:10:41) | |
| [yml] config: ... | |
| brtRiver(2008-12-29 12:10:34) | |
|  | |
| Now when you access the ` ... | |
| brtRiver(2008-12-29 12:10:04) | |
| $ ./symfony doctrine: ... | |
| brtRiver(2008-12-29 12:09:53) | |
| These routes will allow u ... | |
| brtRiver(2008-12-29 12:09:42) |