ワークショップ
お問い合わせフォームを作る(8)
フォームにファイルアップロード機能をつける
フォームにファイル添付機能をつけるための前準備として、ファイルを一時的にサーバーへアップロードする機能を実装していきます。
この記事のポイント
- PHPでファイルをアップロードする仕組みが分かる
- フォームにファイルアップロード機能を実装する
目次
ファイル添付機能への前準備となるアップロード機能
前回の「入力項目に合わせた様々なバリデーション」では、様々なフォームの入力形式にあわせたバリデーション機能を実装しました。
今回からはフォームにファイルのアップロード機能を実装していきます。
今回使用しているコードは、前回までに作成したものを使うことを前提としています。
前回のページ:vol.7 入力項目に合わせた様々なバリデーション
前回作成したコードはこちら:vol.7のサンプルコード – GitHub
ファイルアップロード機能を実装する理由
フォームにPDFファイルや写真画像などの「ファイル添付」機能をつけたい場合があります。
こちらの機能を実装するには、添付したいファイルを一旦サーバーへ保存する必要があります。
例えば、一般的なフォームとして次のような構成であるとします。
- 入力ページ – 氏名やメールアドレスなど必要な事項を入力するページ
- 確認ページ – 入力内容の確認ページ
- 完了ページ – フォーム送信完了のメッセージが表示されるページ
「入力ページ」「と「完了ページ」の間に、入力内容を確認するための「確認ページ」があります。この場合、「氏名」や「メールアドレス」のような入力項目と一緒に、添付したいファイルも引き継ぐ必要があります。
しかし、添付するファイルは数MBと大容量になるケースも多いです。
そのため、この引き継ぎはサーバーの仮ディレクトリへ一時的に保存しておき、「完了ページ」のメール送信をするタイミングで改めてファイルを呼び出し、メールへの添付処理を行います。
メールへファイル添付をする処理はまた改めてご紹介します。
今回はまず、前準備となるファイルをサーバーへ仮保存する機能を実装していきましょう。
Note
赤い箇所は追加するコードを、オレンジの箇所は修正しているコードを示します。
ファイルアップロードについてはグローバル変数$_FILESを使用します。
こちらの変数についての基本的な使い方は「アップロードファイルの情報を取得する:$_FILES」をご覧ください。
アップロード機能の実装
ここではファイルのアップロード先を「images/test/」とすることとして、index.phpにコードを書いていきます。
index.php
<?php
define( "FILE_DIR", "images/test/");
// 変数の初期化
$page_flag = 0;
$clean = array();
$error = array();
// サニタイズ
if( !empty($_POST) ) {
foreach( $_POST as $key => $value ) {
$clean[$key] = htmlspecialchars( $value, ENT_QUOTES);
}
}
if( !empty($clean['btn_confirm']) ) {
$error = validation($clean);
// ファイルのアップロード
if( !empty($_FILES['attachment_file']['tmp_name']) ) {
$upload_res = move_uploaded_file( $_FILES['attachment_file']['tmp_name'], FILE_DIR.$_FILES['attachment_file']['name']);
if( $upload_res !== true ) {
$error[] = 'ファイルのアップロードに失敗しました。';
} else {
$clean['attachment_file'] = $_FILES['attachment_file']['name'];
}
}
if( empty($error) ) {
$page_flag = 1;
}
} elseif( !empty($clean['btn_submit']) ) {
--- 途中省略 ---
<form method="post" action="" enctype="multipart/form-data">
<div class="element_wrap">
<label>氏名</label>
<input type="text" name="your_name" value="<?php if( !empty($clean['your_name']) ){ echo $clean['your_name']; } ?>">
</div>
<div class="element_wrap">
<label>メールアドレス</label>
<input type="text" name="email" value="<?php if( !empty($clean['email']) ){ echo $clean['email']; } ?>">
</div>
<div class="element_wrap">
<label>性別</label>
<label for="gender_male"><input id="gender_male" type="radio" name="gender" value="male" <?php if( !empty($clean['gender']) && $clean['gender'] === "male" ){ echo 'checked'; } ?>>男性</label>
<label for="gender_female"><input id="gender_female" type="radio" name="gender" value="female" <?php if( !empty($clean['gender']) && $clean['gender'] === "female" ){ echo 'checked'; } ?>>女性</label>
</div>
<div class="element_wrap">
<label>年齢</label>
<select name="age">
<option value="">選択してください</option>
<option value="1" <?php if( !empty($clean['age']) && $clean['age'] === "1" ){ echo 'selected'; } ?>>〜19歳</option>
<option value="2" <?php if( !empty($clean['age']) && $clean['age'] === "2" ){ echo 'selected'; } ?>>20歳〜29歳</option>
<option value="3" <?php if( !empty($clean['age']) && $clean['age'] === "3" ){ echo 'selected'; } ?>>30歳〜39歳</option>
<option value="4" <?php if( !empty($clean['age']) && $clean['age'] === "4" ){ echo 'selected'; } ?>>40歳〜49歳</option>
<option value="5" <?php if( !empty($clean['age']) && $clean['age'] === "5" ){ echo 'selected'; } ?>>50歳〜59歳</option>
<option value="6" <?php if( !empty($clean['age']) && $clean['age'] === "6" ){ echo 'selected'; } ?>>60歳〜</option>
</select>
</div>
<div class="element_wrap">
<label>お問い合わせ内容</label>
<textarea name="contact"><?php if( !empty($clean['contact']) ){ echo $clean['contact']; } ?></textarea>
</div>
<div class="element_wrap">
<label>画像ファイルの添付</label>
<input type="file" name="attachment_file">
</div>
<div class="element_wrap">
<label for="agreement"><input id="agreement" type="checkbox" name="agreement" value="1" <?php if( !empty($clean['agreement']) && $clean['agreement'] === "1" ){ echo 'checked'; } ?>>プライバシーポリシーに同意する</label>
</div>
<input type="submit" name="btn_confirm" value="入力内容を確認する">
</form>
<?php endif; ?>
</body>
</htm>
実行結果
入力ページに次のような「画像ファイルの添付」項目が追加されます。
確認ページへ進むと、指定したディレクトリへ画像が保存されます。
Note
ディレクトリへファイルをアップロードする際、ディレクトリのパーミッション(権限)に注意してください。書き込み権限がある場合のみアップロードすることができます。上記のディレクトリはテスト用のため「777」が設定されています。
解説
まずは入力ページのHTMLから解説していきます。
form要素にenctype属性を指定しています。
こちらの指定がないとフォームからのファイル送信ができません。
<form method="post" action="" enctype="multipart/form-data">
form要素で囲っている中で、「お問い合わせ内容」の下に新しくファイルを選択するためのinput要素を追加しています。
<div class="element_wrap">
<label>画像ファイルの添付</label>
<input type="file" name="attachment_file">
</div>
ここでファイルを選択すると、「入力内容を確認する」ボタンを押したタイミングでファイルがサーバーへ送信されます。
続いて、実行するPHPをみていきましょう。
PHPの最初の部分で、定数FILE_DIRを宣言しています。
これは実際にサーバーに存在するディレクトリを指定するようにします。
今回は仮に「images/test/」へアップロードする設定です。
※先述した通りディレクトリのパーミッションに注意。
「// ファイルのアップロード」から下では、実際にファイルをサーバーのFILE_DIRで指定したディレクトリへアップロードする処理を行っています。
まずはif文で、$_FILESにファイルが渡されているかを確認します。
もしファイルが渡されていたら、move_uploaded_file関数でファイルをアップロード(サーバーのディレクトリへ保存)。
アップロードが成功したらtrueが返されるので、配列$cleanへファイル名を渡します。
もしアップロードに失敗してしまった場合は配列$errorにメッセージを入れます。
以上がファイルアップロード機能の流れでした。
続いて、アップロードしたファイルが確認ページでも表示されるように設定します。
確認ページへアップロードした画像を表示
入力内容の確認ページにアップロードした画像が表示されると、アップロードできたことが一目で確認できるため便利です。
続いて、この機能を実装していきましょう。
index.php
<?php
--- 省略 ---
<form method="post" action="">
<div class="element_wrap">
<label>氏名</label>
<p><?php echo $clean['your_name']; ?></p>
</div>
<div class="element_wrap">
<label>メールアドレス</label>
<p><?php echo $clean['email']; ?></p>
</div>
<div class="element_wrap">
<label>性別</label>
<p><?php if( $clean['gender'] === "male" ){ echo '男性'; }else{ echo '女性'; } ?></p>
</div>
<div class="element_wrap">
<label>年齢</label>
<p><?php if( $clean['age'] === "1" ){ echo '〜19歳'; }
elseif( $clean['age'] === "2" ){ echo '20歳〜29歳'; }
elseif( $clean['age'] === "3" ){ echo '30歳〜39歳'; }
elseif( $clean['age'] === "4" ){ echo '40歳〜49歳'; }
elseif( $clean['age'] === "5" ){ echo '50歳〜59歳'; }
elseif( $clean['age'] === "6" ){ echo '60歳〜'; } ?></p>
</div>
<div class="element_wrap">
<label>お問い合わせ内容</label>
<p><?php echo nl2br($clean['contact']); ?></p>
</div>
<?php if( !empty($clean['attachment_file']) ): ?>
<div class="element_wrap">
<label>画像ファイルの添付</label>
<p><img src="<?php echo FILE_DIR.$clean['attachment_file']; ?>"></p>
</div>
<?php endif; ?>
<div class="element_wrap">
<label>プライバシーポリシーに同意する</label>
<p><?php if( $clean['agreement'] === "1" ){ echo '同意する'; }else{ echo '同意しない'; } ?></p>
</div>
<input type="submit" name="btn_back" value="戻る">
<input type="submit" name="btn_submit" value="送信">
<input type="hidden" name="your_name" value="<?php echo $clean['your_name']; ?>">
<input type="hidden" name="email" value="<?php echo $clean['email']; ?>">
<input type="hidden" name="gender" value="<?php echo $clean['gender']; ?>">
<input type="hidden" name="age" value="<?php echo $clean['age']; ?>">
<input type="hidden" name="contact" value="<?php echo $clean['contact']; ?>">
<?php if( !empty($clean['attachment_file']) ): ?>
<input type="hidden" name="attachment_file" value="<?php echo $clean['attachment_file']; ?>">
<?php endif; ?>
<input type="hidden" name="agreement" value="<?php echo $clean['agreement']; ?>">
</form>
--- 省略 ---
実行結果
確認ページに「画像ファイルの添付」が追加され、アップロードした画像が表示されます。
解説
追加したコードの2箇所で、$clean[‘attachment_file’]にファイル名が入っているかを確認しています。
<?php if( !empty($clean['attachment_file']) ): ?>
これは、アップロードが成功したら$clean[‘attachment_file’]にファイル名が格納されるためです。
if文の中では、シンプルにimg要素を使った画像の出力と、input要素で画像のファイル名を出力。
アップロードした写真が確認ページで表示されるようになりました。
以上で、フォームにファイルのアップロード機能が追加されました。
今回は分かりやすく画像ファイルを使っていますが、同じようにPDFファイルやその他の形式のファイルもアップロード可能です。
次回は、アップロードした画像ファイルをメールに添付する処理を実装していきます。
今回作成したコードはこちら:vol.8のサンプルコード – GitHub
こちらの記事は役に立ちましたか?
コメントありがとうございます!
運営の参考にさせていただきます。
記事一覧
- お問い合わせフォームを作る (イントロダクション) お問い合わせフォームを作る
- お問い合わせフォームを作る(1) お問い合わせフォームの入力ページを作成する
- お問い合わせフォームを作る(2) フォームの確認ページ&完了ページを作成
- お問い合わせフォームを作る(3) 自動返信メールの実装
- お問い合わせフォームを作る(4) 入力値の引き継ぎ
- お問い合わせフォームを作る(5) 入力値のサニタイズ
- お問い合わせフォームを作る(6) 入力値のバリデーション
- お問い合わせフォームを作る(7) 入力項目に合わせた様々なバリデーション
- お問い合わせフォームを作る(8) フォームにファイルアップロード機能をつける
- お問い合わせフォームを作る(9) アップロードしたファイルをメールに添付する
- お問い合わせフォームを作る(10) セッションでフォームの多重送信を防ぐ
ありがとうございます。
もしよろしければ、あわせてフィードバックや要望などをご入力ください。