質問: 楽天市場やYahoo!ショッピングではCSVファイルを使った商品の登録ができます。 この商品登録用のCSVファイルを読み書き(ドメインのデータへのコンバート)するシステムをPHPを使って作成しているのですが、CSVファイルをオブジェクトとして取り扱うにはどのようにすればいいのか悩んでいます。 これらネットショップの商品CSVファイルは項目数も多く、設定できる値が制限されていたり値の書式が決まっているなど取り扱いが大変です。 また、ショッピングモール側の仕様変更が度々あり、項目が増えたり廃止されたり入力ルールが変更されるなどメンテナンスが必須です。 現状はCSVファイルを配列で管理しているのですがメンテナンスしやすくするためにクラスとして定義してみようと考えてみました。 ・CSV全体のクラス ・CSVファイル1行分のクラス ・CSVファイルの各項目のクラス 項目1つ1つをクラスとして定義して、各項目の入力ルールを定義しようというアイデアですがこれだと100項目あれば100個のクラスになってしまいます。 こういうクラス設計をやったことがないので加減が分からないのですが、100個でも200個でもあるだけ作っていくものなのでしょうか? それともある程度意味のあるまとまりでまとめておく方がいいでしょうか? 皆様のご意見を教えていただければ幸いです。
回答: がると申します。 全体の仕様やビジネスが見え切れていないので言及しにくい部分も色々とあるのですが。 「CSV全体のクラス」については、SplFileObjectが、PHP的には標準でもあり、使いやすいのではないか、と思います。 書式としては ``` $f_obj = new \SplFileObject(ファイル名); $f_obj->setFlags(\SplFileObject::READ_CSV); foreach ($f_obj as $key => $row) { // $keyに行番号、$rowに1行分のデータ } ``` といった感じです。 あとはこのCSVをどのように使うか、によっても色々と変わるかなぁ、と思うのですが。 自分であれば、見ている範囲であれば ・「項目が増えたり廃止されたり」は、configあたりで「nカラム目はこのデータ」とかいった対応表を作る(例えば「0カラム目はitem_id」「1カラム目はitem_name」とか) ・上述の「$row」のデータを「1行分のデータを扱うクラス」に食わせて、1インスタンスを取得する ``` $item_obj = new item($row); ``` ・validateなどは「1行分のデータを扱うクラス」の中で実装する →簡単な「必須」とか「文字であること/数値であること」「文字長のmix-min」などは簡単にかけるようにしておくと楽 →もうちょっと入り組んだもの(書式チェックとか)は「1項目ごと」に書いちゃうほうが楽 自分なら、validate関連は、itemクラスの中で ``` public function validate() { // 呼び出したい「個々のvalidate」のメソッド名の配列 $validate_methods['validate_hoge', 'validate_foo', 'validate_bar']; // 個々に呼び出し $err = []; foreach($validate_methods as $vm) { $err = $this->$vm($err); } // if ([] !== $err) { // なにかエラーがあったぽい。エラーの詳細は$errの配列の中になんか情報がある事を想定 return false; } // 問題がなかったぽい return true; } /** */ protected function validate_hoge($err) { // 項目hogeに関するvalidate } // 以下略 ``` なんていう書き方をイメージしますかね。ざっくりとは。 あとはまぁ「修正が楽にできる」ように、なので、色々な考え方があると思うので。 色々と試してみて「楽だなぁ、と思った」方法で進めてみると、よいように思われます。 上述、ざっくりとしか書いていないので。 「興味があるからもうちょっと詳しく!!」とかありましたら、コメントなどいただければ、時間があるときに、ですが、返信などできるかと思います。