BEAR.SundayでDoctrine2のORMを使ってみた

リソース志向フレームワークBEAR.SundayでDoctrine\ORMを使ってみた。
DB接続設定がべた書きでテスト時にどうやって切り替えたらいいのかまだわからない上に、（主にBEARの）使い方として間違ってないのか？と微妙に不安ながら、一応動いたところまでメモ。
※思考過程ダダ漏れの、ただのメモです。

参考にしたのはこちら
https://github.com/BEARSunday/bearsunday.github.io/wiki/workshop#di%E3%81%A7%E3%83%AD%E3%82%B0%E3%82%92%E6%8F%90%E4%BE%9B
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html


アプリケーションの想定
---------------------------

シンプルなメモAPI。
認証等はひとまず考えない。
apiにget/post/update/deleteのリクエストを投げるとDBのデータをいい感じに取得・作成・更新・削除できればいいな。

BEAR.Sundayインストール
---------------------------

https://github.com/BEARSunday/bearsunday.github.io/wiki/workshop#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB
の通り。プロジェクト名は仮でMy.NoteAppとする。

```bash
composer create-project bear/skeleton My.NoteApp
cd My.NoteApp
composer install
```

AppResourceでの利用イメージを考える
---------------------------

Doctrine\ORMのEntityManagerを、BEARのAppResourceでこんな感じで利用できたらいいなーという目標を立てた。

```php
// src/Resource/App/Note.php

namespace My\NoteApp\Resource\App;

use BEAR\Resource\ResourceObject;

class Note extends ResourceObject
{
    public function onGet($id)
    {
        $note = $this->entityManager->find('...', $id);
        $this['note'] = ['body' => $note->getBody()];

        return $this;
    }
}

```

Providerを書く
---------------

ワークショップのMonologProviderと同じように、Doctrine\ORM\EntityManagerを作ってくれるProviderを作ることにした。
mysql環境を作るのが面倒なので仮でsqliteで。
DBファイルの配置先はBEAR.Packageのvar以下を眺めて、仮でvar/dbに置くことに決めた。
Doctrine\ORM\EntityManagerの作り方は下記を参考に適当に ~~コピペ~~ 書いた。
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html#obtaining-the-entitymanager

```php
// src/Module/Provider/DoctrineORMProvider

namespace My\NoteApp\Module\Provider;

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Ray\Di\ProviderInterface;
use BEAR\Sunday\Inject\AppDirInject;

class DoctrineORMProvider implements ProviderInterface
{
    use AppDirInject;

    public function get()
    {
        $config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/../Entity"), false);
        $conn = array(
          'driver' => 'pdo_sqlite',
          'path' => $this->appDir . '/var/db/db.sqlite',
        );
        $entityManager = EntityManager::create($conn, $config);

        return $entityManager;
    }
} 
```

追記：
@kenji_sさんがBEAR式の設定を注入する方法をブログに書いてくださっています。
BEAR.SundayでDoctrine2のORMを使ってみた（改）
http://blog.a-way-out.net/blog/2014/07/11/bear-sunday-doctrine/


ProviderをDIに登録
--------------------

src/Module/AppModule.php（最初から存在している）に自作のDoctrineORMProviderを登録。

```php
// src/Module/AppModule.php
    protected function configure()
    {
        $this->install(...); // 最初から書いてある部分

        $this->bind('Doctrine\ORM\EntityManager')->toProvider('My\NoteApp\Module\Provider\DoctrineORMProvider'); // bind,toProviderともに最初のバックスラッシュは要らなかった
    }
```


entityを書く
-----------------

entityの置き場所は他に適切なところが思いつかなかったのでsrc配下にEntityディレクトリを作ってそこに置くことにする。（実はProviderを書いた時点で決めてあって、設定にそれ書いてた）
下記を参考にidとbodyだけのNoteエンティティを書く。
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html#starting-with-the-product
普段Symfony2でDoctrine2のentity書くときとは少しアノテーションの書き方が違うので要注意。

```php
// src/Entity/Note.php

namespace My\NoteApp\Entity;

/**
 * @Entity
 * @Table(name="note")
 */
class Note
{
    /**
     * @var int
     * @Id
     * @Column(type="integer")
     * @GeneratedValue
     */
    private $id;

    /**
     * @var string
     * @Column(type="text")
     */
    private $body;

    // getter,setterは省略
}
```

本当はここでDBにテーブル作成するんだけど、BEAR.Sundayでのコマンドの書き方がわからなかった（汗）のと、Doctrine\ORMのスクリプト書くのも面倒だったので、コマンドでサクッと済ませた。
ついでにテストデータも登録。

```bash
sqlite3 var/db/db.sqlite
> create table note(id INTEGER PRIMARY AUTOINCREMENT NOT NULL, body TEXT NULL);
> insert into note(body) values('test body1');
> insert into note(body) values('test body2');
> .exit
```

実際のAppResourceを書く
----------------------

ここまでで、最初に想定した利用法でDoctrine\ORM\EntityManagerが使えるようになったはず！
早速NoteリソースにEntityManagerをセットして使ってみよう。
私が作るNoteというAppResourceは、どのメソッドでもEntityManagerを使う想定（本来の使い方とは違うかもしれない？）なので、コンストラクタインジェクションでいいだろう。

```php
// src/Resource/App/Note.php

namespace My\NoteApp\Resource\App;

use BEAR\Resource\ResourceObject;
use Doctrine\ORM\EntityManager;
use Ray\Di\Di\Inject;

class Note extends ResourceObject
{
    /**
     * @var EntityManager
     */
    private $entityManager;

    /**
     * @param EntityManager $entityManager
     * @Inject
     */
    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function onGet($id)
    {
        $note = $this->entityManager->find('\My\NoteApp\Entity\Note', $id);
        $this['note'] = ['body' => $note->getBody()];

        return $this;
    }
}

```

実際にNoteをgetしてみる。

```bash
php bootstrap/contexts/api.php get 'app://self/note?id=1'
[BODY]
note => array(
    body test body1
),

[VIEW]
{
    "note": {
        "body": "test body1"
    },
    "_links": {
        "self": {
            "href": "http://localhost/app/note/?id=1"
        }
    }
}
```

やったー！無事に動きました:)
（次回に続く http://qiita.com/77web@github/items/aa4d4e4faca38300eaec ）