FuelPHPでdoctrine2を使ってみた

  • 17
    Like
  • 0
    Comment
More than 1 year has passed since last update.

仕事でどうしてもFuelPHPでOracleを扱う必要があり、
標準のORMでは扱うことが出来なかったため他の手段を探していた。

Symfonyで使われているdoctrine2が使えれば楽だなと思い少し試した話をメモしておく。

※ データベースのテーブルは作ってある前提

doctrine2を使うためのライブラリ

調べてみると既にライブラリがあったのでそれを利用してみる。

https://github.com/aspendigital/fuel-doctrine2

構成

最初は以下の様な標準のディレクトリ構成にする。

yourdirectory/
    core/               # fuelphpのcore 
    packages/           # fuelphpのpackages
    app/                # fuelphpのapp
        bootstrap.php
        classes/
        config/
        views/
        vendor/         # この下にライブラリを置く

インストール

composerでインストールが可能なので、まずcomposer.jsonを作る。

composer.json
{
    "require": {
        "aspendigital/fuel-doctrine2": "dev-master"
    },
    "config": {
        "vendor-dir": "app/vendor"
    },
    "minimum-stability": "dev"
}

composerでinstallする。

$ curl -s 'http://getcomposer.org/installer' |php
$ php composer.phar install

ちゃんとインストールされれば app/vendor の下に色々置かれているはず。

doctrine2を使うための設定

autoload

何もしないと読み込まれず使えないので読み込まれるようにする。

app/bootstrap.php
<?php

// Load in the Autoloader
require COREPATH.'classes'.DIRECTORY_SEPARATOR.'autoloader.php';
class_alias('Fuel\\Core\\Autoloader', 'Autoloader');

// Bootstrap the framework DO NOT edit this
require COREPATH.'bootstrap.php';

/**
 * ここから追加
 */
// app/vendor以下をautoloadする
require APPPATH.'vendor'.DIRECTORY_SEPARATOR.'autoload.php';

// EntityとRepositoryが属する\EntityネームスペースをFuelPHPのAutoloaderに追加
Autoloader::add_namespace('Entity', APPPATH.'classes'.DIRECTORY_SEPARATOR.'entity'.DIRECTORY_SEPARATOR);
/**
 * ここまで
 */

Autoloader::add_classes(array(
));

// Register the autoloader
Autoloader::register();

/**
 * Your environment.  Can be set to any of the following:
 *
 * Fuel::DEVELOPMENT
 * Fuel::TEST
 * Fuel::STAGING
 * Fuel::PRODUCTION
 */
Fuel::$env = (isset($_SERVER['FUEL_ENV']) ? $_SERVER['FUEL_ENV'] : Fuel::DEVELOPMENT);

// Initialize the framework with the config file.
Fuel::init('config.php');

db

databaseの設定もやらないと使えない。

app/config/db.php
<?php

return array(
    'doctrine2' => array(
        'proxy_dir' => APPPATH.'classes'.DIRECTORY_SEPARATOR.'proxy',
        'proxy_namespace' => 'Proxy',
        'metadata_path' => APPPATH.'classes'.DIRECTORY_SEPARATOR.'entity',
    ),
    'default' => array(
        'type' => 'pdo',
        'connection' => array(
            'dsn' => 'oci:dbname=yourdb',       // これはoracle用の設定
            'username' => 'yourdbusername',
            'password' => 'yourdbpasswd',
            'persistent' => false,
        ),
        'identifier' => '',
        'table_prefix' => '',
        'charset' => 'utf8',
        'caching' => true,
        'profiling' => false,
    ),
);

view

EntityクラスがFuelPHPのセキュリティ機能に引っかかってしまうため、viewで扱うための設定をする。
都度追加するのはめんどくさいので基底クラスを作りそれを継承、継承しているものだけ許可をするようにする。

app/config/config.php
<?php

return array(
    // ...
    'security' => array(
        'whitelisted_classes' => array(
            'Fuel\\Core\\Response',
            'Fuel\\Core\\View',
            'Fuel\\Core\\ViewModel',
            'Closure',
            'Entity\\Base',             // これを追加する
        ),
    ),
    // ...
);

エンティティを作る

定義をyamlなどで作ってコマンドで作れる。
...が、色々工夫しないと作れず、今回はお試しなので一旦手作業で作ることにする。

今回は簡単にキャンペーンのエンティティを作るだけにする。

app/classes/entity/base.php
<?php

namespace Entity;

/**
 * Viewのセキュリティ機能を通過させる為に作る基底クラス
 */
class Base
{
}
app/classes/entity/campaign.php
<?php

namespace Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @Entity(repositoryClass="Entity\CampaignRepository")
 * @Table(name="campaigns")
 */
class Campaign extends Base
{
    /**
     * @Id
     * @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @Column(type="string", length=512)
     */
    protected $title;

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

        return $this;
    }

    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

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

    public function getTitle()
    {
        return $this->title;
    }
}

リポジトリも作る。
メソッドはキャンペーン一覧を取得するだけ。

app/classes/entity/campaignrepository.php
<?php

namespace Entity;

use Doctrine\ORM\EntityRepository;

class CampaignRepository extends EntityRepository
{
    public function getCampaignList()
    {
        $qb = $this->createQueryBuilder('c');
        return $qb->getQuery()->getResult();
    }
}

Controllerから使ってみる

先ほど作ってリポジトリからキャンペーン一覧を取得するだけの簡単なものを作成。

app/classes/controller/campaign.php
<?php

use \Fuel\Core\Controller;

class Controller_Campaign extends Controller
{
    public function action_list()
    {
        $em = \Fuel\Doctrine::manager();        
        $campaigns = $em->getRepository('Entity\Campaign')->getCampaignList();

        $this->theme
            ->set_template('campaign/list.html.twig')
            ->set(array(
                'campaigns' => $campaigns,
            ));

        return \Response::forge($this->theme);
    }
}

Viewから使う

Controllerにて取得したものをViewから使い表示する。

app/views/pc/campaign/list.html.twig
{% extends 'pc/layout.html.twig' %}

{% block contents %}
<h1>キャンペーン一覧</h1>

{% if campaigns is empty %}
<p>キャンペーンはありません</p>
{% else %}
<ul>
    {% for campaign in campaigns %}
        <li>{{ campaign.id }} : {{ campaign.title }}</li>
    {% endfor %}
</ul>
{% endif %}
{% endblock contents %}

終わり

基本のfetchできるかだけ試した。
insert,update,deleteも試したいし、paginationとかも試したい所だけど時間がなく断念。

以上。