2009年

[CakePHP] 画像のアップロード&リサイズを簡単にできる ImageBehavior このエントリーを含むはてなブックマーク

CakePHP Add comments

画像のアップロード&リサイズ処理などは割とよくある処理でかつ面倒なものです。その処理を簡単にやってくれる 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’) の指定をお忘れなく。

<div class="users form">
<?php echo $form->create('User', array('enctype'=>'multipart/form-data'));?>
	<fieldset>
 		<legend><?php __('Add User');?></legend>
	<?php
		echo $form->input('name');
		echo $form->file('image');
	?>
	</fieldset>
<?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 に組み込めればいいですね。

関連する投稿

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

  1. [CakePHP] 画像のアップロード&リサイズを簡単にできる ImageBehavior | Sun Limited Mt. « とっても! ちゅどん(雑記帳) Says:

    [...] [CakePHP] 画像のアップロード&リサイズを簡単にできる ImageBehavior | Sun Limite… [CakePHP] 画像のアップロード&リサイズを簡単にできる ImageBehavior | Sun Limited Mt. [...]

  2. skiedr Says:

    really nice that code i did long time ago still in use :)
    sorry that i comment not in Japanese, but my native is Russian :)

  3. matsuura Says:

    Hi, skiedr.
    Thank you for your comment.
    I think ImageBehavior is nice cood, too. :)

  4. 今週の管理人Bookmark (11/15-11/22) - ElectricBrain Standard Says:

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

  5. arai Says:

    すいません、質問なんですがこちらのImage ビヘイビアは確認画面を挟むと使えないんでしょうか?

  6. matsuura Says:

    araiさん
    コメントありがとうございます。
    通常フォームで確認画面を挟めばフォームからの入力内容をどこかに保持しているはずです。Image ビヘイビアを使っても同様です。

  7. arai Says:

    matsuuraさん
    ご回答ありがとうございます。
    自己解決しました!

  8. bubbkis Says:

    質問なのですが、
    Userが画像情報を保存していて、Postがbelongsto=>array(’User’)としている状態で、
    コントローラー側から$this->Post->find();とした場合、
    取り出したUser情報から画像パスは取得出来ませんでした。

    アソシエーションされてる側から、ImageBehaviorは動作しないのでしょうか?

  9. bubbkis Says:

    原因が分かりました。というか勉強になりました。
    afterFindで躓いてました。
    アソシエーションが設定されている関連モデルから呼び出されるafterFindはそのモデルで設定されているものだけで、behaviorで設定されたafterFindは呼び出されないようです。

    cake/libs/model/datasources/dbo_source.phpの__filterResults()を適当に直したら動作したのですが今後どんな影響が出るか分からない所が怖いですが・・・↓こんな風に弄くりました。
    if (isset($model->{$className}) && is_object($model->{$className})) {
    $data = $model->{$className}->afterFind(array(array($className => $results[$i][$className])), false);
    }

    ↓↓

    if (isset($model->{$className}) && is_object($model->{$className})) {
    $data = array(array($className => $results[$i][$className]));
    $return = $model->{$className}->Behaviors->trigger($model->{$className}, ‘afterFind’, array($data, false), array(’modParams’ => true));
    if ($return !== true) {
    $data = $return;
    }
    $data = $model->{$className}->afterFind($data, false);
    if (!isset($data[0][$className])) {
    unset($results[$i][$className]);
    }
    }

    ということで一応報告でした。

  10. matsuura Says:

    bubbkis さん、情報ありがとうございました。時間あるときに試してみます!

Leave a Reply

Additional comments powered by BackType

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS ログイン