PHPプログラミング

ベストプラクティス

フォームを作る vol.8

フォームにファイルアップロード機能をつける

  • このエントリーをはてなブックマークに追加

フォームにファイル添付機能をつけるための前準備として、ファイルを一時的にサーバーへアップロードする機能を実装していきます。

目次

  1. #  ファイル添付機能への前準備となるアップロード機能
  2. #  ファイルアップロード機能を実装する理由
  3. #  アップロード機能の実装
  4. #  確認ページへアップロードした画像を表示

ファイル添付機能への前準備となるアップロード機能

前回の「入力項目に合わせた様々なバリデーション」では、様々なフォームの入力形式にあわせたバリデーション機能を実装しました。
今回からはフォームにファイルのアップロード機能を実装していきます。

前回までに作成したコードはこちらからダウンロードできます:ダウンロード(約2.9KB)

ファイルアップロード機能を実装する理由

フォームにPDFファイルや写真画像などの「ファイル添付」機能をつけたい場合があります。
こちらの機能を実装するには、添付したいファイルを一旦サーバーへ保存する必要があります。
例えば、一般的なフォームとして次のような構成であるとします。

  • 入力ページ – 氏名やメールアドレスなど必要な事項を入力するページ
  • 確認ページ – 入力内容の確認ページ
  • 完了ページ – フォーム送信完了のメッセージが表示されるページ

「入力ページ」「と「完了ページ」の間に、入力内容を確認するための「確認ページ」があります。この場合、「氏名」や「メールアドレス」のような入力項目と一緒に、添付したいファイルも引き継ぐ必要があります。

しかし、添付するファイルは数MBと大容量になるケースも多いです。
そのため、この引き継ぎはサーバーの仮ディレクトリへ一時的に保存しておき、「完了ページ」のメール送信をするタイミングで改めてファイルを呼び出し、メールへの添付処理を行います。

メールへファイル添付をする処理はまた改めてご紹介します。
今回はまず、前準備となるファイルをサーバーへ仮保存する機能を実装していきましょう。

なお、ファイルアップロードについてはグローバル変数$_FILESを使用します。
こちらの変数についての基本的な使い方は「アップロードファイルの情報を取得する:$_FILES」をご覧ください。

アップロード機能の実装

images/test/

コード例

<?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にメッセージを入れます。

以上がファイルアップロード機能の流れでした。
続いて、アップロードしたファイルが確認ページでも表示されるように設定します。

確認ページへアップロードした画像を表示

入力内容の確認ページにアップロードした画像が表示されると、アップロードできたことが一目で確認できるため便利です。
続いて、この機能を実装していきましょう。
赤いコードが追加した箇所です。

コード例

<?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ファイルやその他の形式のファイルもアップロード可能です。

次回は、アップロードした画像ファイルをメールに添付する処理を実装していきます。

今回作成したファイル:ダウンロード(約3.2KB)

  • このエントリーをはてなブックマークに追加