PHPプログラミング

最終更新日:
公開日:

ワークショップ

お問い合わせフォームを作る(8)

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

ワークショップ「お問い合わせフォームを作成する」の第8回目は、フォームにファイル添付機能をつけるための前準備としてファイルを一時的にサーバーへアップロードする機能を実装していきます。

この記事のポイント

  • PHPでファイルをアップロードする仕組みが分かる
  • フォームにファイルアップロード機能を実装する
  • ファイルをアップロードするサーバーのディレクトリはパーミッション(権限)に注意する

目次

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

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

今回使用しているコードは、前回までに作成したものを使うことを前提としています。
前回のページ:vol.7 入力項目に合わせた様々なバリデーション
前回作成したコードはこちら:vol.7のサンプルコード – GitHub

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

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

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

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

ページを移動する度に添付するファイルをアップロードしたり、表示用にダウンロードすると通信するファイルサイズが増えてしまい効率が悪くなってしまいます。
そのため、ファイルはサーバーの仮ディレクトリへ一時的に保存しておき、「完了ページ」のメール送信をするタイミングで改めてファイルを呼び出してメールに添付する実装にします。

メールにファイルを添付する実装については次回改めて解説します。
今回は前準備として、添付するファイルをサーバーへ仮保存する機能を実装していきましょう。

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

define( "FILE_DIR", "images/test/");

---- 省略 ----

PHPの最初の部分で、定数FILE_DIRを宣言しています。
これは実際にサーバーに存在するディレクトリを指定するようにします。
今回は仮に「images/test/」へアップロードする設定にしています。
※先述の通り、ディレクトリのパーミッションの設定に注意してください。

// ファイルのアップロード」のコードでは、フォームで選択されたファイルをサーバーのFILE_DIRで指定したディレクトリへアップロードする処理を行っています。

---- 省略 ----

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']) ) {

---- 省略 ----

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>

--- 省略 ---

変更を保存したら、ブラウザで改めてフォームを表示してみましょう。
フォームの「画像ファイルの添付」から画像ファイルを選択し、「入力内容を確認する」ボタンを押して進んでください。

続いて表示される確認ページに、「画像ファイルの添付」が追加されてアップロードした画像が表示されます。

確認ページにアップロードした画像が表示される

追加したコードでは$clean['attachment_file']にファイル名が入っていることを確認しています。

<?php if( !empty($clean['attachment_file']) ): ?>

これはアップロードが成功すると$clean['attachment_file']にファイル名が格納されるためです。

if文の内側では、img要素による画像の出力とinput要素による画像のファイル名を出力しています。
アップロードした画像が確認ページに表示されるようになりました。

以上で、フォームにファイルのアップロード機能を追加することができました。
今回は画像ファイルを使っていますが、同じアップロードの仕組みを使ってPDFファイルやその他の形式のファイルもアップロードすることが可能です。
ただし画像ではない場合については、確認ページでファイル内容を表示するときにひと工夫必要になります。

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

今回作成したコードはこちら:vol.8のサンプルコード – GitHub