Doctrine2 を Ethna2.6 に導入してみた

■用語

・エンティティ

ゲッター/セッターの集合体
ロジックは書かない、ロジックはリポジトリに委ねる

・リポジトリ

ロジックや DQL を書くところ
DQL を閉じ込めることで可視性の高いソースにする

・プロキシ

キャッシュとか遅延読み込みとからしい
特に意識する必要はないがあるといいらしい

・ライフサイクルイベント

データの保存や取得などのイベント発生時に特定の処理を行うことが出来る
例えば、更新日時を更新する、ログを取る、など

・フィールドタイプ

カラムの型、データベースに依存しない専用の型をサポートしている
フィールドオプションも type, length, unique, nullable, format などがある

■準備

□Ethna プロジェクト内に Doctrine 用のディレクトリを作成

プロジェクト/app/orm/Entities
プロジェクト/app/orm/Proxies
プロジェクト/app/orm/Repositories
プロジェクト/app/orm/yaml
プロジェクト/app/orm/bootstrap.php
プロジェクト/cli-config.php

あと、DB 用意したりネットを参照して諸々設定をする

□エンティティマネージャ

bootstrap.php 内で $EntityManager というインスタンス生成

$EntityManager = DoctrineORMEntityManager::create($conn, $config);

プロジェクト_Backend クラスのコンストラクタで bootstrap.php を読み込み移譲する

require_once 'orm/bootstrap.php';
$this->em = $EntityManager;

■テーブルを作成

※コマンドは cli-config.php のある場所で実行

1..ymlファイルを作成

※エンティティクラスのアノテーションや xml を利用することもできる

2.エンティティクラスを作成

doctrine orm:generate-entities app/orm

3.プロキシクラスやレポジトリクラスも作成しておく

doctrine orm:generate-proxies app/orm/Proxies
doctrine orm:generate-repositories app/orm

4.SQL 実行してテーブル作成

doctrine orm:schema-tool:update --force

※テーブル作成時にエラー

[PDOException]
SQLSTATE[HY000] [2002] No such file or directory

→pdo_mysql.default_socket=/tmp/mysql.sock に設定

■基本の使い方

□プライマリキーで1件取得

$this->backend->em->find('EntitiesOwner',$id);

□特定の条件に当てはまるリストを取得

$this->backend->em->getRepository('EntitiesOwner')
->findBy(array(
'id' => $id,
'flag' => 0
)
);

□特定の条件に当てはまる1件を取得

$this->backend->em->getRepository('EntitiesOwner')
->findOneBy(array(
'id' => $id,
'flag' => 0
)
);

□挿入/更新

if ($id) {
$Owner = $this->backend->em->find('EntitiesOwner', $id);
} else {
$Owner = new EntitiesOwner;
}

$Owner->setFlag($this->af->get('flag'));
$Owner->setData($this->af->get('data'));

$this->backend->em->persist($Owner); // 永続化
$this->backend->em->flush(); // SQL 実行

■リレーション

□リレーションをマッピング

・リレーションには以下のパターンがある
個対個(oneToOne)、個対多(oneToMany)、多対個(manyToOne)、多対多(manyToMany)

・サンプル
以下の例では oneToMany のプロパティが manyToOne の inversedBy に
manyToOne のプロパティが oneToMany の mappedBy に指定されている
referencedColumnName が実際に結合する際に利用するカラム名
referencedColumnName は外部制約キーとなる

◇商品が所属するカテゴリの yaml(親)

EntitiesCategory:
type: entity

fields:
id:
no:
type: integer
generator: { strategy: AUTO }

oneToMany:
products:
targetEntity: EntitiesProduct
mappedBy: category

◇商品の yaml(子)

EntitiesProductProduct:
type: entity

fields:
id:
no:
type: integer
generator: { strategy: AUTO }

manyToOne:
category:
targetEntity: EntitiesCategory
inversedBy: products
joinColumn:
name: category_id ←下記のエイリアス
referencedColumnName: id ←親のプライマリーキー

※yaml 記述の際にはインデントに気をつける、失敗した
※親子の関係を意識しないとなかなかうまくいかない

□保存

$Category = new EntitiesCategoryCategory;
$Product = new EntitiesProductProduct;
$Category->setHoge('hoge');
:
$Product->setHuga('huga');
:
$Product->setCategory($Category); // ここ忘れがち
$this->backend->em->persist($Category);
$this->backend->em->persist($Product);
$this->backend->em->flush();

□取得

$productName = $product->getName();
$categoryName = $product->getCategory()->getName();

※oneToMany の場合は配列になる

foreach ($Category->getProducts() as $product) {
echo $product->getProductName();
}

かわのくんとは

Web系IT企業でプログラミングやマネジメントをしています。趣味で音楽を少々。

Youtubeでライブ動画配信中

Ustreamでライブ動画配信中

スマートフォン向けにPCサイトを自動変換(コンバート)する『CONV2SP』 CSS作成支援ツール『CSSツクール』