HtmlQuickFormで画像のアップロード

HtmlQuickFormは便利だと個人的にはすごく思う。

簡単なメールフォームの場合はこれで事足りるし、smartyをレンダラにすればデザインの自由度もぐっとあがる。

ネット上にはいろりろ情報が乏しいなぁ、みんなつかってないのかなぁと思いつつ、いざやってみるとまぁ大してのせるほど使い方は難しくないのかなぁと思ったりします。

で、今回、画像アップロード機能をつけた場合というのが発生して、何とかできた?のでのせてみたりします。


/*------------------------------------
* PEAR HTMLQuickForm
*------------------------------------*/
require_once 'HTML/QuickForm.php';
require_once 'HTML/QuickForm/group.php';
require_once 'HTML/QuickForm/DHTMLRulesTableless.php';
require_once 'HTML/QuickForm/Renderer/Tableless.php';
require_once 'Mail.php';
require_once 'Mail/mime.php';

?>









フォーム





/************************************
* HTMLQuickForm 設定
***********************************/
$form = new HTML_QuickForm_DHTMLRulesTableless(null,null,'toukou.php', null, array('enctype' => 'multipart/form-data'),true);


/*******************
* 要素の設定
*******************/

//名前
$form->addElement("text", "names", "お名前",array('size'=>60));


//メールアドレス
$form->addElement("text", "email", "メールアドレス",array('size'=>30,'style'=>'ime-mode:disabled;'));

//その他
$form->addElement("textarea", "content", "内容",array('rows'=>10,'cols'=>50));

//アップロード一時ディレクト
define('tmp_dir',dirname(__FILE__).'/tmp/');


/*************************************************
* エラーチェックの設定
*************************************************/
$form->addRule("names","お名前が空白です",'required', null, 'client');
$form->addRule("email","メールアドレスが空白です",'required', null, 'client');
$form->addRule("email","メールアドレスが不正です", email,null, 'client');

//ファイル
$photo1 =& $form->addElement('file','photo1','写真1(jpgのみ)');
$form->addElement('text','photo1_cap', '写真説明1',array('size'=>60));
$photo2 =& $form->addElement('file','photo2','写真2(jpgのみ)');
$form->addElement('text','photo2_cap', '写真説明2',array('size'=>60));
$photo3 =& $form->addElement('file','photo3','写真3(jpgのみ)');
$form->addElement('text','photo3_cap', '写真説明3',array('size'=>60));
//ファイルチェック
$form->addRule('photo1','ファイルサイズは700KBまでです。','maxfilesize',716800);
$form->addRule('photo1','JPEGのみアップロード可能です。','mimetype','image/jpeg');
$form->addRule('photo1','ファイル名が半角英数字ではありません','filename','/^(?!.*\.\.)[a-zA-Z0-9]([a-zA-Z0-9-_.]{0,18})[a-zA-Z0-9-_]$/');

$form->addRule('photo2','ファイルサイズは700KBまでです。','maxfilesize',716800);
$form->addRule('photo2','JPEGのみアップロード可能です。','mimetype','image/jpeg');
$form->addRule('photo2','ファイル名が半角英数字ではありません','filename','/^(?!.*\.\.)[a-zA-Z0-9]([a-zA-Z0-9-_.]{0,18})[a-zA-Z0-9-_]$/');

$form->addRule('photo3','ファイルサイズは700KBまでです。','maxfilesize',716800);
$form->addRule('photo3','JPEGのみアップロード可能です。','mimetype','image/jpeg');
$form->addRule('photo3','ファイル名が半角英数字ではありません','filename','/^(?!.*\.\.)[a-zA-Z0-9]([a-zA-Z0-9-_.]{0,18})[a-zA-Z0-9-_]$/');


/*************************************************
* フィルタの設定
*************************************************/
$form->applyFilter('__ALL__', 'htmlspecialchars');
$form->applyFilter('__ALL__','trim');
/****************************
* 画面遷移
****************************/

//エラーがなかった場合
if($form->validate()){
//$data = $form->getSubmitValues(true);
//修正するが押された場合
if(isset($_POST["buttons"]["reinput"])){
echo '

は必須項目です

';
$buttons = array(
$form->createElement("reset","reset","リセット",'id="reset"class="btn"'),
$form->createElement("submit","submit","送信",'id="submit" class="btn"')
);
$form->addGroup($buttons,"buttons","");
$renderer =& new HTML_QuickForm_Renderer_Tableless();

$form->accept($renderer);
echo $renderer->toHtml();
}

//送信ボタンを押されていたら確認画面を表示
elseif(isset($_POST["buttons"]["submit"])){
//画像のinputを削除
$form->removeElement('photo1');
$form->removeElement('photo2');
$form->removeElement('photo3');
if ($photo1->isUploadedFile()) {
$photo1->moveUploadedFile(tmp_dir);
$rename = date('Ymd_Hi_1').'.jpg';
rename(tmp_dir.$photo1->_value['name'],tmp_dir.$rename);
$form->addElement('static','photo1_tmp', '写真1サムネイル', '');
$form->addElement('hidden','photo1_up', $rename);
}
if ($photo2->isUploadedFile()) {
$photo2->moveUploadedFile(tmp_dir);
$rename = date('Ymd_Hi_2').'.jpg';
rename(tmp_dir.$photo2->_value['name'],tmp_dir.$rename);
$form->addElement('static','photo2_tmp', '写真2サムネイル', '');
$form->addElement('hidden','photo2_up', $rename);
}
if ($photo3->isUploadedFile()) {
$photo3->moveUploadedFile(tmp_dir);
$rename = date('Ymd_Hi_3').'.jpg';
rename(tmp_dir.$photo3->_value['name'],tmp_dir.$rename);
$form->addElement('static','photo3_tmp', '写真3サムネイル', '');
$form->addElement('hidden','photo3_up', $rename);
}

echo '

以下の内容でよろしければ送信を押してください

';
$buttons = array(
$form->createElement("submit","reinput","修正",'id="reinput"class="btn"'),
$form->createElement("submit","regist","送信",'id="submit" class="btn"')
);
$form->addGroup($buttons,"buttons","");
$form->freeze();
$renderer =& new HTML_QuickForm_Renderer_Tableless();
$form->accept($renderer);
echo $renderer->toHtml();
}
//登録ボタンが押されていたら登録処理を実行
elseif(isset($_POST["buttons"]["regist"])){
$data = $form->getSubmitValues(true);
//メール送信処理
ob_start();
include_once('mail_tmpl.txt');
$body =ob_get_clean();
ob_clean();
$body=mb_convert_encoding($body,"JIS","AUTO");

//添付メール配信
$mail_obj =& Mail::factory('mail');

$mime_obj = new Mail_mime();
$mime_obj->setTxtBody($body);
if(isset($data['photo1_up'])){
$mime_obj->addAttachment(tmp_dir.$data['photo1_up']);
}
if(isset($data['photo2_up'])){
$mime_obj->addAttachment(tmp_dir.$data['photo2_up']);
}
if(isset($data['photo3_up'])){
$mime_obj->addAttachment(tmp_dir.$data['photo3_up']);
}
$build_param = array(
'text_charset' =>'ISO-2022-JP',
'head_charset' =>'ISO-2022-JP',
);
$body = $mime_obj->get($build_param);
//日本語添付メールを送る
$headers = array(
'To' => '',//宛先
'From' => '',
'Subject' =>"=?iso-2022-jp?B?".base64_encode(mb_convert_encoding('稿がありました',"JIS","AUTO"))."?=", //題名
);

$header = $mime_obj->headers($headers);
$mail_obj->send(null,$header,$body);
//ファイル削除
if(isset($data['photo1_up'])){
unlink(tmp_dir.$data['photo1_up']);
}
if(isset($data['photo2_up'])){
unlink(tmp_dir.$data['photo2_up']);
}
if(isset($data['photo3_up'])){
unlink(tmp_dir.$data['photo3_up']);
}

echo "

受け付けました。

\n";
echo '';
}
}
else{
//初期画面の表示とエラー画面の表示
echo '

は必須項目です

';
//画像3枚
$buttons = array(
$form->createElement("reset","reset","リセット",'id="reset"class="btn"'),
$form->createElement("submit","submit","送信",'id="submit" class="btn"')
);
$form->addGroup($buttons,"buttons","");
$form->getValidationScript();
$renderer =& new HTML_QuickForm_Renderer_Tableless();

$form->accept($renderer);

echo $renderer->toHtml();
}

?>




と、こんな感じで1枚で入力画面→確認画面→完了画面とお手軽にできちゃいます。

やってみて、ポイントは、確認画面でフォームを$form->freeze();させても画像をアップロードするフォームは凍結されない事。(これは他のサイトでも言われてました。)
ので、$form->removeElement('photo1');で要素を削除すること。
画像のサムネイルの表示にはphpThumbを利用したこと。
phpThumbはクラスライブラリでcakephpでも利用できるので何かと使える便利なライブラリだと思います。
後、画像をアップロードしてメールに添付してサーバー上から削除したこと。
ですかね。

本当は複数画像も処理を1つにしたかったけど、よくわからなかったので妥協。
foreachでまわすのもなんだかなぁと。。。