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

77webさんの「BEAR.SundayでDoctrine2のORMを使ってみた」を試しつつ、少しだけ改良してみます。

BEAR.Sundayのインストール

ベンダー名はMy、アプリケーション名はNoteとします。これらの指定は名前空間で使われます。

$ composer create-project bear/skeleton My.Note dev-develop
$ cd My.Note
$ composer install

なお、ここではdev-developを指定して開発ブランチ(developブランチ)をインストールしています。

Doctrineのインストール

$ composer require 'doctrine/orm:2.4.*'

データベース接続設定

BEAR.Sundayではデータベース接続設定はvar/conf/constants.phpで定義します。

具体的にはデフォルトで以下のようになっています。

var/conf/constants.php

$masterDb = $slaveDb = require __DIR__  .'/db/sqlite.php';
//list($masterDb, $slaveDb) = require __DIR__  .'/db/mysql.php';

return [
    'prod' => [
        // optional
        'master_db' => $masterDb,
        'slave_db' => $slaveDb,
    ],
    'dev' => [],
    'api' => [],
    'test' => []
];

$masterDb$slaveDbが定義されていますが、いずれもdb/sqlite.phpが代入されています。

prod環境(本番環境)でこれらのデータベースが指定されていますが、prod環境の設定が他の環境にも引き継がれるため、デフォルトではすべての環境でのデータベース接続設定は同じになっています。

db/sqlite.phpでは具体的には以下のように定義されています。

var/db/sqlite.php

$sqlite = [
    'driver' => 'pdo_sqlite',
    'path' =>  $appDir . '/var/db/posts.sq3'
];

つまり、var/db/posts.sq3が使用されるSQLiteのデータベースファイルということになります。

ここでは、デフォルトのままにします。

Providerの作成

DoctrineのEntityManagerを返すProviderを作成します。

とりあえず、マスターとスレーブの切り替えは考慮しません。

src/Module/Provider/DoctrineORMProvider.php

<?php

namespace My\Note\Module\Provider;

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Ray\Di\ProviderInterface;
use Ray\Di\Di\Inject;
use Ray\Di\Di\Named;

class DoctrineORMProvider implements ProviderInterface
{
    /**
     * @param array $masterDb
     *
     * @Inject
     * @Named("masterDb=master_db")
     */
    public function __construct(array $masterDb)
    {
        $this->masterDb = $masterDb;
    }

    public function get()
    {
        $paths = [__DIR__.'/../../Entity'];
        $isDevMode = false;

        $config = Setup::createAnnotationMetadataConfiguration(
            $paths, $isDevMode
        );
        $conn = $this->masterDb;

        return EntityManager::create($conn, $config);
    }
}

コンストラクタインジェクションでデータベース接続設定のmaster_dbをプロパティに代入しています。

Providerのインストール

DoctrineORMProviderを使うようにインストールします。

My\Note\Module\AppModuleクラスのconfigure()メソッドの最後に以下を追加します。

src/Module/AppModule.php

$this->bind('Doctrine\ORM\EntityManager')->toProvider('My\Note\Module\Provider\DoctrineORMProvider');

Entityの作成

Entityを作成します。

src/Entity/Note.php

<?php

namespace My\Note\Entity;

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

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

    public function getId() {
        return $this->id;
    }

    public function getBody() {
        return $this->body;
    }

    public function setId($id) {
        $this->id = $id;
    }

    public function setBody($body) {
        $this->body = $body;
    }
}

doctrineコマンドを使えるようにする

cli-config.phpをプロジェクトのルートディレクトリに作成します。

<?php

error_reporting(E_ALL);
ini_set('xdebug.max_nesting_level', 300);

require __DIR__ . '/bootstrap/autoload.php';

use My\Note\Module\AppModule;
use Ray\Di\Injector;
use Doctrine\ORM\Tools\Console\ConsoleRunner;

$module = new AppModule();
$injector = Injector::create([$module]);
$entityManager = $injector->getInstance('Doctrine\ORM\EntityManager');

return ConsoleRunner::createHelperSet($entityManager);

テーブルの作成

doctrineコマンドでテーブルを作成します。

$ php vendor/bin/doctrine orm:schema-tool:create

テストデータの登録

とりあえず、sqlite3コマンドでinsertしておきます。

$ sqlite3 var/db/posts.sq3

> insert into note(body) values('test body1');
> insert into note(body) values('test body2');
> .exit

Appリソースの作成

AppリソースNoteを作成します。

src/Resource/App/Note.php

<?php

namespace My\Note\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\Note\Entity\Note', $id);
        $this['note'] = ['body' => $note->getBody()];

        return $this;
    }
}

コンストラクタインジェクションでEntityManagerをプロパティに代入しています。

Noteリソースの取得

CLIからNoteリソースを取得してみます。

$ php bootstrap/contexts/api.php get 'app://self/note?id=1'

200 OK
content-type: ["application\/hal+json; charset=UTF-8"]
cache-control: ["no-cache"]
date: ["Fri, 11 Jul 2014 03:48:55 GMT"]
[BODY]
note => array(
  body test body1,
),

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

うまく取得できました!

参考

Date: 2014/07/11

Tags: php, bear, doctrine, orm, database