なんとタイムリーな…需要ありまくりですw
こんな新米ブログに言及していただけるとわ…
http://www.1x1.jp/blog/2009/05/cakephp_app_import_swap_framework.html
マイConnectionManagerの置き場所は迷ったのですが、せっかくなので(?)外部プラグインのtools/modelsに入れておくことにしました。
bootstrap.php
<?php $pluginPaths = array(CAKE_CORE_INCLUDE_PATH . DS . 'plugins' . DS); App::import('Core', 'ConnectionManager', array('file' => $pluginPaths[0] . 'tools' . DS . 'models' . DS . 'connection_manager.php')); ?>
bootstrap.phpで定義した*2pluginPaths等はConfigureインスタンスが持っている模様。
以下のようにして取得できる。
<?php $conf = Configure::getInstance(); $pluginPaths = $conf->pluginPaths; ?>
database.php
<?php var $hoge = array('datasource' => 'Tools.Hoge'); ?>
この場合のパスはplugins/tools/models/datasources/hoge_source.php
とはいえあまり多くの修正はしたくない。
今回は幸いloadDataSourceと__getDriverの修正だけで済みました。
connection_manager.php
<?php function loadDataSource($connName) { $_this =& ConnectionManager::getInstance(); if (is_array($connName)) { $conn = $connName; } else { $connections = $_this->enumConnectionObjects(); $conn = $connections[$connName]; } if (!empty($conn['parent'])) { $_this->loadDataSource($conn['parent']); } if (class_exists($conn['classname'])) { return false; } // プラグイン名が指定されてたらpluginPathsを検索する if (!empty($conn['plugin'])) { if (!$this->__loadDataSourceInPluginPaths($conn['plugin'], $conn['filename'])) { $error = __('Unable to load DataSource file %s.php in %s plugin.', true); trigger_error(sprintf($error, $conn['filename'], $conn['plugin']), E_USER_ERROR); return null; } } elseif (file_exists(MODELS . 'datasources' . DS . $conn['filename'] . '.php')) { require (MODELS . 'datasources' . DS . $conn['filename'] . '.php'); } elseif (fileExistsInPath(LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php')) { require (LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php'); } else { $error = __('Unable to load DataSource file %s.php', true); trigger_error(sprintf($error, $conn['filename']), E_USER_ERROR); return null; } } // pluginPathsを検索、あればデータソースをrequireする function __loadDataSourceInPluginPaths($plugin, $filename) { $conf = Configure::getInstance(); foreach ($conf->pluginPaths as $path) { $folder = new Folder($path); list($plugins, $files) = $folder->read(); if (in_array($plugin, $plugins)) { if (file_exists($path . $plugin . DS . 'models' . DS . 'datasources' . DS . $filename . '.php')) { require ($path . $plugin . DS . 'models' . DS . 'datasources' . DS . $filename . '.php'); return true; } } } return false; } function __getDriver($config) { $plugin = null; if (!isset($config['datasource'])) { $config['datasource'] = 'dbo'; } else if (strstr($config['datasource'], '.')){ // .区切りでプラグイン名を抽出 list($plugin, $config['datasource']) = explode('.', $config['datasource']); $plugin = low($plugin); // プラグイン名が大文字で指定されているかもしれないので小文字に } $config['datasource'] = low($config['datasource']); // 同じくデータソース名も小文字に if (isset($config['driver']) && $config['driver'] != null && !empty($config['driver'])) { $filename = $config['datasource'] . DS . $config['datasource'] . '_' . $config['driver']; $classname = Inflector::camelize(strtolower($config['datasource'] . '_' . $config['driver'])); $parent = $this->__getDriver(array('datasource' => $config['datasource'])); } else { $filename = $config['datasource'] . '_source'; $classname = Inflector::camelize(strtolower($config['datasource'] . '_source')); $parent = null; } // プラグイン名を付加して返す return array('filename' => $filename, 'classname' => $classname, 'parent' => $parent, 'plugin' => $plugin); } ?>
これでデータソースも外部プラグインに追いやれました。
もはやappには何も無い…
これが無の境地か
コンフィグ系などアプリごとにファイルを持たなければいけなかったり、
設定する必要があるものに関してはシェルを作ってそこからインストールするようにすれば楽ちん。
アップデート時の更新し忘れも防げる。
しかもシェルのcreateFileメソッドはちゃんと上書き確認もしてくれる(はず)。*3
AppModelの上書きメソッドをどうするか*4。