そろそろCSVHubについて一言いっておくか。もしくは、README.mdサボってごめんなさい!Yacsv pluginの使い方

えーと、1年以上前にYacsvというCSVのインポート処理を簡単にするためのCakePHP pluginを作りました。

k1LoW/Yacsv

さらに、PHP Matsuri 2012でYacsvをコアにおいたCSVHubというWebサービスを作りました。

CSVHub: CSV < convert > Hub

が、README.mdを書くのをサボってました。ゴメンナサイ。。。

Yacsvって何?

数あるCSVインポート系のPluginの一つです。「Yet another CSV」の略です。

ちなみに自分はこの「Yet another」という言葉が大好きで、Yacsv以外にも

  • yak [Yet Another Ktai plugin]
  • Yasd [Yer Another SoftDeletable Behavior]
  • Yav [Yet Another Validation Set]
  • Yamd [Yet Another Markdown plugin]

など、命名に困ったらかたっぱしから「Ya」をつけます。紛らわしいことこの上ない。

Yacsvの特徴は、特にこれといったものはないのですが、強いて言うなら

  • CSVのパーサが強力(自分が作ったものではない)
  • 使用するとき記述量が少ない
  • テストがある
  • README.mdにドキュメントが書かれていない

といったところでしょうか。

CSVのパーサが強力

これはYacsvの公開の条件でもあったのですが、YacsvのCSVのパーサは@yossy222さんの作成されたfgetcsv_reg()を元に作成されています。

どれだけ強力かについては定量的なデータはないのですが、 基本的に今まで、Yacsvを使ってパース周りで問題が起きたことはありません。

ちゃんとパースできるかについて試したいのであれば、是非CSVHubにアップロードしてみてください。設定すればちゃんとパースされますよ。

使用するとき記述量が少ない

Yacsvは基本的にBehaviorとして動くのですが、CakePHPに特化しているので記述量が少ないです。

いや、汎用的に作っていますので、常に少ないわけではありません。多分多くなるときもあります。

例えば

既にModel::save()に近いインターフェースでデータ登録メソッドをモデルに作ってシステムを作っていたら、いきなり『CSVインポート機能も作って』と言われた

こういうときに圧倒的に記述量が少ないです。

え?ニッチ過ぎるって?

では言い換えます。

まずModel::save()に近いインターフェースでデータ登録メソッドを作り、それからCSVインポート機能を作るとわかりやすいし、記述量も少ない

どうでしょう?

作り方は大体わかるけど毎回面倒なCSVアップロード機能が簡単につくれそうじゃないですか?

テストがある

suzukiさんに協力してもらい、しっかりテストがあります(機能追加もありました)。また、はやりのTravis CIでCIされています。

README.mdにドキュメントが書かれていない

大変申し訳ありません。

Yacsvの使い方

いろんな使い方ができるのですが、今回は本当にスタンダードな使い方をサンプルアプリケーションの「コミットログ」を見ながら確認していきましょう。

1. CakePHPの初期セットアップ

まずは何は無くともCakePHP

commit/6980e8fe0e6deeb2924c94980bcaca39231d96d7

CakePHPを設置しSqlite3のデータベースにpostsテーブルだけつくりました。あとはbakeをしたくらい。

postsテーブルのスキーマこちら

2. Postモデルにバリデーションを記述

commit/11088e37fb65959ea05d8bd6b1ebec79a7f07e27

まずはバリデーションを記述します。

ここでposts/addで登録しようとしたら、Post::save()のタイミングでちゃんとバリデーションチェックが走ります。よね?

3. CSVインポート機能を作成開始

ここで、postsテーブルへのCSVインポート機能を実装してみましょう。

まずはYacsvをapp/Pluginに設置

commit/a3eeefcdaf85e1d16b886c8f7a81b7dbd1d1d7fa

Yacsvをbootstrap.phpでloadしてPost::actsAsに記述します

commit/be2757669726eb0ae937be2cf7054ed838275602

当然インポート画面が必要ですので、posts/importページの雛形を作成しましょう。CSVファイルアップロードに使うフィールド名は、とりあえずcsvfileにします。

Viewはファイルアップロードである点に注意してadd.ctpを元に作成。Controllerのアクションはまずはposts/addをコピペしました

commit/8d682a9e0c2dd94a6cdbb417b92ed8f4e84c6044

4. Yacsvの設定 (Post::save()を利用してCSVインポート機能を実装する)

さて、ここからがYacsv独特の設定です。Yacsvの設定はCakeDC製のSearch pluginの設定方法に近い形で実装しています。ちょっと近いだけですが。

今回インポートするCSVはこんな感じです。

commit/34f304ced212b7c577c1850f40ed4f50ae827666

ExcelからCSV出力されたものなので、Shift-JISになっていますが、実際にはこんな感じです

タイトル,内容
PHPMatsuri2012でCSVHubをつくりました,"PHPMatsuri2012でCSVHubをつくりました。
とても楽しかったです。"
PHPMatsuri2013でdevil's pieをつくりました,"PHPMatsuri2013でdevil's pieをつくりました。
とても楽しかったです。"

ヘッダがあったり、改行があったりするやつですね。

まず、Postモデルの設定をしましょう。詳しくはPost.phpに追記したコメントをみてください。

commit/f344eb2f769122d126f678a6cd042fb493b22d25

次に、PostsController::importアクションの設定をしましょう。いろいろな設定が結構autoで設定できる場合があるのがYacsvのいいところですね。

commit/16313f2475a2191227ec192df8835ba575de4a7b

YacsvはExceptionを吐くので、少々強引ですがtry/catchで囲みます。

(また、YacsvのExceptionはあまり親切ではないことが知られていますので、ここは頑張ってください。。。。)

で、終了です。簡単な実装はこれだけです

5. Yacsvのアドバンスドな使い方その1 各行のバリデーションエラーを表示する

4までのCSVインポート、ちゃんとPost::validateを使っています。では各行のバリデーションエラーを表示してみましょう(デザインは適当です)。

commit/f85ee0c13ca33c5d59d6e0cb5f19ef69e3b74636

6. Yacsvのアドバンスドな使い方その2 独自の登録メソッドを使ってCSVインポート機能を実装する

4までのCSVインポートでは、Post::save()を使っていましたが、ちょっと特殊な登録方法だったりすることありますよね?

commit/12d65a585c87a2218607428010b6bafbe65ba915

(今回のサンプルはbeforeSaveでもできますが、まあそこは目をつぶってください^^)

こういうときはPost::importCSV()のオプションをこんな感じで修正するだけでOKです。

commit/a4b06ed95ae6a3ee768622915e553597a72aa9e4

細かすぎて伝わりにくいかもしれませんが、このsaveMethod、実際にかなり使えます。実際の案件でModel::save()で済むようなことはほとんどないですからね。

というわけで

いかがだったでしょうか?

ちなみに今回のサンプルアプリケーションは、app/tmpのパーミッションをいつものように修正するだけで動きますので、設置して触ってみてもらえればと思います。

k1LoW/Sample-Yacsv-Application

このエントリーもってREADME.mdの代わりにしていただければ。。。