FuelPHPでファイルのアップロード(実践編その8)

今日は、FuelPHPで実際にファイルをアップロードしてみたいと思います。Uploadクラスの詳細については、『FuelPHPのUploadクラス』をご参照下さい。ファイルの保存はデータベースに保存する方法と指定のフォルダに保存する方法があります。どちらも一長一短がありますが、今回はアップロードが簡単な指定のフォルダに保存する方法で作成したいと思います。

1. ファイルはフォルダに保存するにしても、保存したファイルの情報(ファイル名、保存したフォルダのパス、その他のファイル情報)は、データベースに保存しておいた方がいいので、実践編の最初の方で作成した、col_imagesテーブルを下記のように修正しました。

2. モデルcollection.phpに$_has_manyの設定をします。下記を追加します。$_has_manyは$_belongs_toとは逆で、主モデル(Aモデル)の1つのデータに対して参照モデル(Bモデル)の複数データをリレーションしています。つまり1つのデータが複数の画像を持てることになります。

app/classes/model/collection.php

//$_has_manyの設定
 protected static $_has_many = array(
 'colimg'=>array(
 'key_from'=> 'id',
 'model_to'=>'Model_Colimage',
 'key_to'=>'collection_id',
 'cascade_save'=>true,
 'cascade_delete'=>false,
 ),
 );

3. モデルcolimage.phpも作成します。

app/classes/model/colimage.php

<?php
class Model_Colimage extends Orm\Model{
 //使用するフィールド名をセット
 protected static $_properties = array(
 'id',
 'filename',
 'filepath',
 'mimetype',
 'collection_id',
 'info',
 'created',
 'content',
 );
 //テーブル名をセット
 protected static $_table_name = 'col_images';
 //プライマリーキーをセット
 protected static $_primariy = array('id');
}

4. コントローラにuploadアクションを追加します。

app/classes/controller/collection.php

public function action_upload($id){
 //もしPOST送信されたら
 if (Input::method() == 'POST'){
 //Uploadクラスの設定
 $config=array(
 'path'=>DOCROOT.'assets/img/collection',
 'auto_rename'=>true,
 'ext_whitelist'=>array('img','jpg','jpeg','gif','png'),
 );
 Upload::process($config);
 //ファイルアップロード検証がOKなら
 if(Upload::is_valid()){
 //アップロードファイルを保存します。
 Upload::save();
 //保存結果からファイル情報を取得
 $result=Upload::get_files();
 $colimage=Model_Colimage::forge();
 $colimage->filename=$result[0]['saved_as'];
 $colimage->mimetype=$result[0]['mimetype'];
 $colimage->filepath='collection/'.$result[0]['saved_as'];
 $colimage->collection_id=$id;
 //ファイル情報を配列のまま保存
 $colimage->info=serialize($result[0]);
 //もしデータが保存されたら
 if ($colimage and $colimage->save()){
 Session::set_flash('success', '<span class="btn btn-primary span9">ID-'.$colimage->collection_id.'の『'.$colimage->filename.'』を追加しました</span><br>');
 //detailページへ移動
 Response::redirect("collection/detail/$id");
 }else{
 //データが保存されなかったら
 Session::set_flash('error', '保存できませんでした');
 }
 }
 }
 $data['col']=Model_Collection::find($id);
 $this->template->title="WinRoad徒然草";
 $this->template->content = View::forge('collection/upload', $data);
 }

5. ビューファイルupload.phpを作成します。

app/views/collection/upload.php

<h3>画像挿入</h3>
 <?php echo Form::open(array('name'=>'upload','enctype'=>'multipart/form-data','method'=>'post')); ?>
 <?php echo '<div class="alert-error">'.Session::get_flash('error').'</div>'?>
 <table width="100%" border="0">
 <tr>
 <th align="right" scope="row" class="span2">タイトル:</th>
 <td><?=$col->title?>
 &nbsp;</td>
 </tr>
 <tr>
 <th align="right" scope="row">画像:</th>
 <td><?php echo Form::file('upload',array('class'=>'span4')); ?>
 &nbsp;</td>
 </tr>
 <tr>
 <th colspan="2" scope="row">
 <?php echo Form::submit('submit', '保存', array('class' => 'btn btn-primary span4')); ?>
 </th>
 </tr>
</table>
 <?php echo Form::close(); ?>

6. 画像挿入後に、挿入画像を確認するために、明細ページ(detail.php)も修正します。データベースの接続をOrmモデルに変更しましたので、ほとんどの部分を修正しています。尚、データの表示部分で$col->titleや、$col[‘modified’]の2種類の表記があります。本来ならどちらかに統一すべきですが、どちらも同じ結果ですので、あえて変更していません。

app/views/collection/detail.php

<div class="row">
 <h3 class="span9"><?php echo Session::get_flash('success','明細ページ');?></h3>
 <div class="btn-group span9">
 <?php echo '<div class="alert-error">'.Session::get_flash('error').'</div>'?>
 <?php echo Html::anchor('collection/edit/'.$col['id'],'修正',array('class'=>'btn btn-success'))?>
 <?php echo Html::anchor('collection/upload/'.$col['id'],'画像挿入',array('class'=>'btn btn-primary'))?>
 <?php echo Html::anchor('collection/delete/'.$col['id'],'削除',array('class'=>'btn btn-danger'))?>
 </div>
 </div>
 <div class="row">
 <div class="span9">
 <table width="100%" border="1">
 <tr>
 <th width="20%" scope="row">ID</th>
 <td width="50%"><?=$col->id?></td>
 <td width="30%" rowspan="7"><?=(empty($img->filepath)) ? '' : Asset::img($img->filepath,array('class'=>'span3'));?></td>
 </tr>
 <tr>
 <th scope="row">タイトル</th>
 <td><?=$col->title?></td>
 </tr>
 <tr>
 <th scope="row">種別</th>
 <td><?=$col->col_assort_id?></td>
 </tr>
 <tr>
 <th scope="row">作成日</th>
 <td><?=$col['created']?></td>
 </tr>
 <tr>
 <th scope="row">更新日</th>
 <td><?=$col['modified']?></td>
 </tr>
 <tr>
 <th scope="row">コード番号</th>
 <td><?=$col['col_code']?></td>
 </tr>
 <tr>
 <th scope="row">保管場所</th>
 <td><?=$col['save_space']?></td>
 </tr>
 <tr>
 <th scope="row">備考</th>
 <td colspan="2"><?=$col['note']?></td>
 </tr>
 </table>
 </div>
 </div>

7. それでは、ブラウザで確認してみます。indexページから修正するタイトル名をクリックします。

8. 新しく作成されている画像挿入ボタンをクリックします。

9. アップロードするファイルを選択して、保存ボタンをクリックします。

10. 挿入された画像が表示されています。

11. 画像データは、public/assets/img/collectionフォルダに画像Desert.jpgが挿入されているのが分かります。

12. phpMyAdminで保存された情報データを確認してみます。アップロードしたファイルの情報が保存されています。尚、infoフィールドには、Upload::get_files()で取得した配列がシリアル化して保存されています。これらの内容を取り出すには、unsirialize()を利用して下さい。いちいち取り出すのが面倒な使用頻度の高いファイル名、ファイルパス、mimetypeは別フィールドを作成して保存しています。

本日のコード解説

  •  ‘enctype’=>’multipart/form-data’
    データをマルチパートデータとして送信するときに指定します。フォーム内にファイルの送信欄を設置する場合は、この形式を指定しておく必要があります。ビューファイルupload.phpの2行目です。
  • ‘path’=>DOCROOT.’assets/img/collection’,
    アップロードファイルの保存場所をドキュメントルートのassets/imgフォルダ内のcollectionフォルダに指定します。collecitonフォルダが存在しない場合は、新しく作成されます。collectionコントローラのuploadアクション内8行目です。
  • ext_whitelist’=>array(‘img’,’jpg’,’jpeg’,’gif’,’png’),
    アップロードファイルを画像に限定するために、アップロード可能なファイルの拡張子を指定します。同じくuploadアクションの9行目です。
  •  Upload::process($config);
    ファイルの検証条件$configをセットします。uploadアクションの11行目です。
  • Upload::is_valid()
    アップロード下ファイルが検証に成功したかどうかを判定します。検証したファイルが1つ以上ある場合にtrueを返します。 uploadアクションの13行目です。
  • Upload::get_files()
    保存結果からファイル情報を取得します。 ファイル情報は多次元配列として返りますので、ファイル情報を個別に取得するときに、多次元配列の最初のデータとして$result[0][‘saved_as’]のように取得するデータのキーを0に指定します。uploadアクションの17行目以下です。
  • $colimage->info=serialize($result[0]);
    ファイル情報をシリアル化して配列のまま保存します。ファイル情報を個別に取り出すには、unsirialize()で取り出すことが出来ます。uploadアクションの24行目です。
  • Asset::img($img->filepath)
    Assetクラスとは、静的なリソース(資産)に簡単にアクセスできる手段を提供するためのクラスです。ドキュメントルールのimgフォルダ、つまり、public/assets/imgフォルダにどこからでも簡単にアクセスすることが出来ます。ビューファイルdetail.phpの16行目です。

FuelPHPのUploadクラスを使うとファイルを簡単にしかも安全にアップロードすることが出来ますね。本日は以上です。

追伸

10.の画像で、種別が4のまま表示されていました。せっかく$_belongs_toでリレーションしているのに、これでは台無しですね。ビューファイルdetail.phpの24行目<?=$col->col_assort_id;?>を下記のように修正しました。尚、種別のIDが登録されていなければ、エラーになりますので、種別IDが登録されていなければ空白を表示するようにしています。

<?=empty($col->colas->as_name) ? '' : $col->colas->as_name;?>

ブラウザで確認すると下記のようにきちんと種別が表示されているのが確認できました。

以上、修正でした。(^0^)

このエントリーを含むはてなブックマーク Buzzurlにブックマーク livedoorクリップ Yahoo!ブックマークに登録

トラックバック&コメント

この投稿のトラックバックURL:

コメントをどうぞ

このページの先頭へ