CakePHP

CakePHP2.1でファイルのアップロード(実践編その9)

更新日:

今日は、CakePHPでファイルをアップロードしてみたいと思います。FuelPHPにはアップロードクラスというファイルのアップロードを簡単に処理するクラスがあって簡単でしたが、CakePHPでは、FuelPHPのように簡単にファイルをアップロードできるクラスはなさそうです。

1. まず、ファイルをアップロードするために、col_imagesテーブルをアソシエーションでcollectionsテーブルとつなげます。col_imagesテーブルは結構修正しています。詳細は、『FuelPHPでファイルのアップロード』をご確認下さい。

2. モデルにcollectionsテーブルとcol_imagesテーブルの関連づけを行います。前にcol_assortsテーブルとbelongsToで関連づけをしていますが、今回はhasManyで関連づけをします。

app/Model/Collection.php

//hasManyアソシエーションの設定
 public $hasMany = 'ColImage';

3. CakePHPは、たったこれだけでデータベーステーブルの関連づけが出来るのは、とても便利ですね。それでは、ファイルアップロード用のビューファイルを作成する前に、index.ctpにビューファイルへのリンクを作成します。下記のように修正しました。修正箇所は、29行目と39行目です。

app/View/Collection/index.ctp

<h1>私のコレクション</h1>
<div class="paging">
<?php
 echo $this->Paginator->prev('<<', array(), null, array('class' => 'prev disabled'));
 echo $this->Paginator->numbers(array('separator' => ''));
 echo $this->Paginator->next('>>', array(), null, array('class' => 'next disabled'));
 ?>
 </div>
 <table cellpadding="0" cellspacing="0">
 <tr>
 <th>
 <?php //echo "ID";?>
 <?php echo $this->Paginator->sort('id','ID');?>
 </th>
 <th>
 <?php //echo "タイトル";?>
 <?php echo $this->Paginator->sort('title','タイトル');?>
 </th>
 <th>
 <?php //echo "種別";?>
 <?php echo $this->Paginator->sort('col_assort_id','種別');?>
 </th>
 <th>
 <?php //echo "作成日";?>
 <?php echo $this->Paginator->sort('created','作成日');?>
 </th>
 <th><?php echo "コード番号";?></th>
 <th><?php echo "保管場所";?></th>
 <th><?php echo "画像";?></th>
 </tr>
 <?php foreach ($Collections as $row): ?>
 <tr>
 <td><?php echo h($row['Collection']['id']); ?>&nbsp;</td>
 <td><?php echo $this->Html->link($row['Collection']['title'],array('action'=>'edit',h($row['Collection']['id'])));?>&nbsp;</td>
 <td><?php echo h($row['ColAssort']['as_name']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['created']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['col_code']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['save_space']); ?>&nbsp;</td>
 <td><?php echo $this->Html->image('b_edit.png',array('url'=>'file_upload'.DS.$row['Collection']['id']));?></td>
 </tr>
<?php endforeach; ?>
 </table>

4. 次にファイルアップロード用のビューファイルを作成します。

app/View/Collection/file_upload.ctp

<h1>フィルのアップロード</h1>
<?php
//フォームの開始を宣言する
 echo $this->Form->create(null,array('type'=>'file'));
 //入力フォームの生成
 echo $this->Form->file('image');
 //フォームの終了宣言
 echo $this->Form->end('ファイルのアップロード');
?>
<!--画像がアップされた場合に表示する-->
<?php if(!empty($img['filename'])){;?>
<?php echo $this->Html->image($img['filepath']);}?>

4. ファイルを保存するためのfile_uploadアクションを作成します。

app/Controller/CollectionController.php

public function file_upload($id=null){ 
 //もしデータが送信されたら
 if($this->request->data){
 //ファイル情報の取得
 $image=$this->request->data['Collection']['image'];
 //データベース情報を整理する
 $data['filename']=$image['name'];
 $data['filepath']='collection/'.$image['name'];
 $data['collection_id']=$id;
 $data['mimetype']=$image['type'];
 $data['info']=serialize($image);
 $data['size']=$image['size'];
 //ファイルをデータベースに保存する
 $data['content']=file_get_contents($image['tmp_name']);
 //もしデータが保存されたら
 if($this->Collection->ColImage->save($data)){
 $this->Session->setFlash('画像データを保存しました');
 //ファイルの保存用パスの指定
 $path=IMAGES.'collection'.DS.$image['name'];
 //ファイルを指定フォルダに保存
 move_uploaded_file($image['tmp_name'], $path);
 //ファイル情報をビューに渡す
 $this->set('img',$data);
 echo var_dump($image);
 //データが保存できなかったら
 } else {
 $this->Session->setFlash('画像データは保存できませんでした');
 echo var_dump($image);
 }
 } 
 //指定プライマリーキーのデータをセット
 $this->request->data=$this->Collection->read(null,$id);
 }

5. 今回は、画像データのバリデーション処理をするためにモデルColImage.phpも作成します。

app/Model/ColImage.php

<?php
 App::uses('AppModel', 'Model');
 class ColImage extends AppModel{
 //画像データのバリデーション
 public $validate = array(
 'filename'=>array(
 array(
 //拡張子の指定
 'rule'=>array('extension',array('jpg','jpeg','gif','png')),
 'message' => '画像ではありません',
 )
 ),
 'size'=>array(
 array(
 //画像サイズの制限(1KB~1MB)
 'rule'=>array('range',1024,1048576),
 'message' => '画像サイズが範囲外です',
 )
 ),
 );
 }

6. それでは、ブラウザで確認してみます。indexページの画像入力用のリンクをクリックします。

7. アップロードしたい画像を指定して『ファイルのアップロード』ボタンをクリックします。

8. アップロードされた画像が表示されました。

9.  phpMyAdminでデータを確認してみます。今、アップロードしたデータが保存されています。

10. ファイルをアップロードしたフォルダも調べてみます。尚、collectionフォルダは、事前に作成しておきました。FuelPHPのUploadクラスなら、自動でフォルダごと作成してくれるのですが、CakePHPでは、先に保存先のフォルダは作成しておく必要があります。

app/webroot/img/collection/Desert.jpg

11. 尚、今回は、FuelPHPと違って、データベースにも直接保存してみました。それでは、データベースに保存した画像を表示してみましょう。file_viewアクションを作成します。

app/Controller/CollectionController.php

public function file_view($id){
 //オートレイアウトを無効にします
 $this->layout = false;
 //指定IDの最新のデータを検出します
 $image=$this->Collection->ColImage->find('first',array(
 'conditions'=>array('collection_id'=>$id),
 'order'=>array('created'=>'desc')));
 //ヘッダー情報を画像として指定します。
 header('Content-type: image/jpeg');
 //指定IDの画像データを表示します
 echo $image['ColImage']['content'];
 }

12. 画像を表示してみます。この画像は、コントローラで直接表示しています。

13. 只、データベースに保存したデータは、バイナリデータですので、ビューに渡して、ページの一部に表示するということが簡単には、出来ません。ページの一部として表示させるには、<img>タグで、表示させたい画像を指定する必要がありますので、imgフォルダに保存する必要があります。

 本日のコード解説

  •  $this->Html->image('b_edit.png',array('url'=>'file_upload'.....))
    Htmlヘルパークラスのimageメソッドは、画像タグを生成するためのメソッドです。第1引数に画像のパスを指定します。これは、『IMAGES_URL』で指定されたパスで、デフォルトはapp/webroot/imgがベースパスになりますので、表示したい画像をimgフォルダに保存してあれば、ファイル名指定するだけでパスを指定したことになります。 第2引数は、タグ属性値及びオプション名をキーとする値を連想配列で指定します。
  • $this->Form->creat(null,array('type'=>'file'))
    Formヘルパークラスのcreateメソッドは、フォームの開始を宣言するメソッドです。第1引数にモデル名を指定します。モデルを伴わないinputを行いたいときはnullを指定します。第2引数にはオプションを指定します。指定可能なオプションは、action、url、type、enctype、default、encodingです。typeにfileを指定した場合、enctypeは自動的にmultipart/form-actionが設定されます。
  • $this->Form->file('imge')
    Formヘルパークラスの、fileメソッドは、fileインプットタグを生成します。 第1引数に、フィールド名を指定します。第2引数は、オプションを配列で指定します。
  • file_get_contents()
    file_get_contentsは、PHPの関数で、ファイルの内容を全て文字列に読み込むための関数です。
  • move_uploaded_file()
    これもPHPの関数で、アップロードされたファイルを新しい位置に移動するための関数です。tmp(一時保存ファイル)ファイルを指定のフォルダに移動して保存します。第1引数にtmpファイル名、第2引数に移動する為のパスを指定します。
  • var_dump($image)
    これもPHPの関数で、指定した変数に関する型や値を含む構造化された情報を返します。この関数は、プログラム作成の段階でデータの情報を確認するためによく使用します。 アプリケーションを公開するときには、削除し忘れないようにして下さい。
  • 'rule'=>array('extension',array('jpg','jpeg','gif','png'))
    バリデーションで拡張子を指定しています。第2引数以外のファイルがアップロードされたら、バリデーションエラーになります。
  • 'rule'=>array('range', 1024,1048576)
    画像サイズの範囲を指定しています。第2引数が、最小値、第3引数が最大値です。ここでは、1KB以上1MB以下のサイズを指定しています。

CakePHPには、標準でファイルをアップロードするのに最適なクラスがありませんので、モデルのバリデーションを使って簡単なバリデーションは行っています。これ以外に同じファイル名があったら、上書きするのか別名で登録するのかとかいろいろな条件がありますが、ほとんど自分で作成しなければならないみたいです。この辺に関しては、FuelPHPの方が便利ですね。

本日は以上です。

-CakePHP
-

Copyright© WinRoad徒然草 , 2018 All Rights Reserved Powered by AFFINGER5.