PHP4でDB系のテストがやりたくてrake db:fixtures:load的にテーブル毎のファイルからDBへロード/ダンプするクラスを書いてみました。
<?php
require_once 'INILoader.php';
dump_ini('/path/to/fixtures', 'mysql://user:pass@localhost/dbname');
?>
(magpieみたいにグローバルにいい加減なファサード作っちゃうquick & dirtyさ加減)
こんな感じで書くと、
% cat fixtures/member.ini
[member1]
id = "1"
design_id = "1"
account = "komagata"
password = "aaa"
email = "komagata@p0t.jp"
createdtime = "2006-08-12 15:36:51"
[member2]
id = "2"
design_id = "2"
account = "tom"
password = "iii"
email = "tom@gmail.com"
createdtime = "2006-08-12 11:36:51"
[member3]
id = "3"
design_id = "3"
account = "bob"
password = "uuu"
email = "bob@gmail.com"
createdtime = "2006-08-12 12:36:51"
こんな感じの中身を指定したディレクトリに“テーブル名.ini”で吐く。yamlだとまんま過ぎなので何故かiniです。
<?php
require_once 'INILoader.php';
load_ini('/path/to/fixtures', 'mysql://user:pass@localhost/dbname');
?>
こう書くと逆にiniファイルを読んでテーブルにロードする。
以下コード。(さっとパッケージ化できる人になりたい)
<?php
require_once 'DB.php';
class INILoader
{
var $fixtures_dir;
var $dsn;
var $key_check;
var $db;
function INILoader($fixtures_dir, $dsn, $key_check = true)
{
$this->fixtures_dir = $fixtures_dir;
$this->dsn = $dsn;
$this->key_check = $key_check;
$this->db =& DB::connect($dsn);
$this->db->autoCommit(false);
$this->db->setFetchMode(DB_FETCHMODE_ASSOC);
}
function load($name = null)
{
if (is_null($name)) {
$this->db->query('BEGIN');
$this->_truncate_all();
$this->_load_all();
$this->db->commit();
} else {
$this->db->query('BEGIN');
$this->_truncate($name);
$this->_load($name);
$this->db->commit();
}
}
function dump($name = null)
{
if (is_null($name)) {
$this->_remove_all();
$this->_dump_all();
} else {
$this->_remove($name);
$this->_dump($name);
}
}
function _load_all()
{
if (!$this->key_check and preg_match("/^mysql/", $this->dsn)) {
$this->db->query('SET FOREIGN_KEY_CHECKS = 0');
}
foreach ($this->_get_ini_files() as $file) {
list($name, $ext) = split("\.", $file);
$this->_load($name);
}
if (!$this->key_check and preg_match("/^mysql/", $this->dsn)) {
$this->db->query('SET FOREIGN_KEY_CHECKS = 1');
}
}
function _truncate_all()
{
foreach ($this->_get_ini_files() as $file) {
list($name, $ext) = split("\.", $file);
$this->_truncate($name);
}
}
function _load($name)
{
echo "Load table {$name}... ";
$data = parse_ini_file("{$this->fixtures_dir}/{$name}.ini", true);
foreach ($data as $fields) {
if (DB::isError($res = $this->db->autoExecute($name, $fields))) {
$this->db->rollback();
echo "failed\n";
trigger_error('INILoader::_load(): Failed to load. '
.$res->toString(), E_USER_ERROR);
}
}
echo "succeed\n";
}
function _truncate($name)
{
echo "Truncate table {$name}... ";
$sql = "TRUNCATE $name";
if (DB::isError($res = $this->db->query($sql))) {
$this->db->rollback();
echo "failed\n";
trigger_error('INILoader::_truncate(): Failed to truncate. '
.$res->toString(), E_USER_ERROR);
}
echo "succeed\n";
}
function _dump_all()
{
foreach ($this->db->getTables() as $table) {
$this->_dump($table);
}
}
function _remove_all()
{
foreach ($this->db->getTables() as $table) {
$this->_remove($table);
}
}
function _dump($name)
{
echo "Dump table {$name}... ";
$file = "{$this->fixtures_dir}/{$name}.ini";
$handle = fopen($file, 'a');
$sql = "SELECT * FROM $name";
foreach ($this->db->getAll($sql) as $index => $fields) {
$line = "[{$name}".++$index."]\n";
foreach ($fields as $key => $value) {
$line .= "{$key} = \"{$value}\"\n";
}
if (!fwrite($handle, $line)) {
trigger_error("INILoader::dump(): Failed to write $file",
E_USER_ERROR);
}
}
fclose($handle);
echo "succeed\n";
}
function _remove($name)
{
echo "Remove file {$name}.ini ... ";
unlink("{$this->fixtures_dir}/{$name}.ini");
echo "succeed\n";
}
function _get_ini_files()
{
$files = array();
$d = dir($this->fixtures_dir);
while ($entry = $d->read()) {
if (preg_match("/\.ini$/", $entry)) {
$files[] = $entry;
}
}
$d->close();
return $files;
}
}
function load_ini($fixtures_dir, $dsn, $key_check = false)
{
$loader =& new INILoader($fixtures_dir, $dsn, $key_check);
$loader->load();
}
function dump_ini($fixtures_dir, $dsn)
{
$loader =& new INILoader($fixtures_dir, $dsn);
$loader->dump();
}
?>