[CakePHP] 画像のアップロード&リサイズを簡単にできる ImageBehavior

画像のアップロード&リサイズ処理などは割とよくある処理でかつ面倒なものです。その処理を簡単にやってくれる Imageビヘイビアの紹介です。CakeFest で紹介された Media Plugin が高性能なので、メディアプラグインを使うのがいいのかもしれませんが、以前から Image ビヘイビアに関していつか使い方をまとめようと思っていたので紹介します。
参考サイト:ActAs Image column behavior (Articles) | The Bakery, Everything CakePHP
Baker で紹介されていた Image ビヘイビアです。このビヘイビアはアップロードされた画像をサムネイル作成、リサイズ、複数のバリエーションのサイズの画像を作成してくれます。またモデルを find すると画像のパスを返してくれます。
作成される画像は、webroot/img/[Model Name]/[Model ID]/ 以下に設定した名前でそれぞれの画像を作成してくれます。

インストール
元サイトにソースがありますが、コメント欄でかなりやり取りがあり結構修正しなければなりません。コメント欄以外にも私の方で修正した部分もあります。最終的に使ったソースをアップしておきます。
ImageBehavior – GitHub
DB の準備
まずモデルのカラムにアップロードファイルの mime タイプを入れるカラムを作成します。今回はユーザ名と画像を持つユーザモデルを作成します。

CREATE TABLE `users` (
`id` tinyint(4) NOT NULL auto_increment,
`name` varchar(20) NOT NULL,
`image` varchar(255) default NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`)
);

モデル
次にモデルに Image ビヘイビアの設定を入れます。
カラム名の指定
array(’fields’=>’image’) となっている部分が DB のカラムに指定したカラム名になります。
サムネイルの指定
thumbnail => array(’create’=>true) とすることにより、thumb_ をプレフィックスにしたファイル名でサムネイル画像が作成されます。サイズはデフォルトで 100×100 です。サイズの指定も可能です。この指定を省略すればサムネイルは作成されません。
リサイズの指定
resize => array(…) で指定したサイズでリサイズします。縦、横のサイズ、アスペクト比を保つか、指定サイズよりも小さい場合拡大するかなどを指定します。省略した場合はリサイズされずにアップロードされます。
その他のサイズの画像作成
その他のサイズの画像を作成したい場合は、version => array( … ) で指定します。

class User extends AppModel {
var $name = 'User';
var $actsAs = array(
'Image'=>array(
'fields'=>array(
'image'=>array(
'thumbnail'=>array('create'=>true),
'resize'=>array(
'width'=>'200',
'height'=>'200',
'aspect'=>true,
'allow_enlarge'=>true,
),
'versions'=>array(
array(
'prefix'=>'small',
'width'=>'70',
'height'=>'70',
'aspect'=>true,
'allow_enlarge'=>true,
),
)
)
)
)
);
}

ビュー
注意する点としてはアップロードするので array(’enctype’=>’multipart/form-data’) の指定をお忘れなく。

<?php echo $form->create('User', array('enctype'=>'multipart/form-data'));?>

<?php __('Add User');?>
<?php
echo $form->input('name');
echo $form->file('image');
?>

<?php echo $form->end('Submit');?>

画像保存ディレクトリ
アップロードした画像は /webroot/img/ 以下にモデル名、モデルのID によってディレクトリが分けられ保存されます。そのため、webroot/img に apache 実行ユーザに書き込み権限を与えておく必要があります。保存形式は
/webroot/img/[Model Name]/[Model ID]/[column_name].[ext]
という感じになります。thumbnail と version で指定したものにはそれぞれプレフィックスが付きます。
上記の設定で、ユーザID が 1 のユーザが hoge.jpg という画像をアップロードすると
/webroot/img/User/1/image.jpg
/webroot/img/User/1/thumb_image.jpg
/webroot/img/User/1/small_image.jpg
と3つのファイルが保存されます。
コントローラ
コントローラでは特に変わったことをする必要はありません。save すれば画像が保存されます。

function add() {
if (!empty($this->data)) {
$this->User->create();
if ($this->User->save($this->data)) {
$this->Session->setFlash(__('The User has been saved', true));
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash(__('The User could not be saved. Please, try again.', true));
}
}
}

ユーザモデルのデータを取得すれば、作成した各種画像のパスが取得できます。

$user = $this->User->read(null, $id);
debug($user);

Array
(
[User] => Array
(
[id] => 1
[name] => hoge
[image] => Array
(
[path] => User/12/image.jpg
[thumb] => User/12/thumb_image.jpg
[small] => User/12/small_image.jpg
)
[created] => 2009-11-13 15:48:02
[modified] => 2009-11-13 16:08:15
)
)

画像のパスは webroot/img ディレクトリからの相対パスなので下記のように Html ヘルパーを使って出力できます。

<?php echo $html->image($user['User']['image']['path']); ?>

その他
アップロード処理なので、モデルできっちりとバリデーション処理はしてください。この辺りも Behavior に組み込めればいいですね。