CakePHP1.3.6:Media Plugin1.3RCに挫折して、ファイルアップロードを自作(その1)

ファイルアップロードをやってみようと思い、名高いMedia Pluginを試して、半日がかりでやってみたが、結局挫折。

サイトを見て、おやおやと思ったのが、0.x系から飛んで、1.3RCが出てること。こういうのは経験的に危ない。YUIStrutsなんかもそうですね。アーキテクチャが変わっちゃって、ググって開発できない可能性が高い。
半日がかりでいじってみたが、mediumヘルパーがmediaヘルパーに変わっていて表示系がうまくいかない。実力的にソースを直すところまでいけないので、挫折した。
PeclのImageMagicを入れるのも、レンタルサーバーで動かすときの障害になりそうだし。

でも、悪いことばかりじゃなく、Media Pluginを触って目からうろこが落ちた。Media PluginにはAttachmentというスキームが同梱されているが、その名の通り、「なんらかのコンテキスト(ドキュメント)の添付としてMadiaを添付する」という考え方になっている。
裏を返せば、「mediaにはなんらかのコンテキストが付随している」ということ。タイトルとかメモとか。

そういうことで、同じ考え方でjpg/png/gifをアップロードして、リサイズするコードを自作した。簡単なコードなのでGDだけでうごく。だが、DRYじゃない。

テーブル

上のことを実現する場合、

  • テーブルに属性(テキスト)とmedia(バイナリ)を持たせてしまう。
  • テーブルに属性(テキスト)とmediaのメタ情報(在り処、サイズなど)を持たせて、mediaはファイルシステムに持たせる。

がある。GAE/Jを評価した際には(GAEの制約もあって)上の方法をとった。これだととてもシンプルになるが、下の方法が一般的なのかなとも思う。
これらの方法は、属性に対してmediaが1つの場合を想定していて、実際はこれでいいのだと思うが、Media Pluginでは複数のAttachmentが持てるようになっている。

  • 属性用とmedia用の2つのテーブルを用意して、media用のテーブルにはメタ情報を持たせる。mediaはファイルシステムに格納する。

今回は、この方法をとることにした。属性用のテーブルと、メタ情報はhasManyの関係になるので、その実験にもなるし。

属性用テーブル

mediaの属性を持たせるテーブルのDDLは以下。

CREATE TABLE IF NOT EXISTS `docs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` text COLLATE utf8_unicode_ci NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

mediaのメタ情報を持たせるテーブルのDDLは以下。

CREATE TABLE IF NOT EXISTS `doc_images` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `doc_id` int(11) NOT NULL,
  `path` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

モデル

/app/modelsにdoc.php, doc_image.phpを作成する。

doc.php

後述のdoc_image.phpとは、hasManyの関係として、docからカスケーディング・デリートがかかるようにする(dependent=>true)。

<?php 

class Doc extends AppModel {
	public $name = 'Doc';

	public $hasMany = array(
		"DocImage" => array(
			'className' => 'DocImage',
			'dependent' => true
		)
	);
	
	public $validate = array(
				'title'=>array(
						'rule' => 'notEmpty',
						'message' =>'入力してください'
						)
			);
}
?>

doc_image.php

<?php
class DocImage extends AppModel {
	var $name = 'DocImage';
}
?>

続きはこちら