CakePHPでRDB以外のデータソースを使う時のBakeのエラーと回避
CSVをデータソースとして扱えるようにする CsvSource というプラグインがあります。
コントローラーの $uses にCSVを使うモデルを設定したら、Bake で View を焼く際にエラーが出るようになってしまいました。
CsvSource とは
http://github.com/cakephp/datasources
CakePHP の github に datasources というリポジトリがあります。
CsvSource をはじめ、いくつかのデータソースが扱えるプラグインになってます。
エラーの状況
<?php class Csv extends AppModel{ public $useDbConfig = 'csv'; }
CsvSource を使うと、RDBではなくCSVをデータソースとして扱えるモデルが作れます。
<?php class ExamplesController extends AppController { public $name = 'Examples'; public $uses = array('Example', 'Csv'); public function index(){ $this->Csv->find(); }
public $uses = array('Example', 'Csv'); とする事で、このコントローラーでCsvモデルが使えるようになります。
--------------------------------------------------------------- Interactive Bake Shell --------------------------------------------------------------- [D]atabase Configuration [M]odel [V]iew [C]ontroller [P]roject [F]ixture [T]est case [Q]uit What would you like to Bake? (D/M/V/C/P/F/T/Q) > v --------------------------------------------------------------- Bake View Path: /Users/myuser/Dev/cakephp1.3.0/../cakephp_baked/views/ --------------------------------------------------------------- Possible Controllers based on your current database: 1. Examples Enter a number from the list above, type in the name of another controller, or 'q' to exit [q] > 1 Would you like bake to build your views interactively? Warning: Choosing no will overwrite Hospitals views if it exist. (y/n) [n] > Error: Missing database table 'csvs' for model 'Csv'
こんな感じで、Bake で View を焼く時にエラーが出るようになってしまいました。
Controller や Model は Bake の必要がなかったのでやってませんが、同様のエラーが起こるかもしれません。
解決策
<?php class ExamplesController extends AppController { public $name = 'Examples'; public function index(){ $this->loadModel('Csv'); $this->Csv->find(); }
public $uses はデフォルトのままにしておいて、loadModel() メソッドで使う時にロードする形にします。
この書き方なら View を Bake で焼く時にも、エラーがなく処理できました。
補足
コントローラの中で、$usesでモデルをいくつも書いておけば、
$this->Model1->find();
$this->Model1->Model2->find();
みたいにして快適にモデルにアクセスできるのですが、この$usesの配列にモデル名を加えていくと、一つにつき、4-6%表示時間が多くかかるとのこと。試しに7モデルを$usesで読み込むようにしたら、40%も表示時間が増えたそうです (追記:たぶんこの比較は、あるアクションで使うモデルが1つだった場合に、$usesで7モデル定義した場合と、$usesには何も定義せず、該当アクション内で1つのモデルだけloadModelした場合で比較してるっぽい)
Modelを2個以上読み込む場合は、$usesを使わない方がスピードアップする - cakephperの日記(CakePHP, Laravel, PHP)
パフォーマンスの観点からも loadModel() で使う時だけに設定した方が良いみたいです。
<?php class DATABASE_CONFIG { var $default = array(...); var $csv = array( 'datasource' => 'datasources.csvSource', 'path' => '../tmp/csv', // local path on the server(windows) 'extension' => 'csv', // file extension of CSV Files 'readonly' => true, // only for reading 'recursive' => false, // only false is supported at the moment ); }
ちなみに、CsvSource を使うための app/config/database.php はこんな感じ。