Phalconで既存のプロジェクトにモジュールを追加する1

2014年 6月24日 PHP Phalcon

PhalconでCakePHPやSymfonyにおけるPluginやRailsにおけるGemのように、パッケージ化されたMVCを抜き差しできる仕組みがないか調べてみたのですが、どうもなさそうなかんじです。
Pluginクラスがあるのですが、これはDispatherに絡めてフック処理を入れたりするもののようです。

そこで、モジュールを使って実現できないか試してみます。
以前作成した簡易ブログにコメント機能を付けていきます。



テーブル構成

postに対するコメントだけでなく、汎用性を持たせるため、モデル名とモデルIDをキーにします。

sql
CREATE TABLE comments
(
    id int(11) NOT NULL AUTO_INCREMENT,
    model varchar(255),
    model_id int(11) NOT NULL,
    body text,
    PRIMARY KEY (id)
);

Scaffolding

とりあえずコメント機能をScaffoldingします。
Viewはphtmlではなくvoltにします。
PHPは元々テンプレートエンジンでViewをそのまま記述できるのに、高いコストを払ってSmartyなどのテンプレートエンジンを使うことに否定的でしたが、voltのエンジンはCで実装されているので後ろめたさなく使えます。

$  phalcon scaffold --table-name=comments --template-engine=volt
 
Phalcon DevTools (1.3.2 ALPHA 1)
 
Success: Model "comments" was successfully created. 
 
/opt/local/apache2/htdocs/phalcon-sample/app/config/../../app/controllers/CommentsController.php
/opt/local/apache2/htdocs/phalcon-sample/app/config/../../app/views/comments/index.phtml
/opt/local/apache2/htdocs/phalcon-sample/app/config/../../app/views/comments/search.phtml
/opt/local/apache2/htdocs/phalcon-sample/app/config/../../app/views/comments/new.phtml
/opt/local/apache2/htdocs/phalcon-sample/app/config/../../app/views/comments/edit.phtml

モジュール化

Scaffoldingで作ったコメント機能をモジュール化します。
appの下にmodules/commentsディレクトリを作り、その下に先ほどScaffoldingで生成したファイルを配置します。
さらにcommentsの下にModule.phpを作成します。

modules
└── comments
    ├── Module.php
    ├── controllers
    │   └── CommentsController.php
    ├── models
    │   └── Comments.php
    └── views
        └── comments
            ├── edit.volt
            ├── index.volt
            ├── new.volt
            └── search.volt

Module.phpは次のようにします。
Databaseの設定は既存プロジェクトのものを使います。

php
namespace Sample\Comments;
 
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\ModuleDefinitionInterface;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
 
class Module implements ModuleDefinitionInterface
{
    /**
     * Registers the module auto-loader
     */
    public function registerAutoloaders()
    {
        $loader = new Loader();
        $loader->registerNamespaces(array(
            'Sample\Comments\Controllers' => __DIR__ . '/controllers/',
            'Sample\Comments\Models' => __DIR__ . '/models/'
        ));
        $loader->register();
    }
 
    /**
     * Registers the module-only services
     *
     * @param Phalcon\DI $di
     */
    public function registerServices($di)
    {
        /**
         * Read configuration
         */
        $config = include __DIR__ . "/../../config/config.php";
 
        /**
         * Setting up the view component
         */
        $di->set('view', function() {
        $view = new View();
        $view->setViewsDir(__DIR__ . '/views/');
        $view->registerEngines(array(
            '.volt' => function ($view, $di) {
 
                $volt = new VoltEngine($view, $di);
 
                $volt->setOptions(array(
                    'compiledPath' => __DIR__ . '/../../cache/',
                    'compiledSeparator' => '_'
                ));
 
                return $volt;
            },
            '.phtml' => 'Phalcon\Mvc\View\Engine\Php'
        ));
 
        return $view;
    });
 
    $di->set('db', function () use ($config) {
        return new DbAdapter(array(
            'host' => $config->database->host,
            'username' => $config->database->username,
            'password' => $config->database->password,
            'dbname' => $config->database->dbname
        ));
    });
}

モジュールの読み込み

app/configの下にmodules.phpを作ります。

php
// app/config/modules.php
 
$application->registerModules(array(
    'comments' => array(
        'className' => 'Sample\Comments\Module',
        'path' => __DIR__ . '/../modules/comments/Module.php'
    )
));

public/index.phpで作ったmodules.phpを読み込みます。

php
/**
 * Include modules
 */
require __DIR__ . '/../app/config/modules.php';

モジュールのルーティング

app/configの下にroutes.phpを作ります。
デフォルトの名前空間は既存のSample\Controllersに設定します。

そしてcommentsモジュール用のルーティングを行います。
これがめんどくさい‥

php
// app/config/routes.php
$router = new Phalcon\Mvc\Router();
 
$router->setDefaultNamespace("Sample\Controllers");
 
$router->add( '/comments', array(
    'namespace' => 'Sample\Comments\Controllers' ,
    'module' => 'comments',
    'controller' => 'comments' ,
    'action' => 'index'
));
 
$router->add( '/comments/', array(
    'namespace' => 'Sample\Comments\Controllers' ,
    'module' => 'comments',
    'controller' => 'index' ,
    'action' => 'index'
));
 
$router->add( '/comments/:controller', array (
    'namespace' => 'Sample\Comments\Controllers' ,
    'module' => 'comments',
    'controller' => 1,
    'action' => 'index',
));
 
$router->add( '/comments/:controller/', array (
    'namespace' => 'Sample\Comments\Controllers' ,
    'module' => 'comments',
    'controller' => 1,
    'action' => 'index',
));
 
$router->add( '/comments/:controller/:action', array (
    'namespace' => 'Sample\Comments\Controllers' ,
    'module' => 'comments',
    'controller' => 1,
    'action' => 2,
));
 
$router->add( '/comments/:controller/:action/', array (
    'namespace' => 'Sample\Comments\Controllers' ,
    'module' => 'comments',
    'controller' => 1,
    'action' => 2,
));
 
$router->add('/comments/:controller/:action/:params',array(
    'namespace' => 'Sample\Comments\Controllers',
    'module' => 'comments',
    'controller' => 1,
    'action' => 2,
    'params' => 3,
));
 
return $router;
//app/service.php
$di->set('router', function () {
        return require __DIR__ . '/routes.php' ;
});

ディレクトリ(名前空間)の登録

LoaderのregisterNamespacesで名前空間とディレクトリのマップを登録します。

php
// app/config/loader.php
 
$loader->registerNamespaces(array(
    'Sample\Models' => $config->application->modelsDir,
    'Sample\Controllers' => $config->application->controllersDir,
    'Sample\Comments\Models' => __DIR__ . '/../../app/modules/comments/models/',
    'Sample\Comments\Controllers' => __DIR__ . '/../../app/modules/comments/controllers/'
));

ここまででhttp://localhost/phalcon-sample/commentsとかでコメントモジュールにアクセスできるようになりました。
長くなってきたので記事にコメントできるようにする方法はその2に書きます。



前へ 次へ