あらまし
配属先で[Slim]を使っているので、使い方などをメモしている。
前回
Whoops補足
前回、Whoopsの導入で、dopesong/Slim-Whoopsを導入してデバッグバー(kitchenu/Slim-Debugbar)を導入する際に
12 // ob_start以降のエラーをハンドルする
13 $container['phpErrorHandler']/* = $container['errorHandler']*/ = function($c) {
14 return new Dopesong\Slim\Error\Whoops($c->get('settings')['displayErrorDetails']);
15 };
のようにerrorHandlerをコメントアウトしていたのは、デバッグバーの受け取るエラーが合わない為でした
なので、vendor以下を修正する事になってしまいますが、
...
24 class Whoops extends \Slim\Handlers\Error // デバッグバー側で受け取るエラーを継承させる
25 {
...
118 protected function determineContentType(ServerRequestInterface $request)
119 {// Slim\Handlers\Error::determineContentTypeのアクセス修飾子に合わせる
...
のようにするとコメントを外しても動作します
Phpmig導入
マイグレーションツールとして、Phpmigを導入してみます
マイグレーションツールとしては、Phinxも有名ですが、少しいじってみた感じとして、データベースにマイグレーションの情報が書き込まれるのがどうだろうな、と思ったりした為です
ちなみに、Phpmigですと、マイグレーション情報として初期化したディレクトリ内に、.migrations.logというファイルが作られて、その中に情報が書き込まれます
インストール
$ composer require davedevelopment/phpmig
マイグレーション用ディレクトリ作成
$ mkdir data
デフォルトだとプロジェクトルートにmigrationsというフォルダを作成してその中に色々作られますが、フィクスチャなど関連したデータをまとめたかったので、data/というディレクトリを作成しました
コマンドライン用に登録
...
"scripts": {
...
"phpmig": "cd data && phpmig"
...
}
...
初期化
$ composer phpmig init
data/phpmig.phpが出来るので、それを色々修正して、自分のシステムに合わせるようにします
<?php
use \Phpmig\Adapter;
// get environment variables from phpdotenv
$dotenv = new Dotenv\Dotenv(__DIR__. '/../');
$dotenv->load();
// disable web debug tools
putenv('DEBUG=0');
$settings = require __DIR__ . '/../src/settings.php';
// we shold not need Slim\App, but want container...
$app = new Slim\App($settings);
require __DIR__ . '/../src/dependencies.php';
$container = $app->getContainer();
// replace this with a better Phpmig\Adapter\AdapterInterface
$container['phpmig.adapter'] = new Adapter\File\Flat(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/.migrations.log');
...
こんな感じに書き換えて、slim側の設定を読み込むようにします
マイグレーションファイル作成
$ composer phpmig generate AddTableTest
> cd data && phpmig 'generate' 'AddTableTest'
+f ./migrations/20161112055904_AddTableTest.php
まだデータベースとの接続などを導入していないのでここまでです
Idiorm & Paris導入
データベースアクセスに何を使おうか?とここしばらく考えていましたが、軽量と聞いていたIdiorm & Parisを導入してみます
IdiormがORM、ParisがActiveRecordのようです
$ composer require j4mie/idiorm j4mie/paris
データベース設定
# database settings
DB_PHPMIG1_DSN = mysql:host=localhost;dbname=phpmig1
DB_PHPMIG1_USER = root
DB_PHPMIG1_PASS =
DB_PHPMIG2_DSN = mysql:host=localhost;dbname=phpmig2
DB_PHPMIG2_USER = root
DB_PHPMIG2_PASS =
<?php
return [
'settings' => [
...
// database settings
'db' => [
'phpmig1' => [
'dsn' => getenv('DB_PHPMIG1_DSN'),
'user' => getenv('DB_PHPMIG1_USER'),
'pass' => getenv('DB_PHPMIG1_PASS'),
],
'phpmig2' => [
'dsn' => getenv('DB_PHPMIG2_DSN'),
'user' => getenv('DB_PHPMIG2_USER'),
'pass' => getenv('DB_PHPMIG2_PASS'),
],
],
],
];
職業柄か、複数DBを使用する事が多いので、2台設定しています
...
$container = $app->getContainer();
if ($container->get('settings')['debug']) {
...
// debugbar setting
$settings = $container->get('settings')['debugbar'];
$provider = new Kitchenu\Debugbar\ServiceProvider($settings);
$provider->register($app);
// デバッグバーに、データベース項目を追加する
ORM::configure('logging', true);
$collector = new DebugBar\DataCollector\PDO\PDOCollector();
$container['debugbar']->addCollector($collector);
}
...
// databases
foreach ($container->get('settings')['db'] as $dbname => $settings) {
// idiorm settings
ORM::configure([
'connection_string' => $settings['dsn'],
'username' => $settings['user'],
'pass' => $settings['pass'],
], null, $dbname);
// デバッグ時には、デバッグバーに、コネクションを登録する
if ($container->get('settings')['debug']) {
$pdo = ORM::get_db($dbname);
$debugbar = $container['debugbar'];
$collector = $debugbar->getCollector('pdo');
$source = new DebugBar\DataCollector\PDO\TraceablePDO($pdo);
$collector->addConnection($source, $dbname);
}
// コンテナからもコネクションを取得出来るように設定
$container["db.$dbname"] = function($c) use ($dbname) {
return ORM::get_db($dbname);
};
}
$container["db.$dbname"]としている為に、$container->db.$dbnameという取得の仕方が出来ません
あまりコンテナから取得する事は無いだろう、という事と、表記的に、db以下にコネクションをまとめたい、という事からこんな事をしていますが、取得したい場合は
$container->get("db.$dbname")という感じで取得出来ます
マイグレーションファイル設定
上の、マイグレーションファイル作成で生成されたファイルを編集します
<?php
use Phpmig\Migration\Migration;
class AddTestTable extends Migration
{
/**
* Do the migration
*/
public function up()
{
$this->get('db.phpmig1')->exec("
CREATE TABLE `test1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`value` int(11) NOT NULL,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)
");
$this->get('db.phpmig2')->exec("
CREATE TABLE `test2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`value` int(11) NOT NULL,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)
");
}
/**
* Undo the migration
*/
public function down()
{
$this->get('db.phpmig1')->exec("DROP TABLE `test1`");
$this->get('db.phpmig2')->exec("DROP TABLE `test2`");
}
}
マイグレーション適用
$ composer phpmig migrate
> cd data && phpmig 'migrate'
== 20161112055904 AddTableTest migrating
== 20161112055904 AddTableTest migrated 0.0169s
これで、テーブルが作成されます
20161112055904
適用されたマイグレーションの番号が書き込まれて行きます
ロールバック
$ composer phpmig rollback
> cd data && phpmig 'rollback'
== 20161112055904 AddTableFoo reverting
== 20161112055904 AddTableFoo reverted 0.0222s
これで、直近のマイグレーションが取り消されて、テーブルが削除されます
感想
Whoopsの件は、修正をプルリクしておくべきなのかもしれませんが、そもそも今回使用してみたデバッグバー側でエラーを補足しなければ問題無かったはず(エラーしたらWhoopsが捕捉して表示するのでデバッグバー側で処理する必要が無い)なので、どのように修正するのか難しいところです