EC-CUBE:画像アップロードのしくみ(開発者向け)

EC-CUBEにおいて、ルールに則って画像アップロードを行う場合、一般的なHTMLテンプレートフォームは以下のように4つのパートで構成されます。

  1. 画像アップロード専用のhiddenパラメータ
  2. アップロード後の画像サムネイル表示エリア+画像削除リンク
  3. 画像ファイル参照フォーム要素
  4. アップロードボタン

では具体的にHTMLテンプレートと、PHPプログラムを見ていきましょう。

本記事はVer2.12以降を対象にしています。

アップロード用のフォームサンプル

<form name="form1" id="form1" method="post" action="./<!--{$smarty.server.SCRIPT_NAME}-->" enctype="multipart/form-data">
<input type="hidden" name="<!--{$smarty.const.TRANSACTION_ID_NAME}-->" value="<!--{$transactionid}-->" />
<input type="hidden" name="mode" value="edit" />
<input type="hidden" name="image_key" value="" />
<input type="hidden" name="image_key" value="" />
<!--{foreach key=key item=item from=$arrHidden}-->
<input type="hidden" name="<!--{$key}-->" value="<!--{$item|h}-->" />
<!--{/foreach}-->
<!--{assign var=key value="logo_image"}-->
<span class="attention"><!--{$arrErr[$key]}--></span>
<!--{if $arrFile[$key].filepath != ""}-->
<img src="<!--{$arrFile[$key].filepath}-->" alt="<!--{$arrForm.name|h}-->"> <br /><a href="" onclick="eccube.setModeAndSubmit('delete_image', 'image_key', '<!--{$key}-->'); return false;">[画像の取り消し]</a><br />
<!--{/if}-->
<input type="file" name="<!--{$key}-->" style="<!--{$arrErr[$key]|sfGetErrorColor}-->" />
<a class="btn-normal" href="javascript:;" name="btn" onclick="eccube.setModeAndSubmit('upload_image', 'image_key', '<!--{$key}-->'); return false;">アップロード</a>
</form>

アップロードボタンで発行されるデータ送信用のJavaScript

アップロードボタンが押されると「eccube.setModeAndSubmit()」関数が呼ばれます。

/**
* モードとキーを指定してSUBMITを行う。
*
* @param string mode フォームのhidden要素「mode」をこの値に設定する。
* @param string keyname 次のkeyidパラメータとセットでフォームデータに「(keyname)=(keyid)」としてPOSTされる。
* @param mixed keyid keynameパラメータの値としてセットされる。
*/
eccube.setModeAndSubmit(mode, keyname, keyid);

このJavaScriptによって「input type=”hidden” name=”mode”」の値が「upload_image」に設定され、一旦フォームの内容がSubmitされます。

ページクラス(LC_Page系クラス)内での処理方法

では、ページクラスでPOSTされたファイルデータを処理していきましょう。

サンプルの例だとアップロードされた画像ファイルデータは「$_REQUEST[‘logo_image’]」としてLC_Page継承クラスに渡されるので、これをaction()メソッドをオーバーライドして処理します。

データ受け入れ準備

public function action() {
$objFormParam = new SC_FormParam_Ex();
$mode = $this->getMode();
$this->lfInitParam($mode, $objFormParam);
// ファイル管理クラス
$this->objUpFile = new SC_UploadFile_Ex(IMAGE_TEMP_REALDIR, IMAGE_SAVE_REALDIR);
// ファイル情報の初期化
$this->objUpFile->addFile('ロゴ画像', 'sample_image', array('gif','jpeg','jpg','png'), IMAGE_SIZE, false, CLASS_IMAGE_WIDTH, CLASS_IMAGE_HEIGHT);
// Hiddenからのデータを引き継ぐ
$this->objUpFile->setHiddenFileList($_POST);

1~3行目はどのフォームでも共通なパラメータ受け取り用の処理です。

独特なのは「SC_UploadFile_Ex」クラスを利用した部分でしょう。
このクラスは画像だけではなく色々なファイルをアップロードする際にも利用でき、また複数のファイルアップロードにも対応した便利なクラスです。
「IMAGE_TEMP_REALDIR」はファイルの一時的なアップロード場所で「IMAGE_SAVE_REALDIR」は正式に投稿完了した際に保存先となる場所です。

また「addFile」メソッドはアップロードファイルの受け入れを定義する関数で、次のようなパラメータを必要とします。

/**
* ファイル情報追加
*
* @param string  $disp_name フォーム項目名(「ロゴ画像」など)
* @param string  $keyname   フォーム変数名(「logo_image」など)
* @param array   $arrExt    受け入れファイルの拡張子一覧
* @param integer $size      アップロード可能な最大ファイルサイズのバイト数
* @param boolean $necessary 必須ファイルかどうか(デフォルトはfalse)
* @param integer $width     最大ファイル幅(ピクセル)
* @param integer $height    最大ファイル高(ピクセル)
* @param boolean $image     画像ファイルかどうか(デフォルトはtrue)
*/
public function addFile($disp_name, $keyname, $arrExt, $size, $necessary=false, $width=0, $height=0, $image=true)

最後の「setHiddenFileList」メソッドですが、これはファイルをアップロードした際に、一時的な状態や正式にアップロードが完了した状態では、POSTパラメータに自動的にhiddenパラメータとしてアップロードしているファイル情報がセットされているので、その情報を毎回受け取れるようにしておくためです。

switch文で画像アップロード用の処理

フォームからのリクエストパターンは以下の4つが王道としてあります。

  1. フォーム画面の表示(pre_edit)
    ※すでに画像がアップされていたらそれをサムネール表示
  2. 画像のアップロードや再アップロード(upload_image)
  3. この内容で登録(edit)
  4. 画像の削除(delete_image)
switch ($mode) {
//この内容で登録
case 'edit':
$objFormParam->setParam($_REQUEST);
$objFormParam->convParam();
$post = $objFormParam->getHashArray();
$this->arrErr = $this->lfCheckError($post, $objFormParam);
if (count($this->arrErr) == 0) {
//画像を正式に保存フォルダに移す
$this->objUpFile->moveTempFile();
$this->tpl_onload = "location.href = './'".$_SERVER['SCRIPT_NAME']."; return;";
}
// 画像のアップロード
case 'upload_image':
$objFormParam->setParam($_REQUEST);
$objFormParam->convParam();
$post = $objFormParam->getHashArray();
// ファイル存在チェック
$this->arrErr = $this->objUpFile->checkExists($post['image_key']);
// 画像保存処理
$this->arrErr[$post['image_key']] = $this->objUpFile->makeTempFile($post['image_key']);
break;
// 画像の削除
case 'delete_image':
$objFormParam->setParam($_REQUEST);
$objFormParam->convParam();
$this->arrErr = $objFormParam->checkError();
$post = $objFormParam->getHashArray();
if (count($this->arrErr) == 0) {
$this->objUpFile->deleteFile($post['image_key']);
}
break;
//フォーム表示
case 'pre_edit':
$objFormParam->setParam($_REQUEST);
$objFormParam->convParam();
$this->arrErr = $objFormParam->checkError();
$post = $objFormParam->getHashArray();
//$arrRetはDBに格納したプラグインデータ等から取り出したファイル名
if (count($this->arrErr) == 0) {
$this->objUpFile->setDBFileList($arrRet);
}
break;
}
// FORM表示用配列を渡す。
$this->arrFile = $this->objUpFile->getFormFileList(IMAGE_TEMP_URLPATH, IMAGE_SAVE_URLPATH);
// HIDDEN用に配列を渡す。
$this->arrHidden = array_merge((array) $this->arrHidden, (array) $this->objUpFile->getHiddenFileList());

この内容で登録

フォームの内容変更を正式に登録するモードで、ファイルアップロード処理では「$this->objUpFile->moveTempFile()」によって一時的なディレクトリから保存用ディレクトリにファイルを移動させるだけの処理となります。

画像のアップロード

「$this->objUpFile->checkExists」の箇所でPOSTされたデータにファイル情報があるかどうか(必須でかつ存在しない場合はエラーメッセージが返る)をチェックします。

次の「$this->objUpFile->makeTempFile()」でファイルを一時的な場所に保存します。
なぜ一時的かというと、EC-CUBEのフォーム情報送信のルールではファイルアップロードした段階ではまだフォーム情報の登録ではないためです。「この内容で登録」($modeでいうと「edit」)して初めて正式な登録として処理します。

また、このモードではファイルアップロード処理のみに限定し、その他のフォーム情報のエラーチェックは行わないようにします。

画像の削除

画像の削除は「$this->objUpFile->deleteFile()」ですぐに削除されます。

フォーム表示

デフォルトではフォーム表示モードになります。

ここでは、あなたが作成したプラグインで管理している画像データリストなどのデータをDB等から取得し「(image_key名)=(ファイル名)」という形のハッシュ配列で「$this->objUpFile->setDBFileList()」に渡します。これによって「この内容で登録」で保存されている実際のファイルと(image_key名)が紐付けられます。

switch文で処理されたファイル情報を取り出す

「$this->arrFile…」の処理では、(image_key名)にファイル情報ハッシュを紐付けます。例えば、次のようなデータが紐付けられます。

Array
(
[logo_image] => Array
(
[filepath] => /upload/save_image/01031918_52c68e67d0d7e.png
[real_filepath] => /path/to/ec-cube/html/upload/save_image/01031918_52c68e67d0d7e.png
[width] => CLASS_IMAGE_WIDTH
[height] => CLASS_IMAGE_HEIGHT
[disp_name] => ロゴ画像
)
)

また「$this->arrHidden…」には、(image_key名)の頭に「temp_」「save_」が付加されたキー名に対応したファイル名がハッシュデータで設定されます。

Array
(
[temp_logo_image] => 01031918_52c68e67d0d7e.png
[save_logo_image] => 01031850_52c687f7ecd50.png
)

「temp_…」のデータは、画像をアップロードするモードで設定され、「save_…」はすでに保存された画像ファイルが存在する場合に常に付加されます。

このページをシェアする

1 件のコメント

  • ほたて より:

    探していた情報でした。
    ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

2014-01-04