忘れているかもしれませんが、今回の一連のプログラムは「Baseballサークルサイト」を作る過程での勉強ですね。そこで今回はサークルメンバーが撮った画像をサークルサイト内に掲載するために画像アップロード機能を作っていきたいと思います。
画像アップロードの3つのステップ
- ステップ1 POSTメソッドで画像をサーバーにアップロード
- ステップ2 アップロードされた画像をサーバーにて保存
- ステップ3 画像フォルダ内の画像を一覧表示、ページング機能を持たせる。
ステップ1 POSTメソッドで画像をアップロード
画像アップロードフォームを作る
以前のトップページのindex.htmlをコピーしてupload.phpという名前で保存します。
upload.phpには、POSTされたデータがなければアップロードフォームを表示し、あれば画像を保存する機能を持たせます。そのため画像アップロードフォームは、actionの指定先が自分自身になります。
upload.php
ここから本文 | |
<h1>画像アップロード</h1> <form action=”upload.php” method=”post” enctype=”multipart/form-data”> <div class=”form-group”> <label>アップロードファイル</label><br> <input type=”file” name=”image” class=”form-control-file”> </div> <br> <input type=”submit” value=”アップロードする” class=”btn btn-primary”> </form> | enctypeという属性で、”multipart/form-dataを指定していますが、これは通常のPOST送信と違って画像ファイルなどをアップロードするときに指定する属性です。 inputタグのtype属性にfileを指定していると、アップロードするためのファイル選択になり、name属性がPOSTされたデータの変数名になります。 |
navbar.php
<li class=”nav-item”><a class=”nav-link” href=”info.php”>お知らせ</a></li> <li class=”nav-item”><a class=”nav-link” href=”upload.php“>画像アップロード</a></li> <li class=”nav-item”><a class=”nav-link” href=”album.php“>アルバム</a></li> <li class=”nav-item”><a class=”nav-link” href=”#”>掲示板</a></li> | upload.phpのリンクを追加。 また、 後ほど作成すalbum.phpのリンクを追加。 |
ステップ2 画像の保存
アップロードされた画像は、サーバー内のテンポラリフォルダという場所に一時的に保存されます。あくまでも一時的なので、これを今作っているBaseballサークル内の画像フォルダに移動する必要がでてきます。
そこで、まずはBaseballサークル内に画像を保存するためのフォルダを作成しましょう。baseballフォルダ内にalbumというフォルダを作成します。
それではupload.phpファイルを修正していきましょう。難しくなるのでゆっくりあせらず。
upload.php
<?php $fp = fopen(“info.txt”,”r”) ?> <?php $msg = null; $alert = null; | メッセージ表記を行うための$msgと、そのメッセージを表示するときのボックスの色を決める$alertのそれぞれの変数を作成。どちらもnullを代入しておき、アップロード状況がないことを表しておきます。画像がアップロードされてれば、それぞれに文字列が代入されます。 |
if(isset($_FILES[‘image’]) && is_uploaded_file($_FILES[‘image’][‘tmp_name’])){ $old_name = $_FILES[‘image’][‘tmp_name’]; $new_name = $_FILES[‘image’][‘name’]; | if構文でアップロードされたファイルがあるか、またそのファイルが正しくアップロードされたものであるかを調べます。 is_uploaded_file関数は、引数のファイル名を指定すると、正しい手順でアップロードされたものであればTUREを、そうでなければFALSEを返します。 $_FILESはグローバル変数です。1つ目の要素はinputタグでつけたname属性の値です。2つ目の要素は次のような各種情報が格納されます。 ・tmp_name:テンポラリフォルダにアップされたときに自動的につけられた仮の名前。 ・name:ファイルの種類 テンポラリフォルダのファイルをalbum.phpファルダ以下に $new_nameとして保存します。 |
if(move_uploaded_file($old_name,’album/’.$new_name)){ $msg = ‘アップロードしました’; $alert = ‘success’; } else { $msg = ‘アップロードできませんでした’; $alert = ‘danger’; } } ?> <!DOCTYPE html> <html lang=”ja”> ~ | move_uploaded_file(移動元ファイル名, 移動先ファイル名)関数を使って、テンポラリフォルダからalbumフォルダに画像を移動します。この関数は、正しく移動できればTRUEを返り値になります。 |
ステップ3 画像フォルダ内の画像を一覧表示
アップロードが出来ましたら次は、index.phpをコピーしalbum.phpというファイルを作り、画像フォルダ内の画像を一覧表示させてみましょう。
album.php
<?php $images = array(); | 画像ファイルのリストを格納する配列 |
if($handle = opendir(‘./album’)){ while($entry = readdir($handle)){ if($entry !=”.” && $entry !=”..”){ $images[] = $entry; } } closedir($handle); } ?> <!DOCTYPE html> <html lang=”ja”> ~ | 画像フォルダから画像ファイルを読み込みます。 opendir関数でフォルダを開きます。引数に指定されたフォルダを開き、ディレクトリハンドルを返します。これはどこのフォルダを開いているかを示すためのもので、サーバーとして使われることが多いOSではフォルダのことをディレクトリと呼ぶため「ディレクトリを操作するもの」という意味があります。 readdir関数は、引数のディレクトリハンドルからファイル名を読み込んで返り値にし、取得できなくなるとFALSEを返します。 ここではwhile構文を使ってファイル名を取得し、変数$entryに格納していきます。while構文の式では、readdir関数によりファイル名が取得出来ている限り条件式がTRUEになるため繰り返し続け、すべてのファイルを読み込んだらFALSEとなってループを抜けます。 $images配列に格納するのは、ファイル名が「.」と「..」ではないときです。この処理の理由は、サーバー上でファイル名の一覧を取得すると、現在のフォルダを示す「.」と、一つ上の階層のフォルダを示す「..」も取得してしまうためです。今回は画像ファイルだけ取得したいので、if構文でこの2つを除外しています。 ファイルの取得が終わったら、ファイルの読み書きをしたときと同様に、closedir関数を使ってフォルダを閉じています。 |
albumフォルダ内の画像がアルバムに一覧表示されました。
ページングの構築
何ページかに分けて表示していく処理、それがページングです。「次のページ」のようにある程度の個数に区切って次のページに表示させてみましょう。
album.php 赤字が追記
<?php $images = array(); $num = 3; if($handle = opendir(‘./album’)){ while($entry = readdir($handle)){ if($entry !=”.” && $entry !=”..”){ $images[] = $entry; } } closedir($handle); } ?> <!DOCTYPE html> <html lang=”ja”> ~ | $num = 3;で変数numを1ページに表示する画像の枚数に代入。 |
<?php if(count($images) > 0){ echo ‘<div class=”row”>’; $images = array_chunk($images, $num); $page = 1; | array_chunk関数は、第一引数の配列を第二引数の数ごとに分割する関数で戻り値は配列です。基本となるページ数は$pageに代入し1ページ目とします。 |
if(isset($_GET['page'] ) && is_numeric($_GET['page'])){ | if構文で「GETメソッドでpageという変数が送られたか?」と「page変数が数字か?」という2点について調べます。 isset関数は変数が定義されているかどうかを調べる関数で、定義されていればTRUE、されてなければFALSEを返します。 is_numeric関数は引数が数値の時にTRUE、そうでないときFALSE。 GETメソッドはURLに変数と値を指定するため、必ずしも期待する値が送られてくるは限りません。そのためpageという変数名で、値が数字であることを二重にチェックする必要があります。 正しく値が送られてれば、$_GET[‘page’]の値をintval関数により数値として受け取ります。 次のif構文では指定されたページに要素があるか確認します。$images[ページ数]の配列をisset関数で調べます。「もし存在しなければ」$pageに1を代入するという処理。調べるページ数は、$page-1の要素です。$imageは配列になっていて、1ページ目は要素番号だからです。 |
foreach ($images[$page-1] as $img){ echo ‘<div class=”col-3″>’; echo ‘<div class=”card”>’; echo ‘<a href=”./album/’.$img.'” target=”_blank”><img src=”./album/’.$img.'” class=”img-fluid”></a>’; echo ‘</div>’; echo ‘</div>’; } echo ‘</div>’; | foreach構文で指定するのが$images[$page-1]です。 以前は$imageだけでしたが、今回はarray_chunk関数で分割しているので、指定したページ数からマイナス1して、配列用のページ数を指定します。 |
echo ‘<nav><ul class=”pagination”>’; for ($i = 1; $i <= count($images); $i++){ echo ‘<li class=”page-item”><a class=”page-link” href=”album.php?page=’.$i.'”>’.$i.'</a></li>’; } echo ‘</ul></nav>’; }else { echo ‘<div class=”alert alert-dark” role=”alert”>画像はまだありません</div>’; } ?> | bootstrapの<ul class=”pagination“>を使ってページネーション画面を作ります。またli要素には<li class=”“page-item“>を、aタグ要素には<a class=”page-link” >を割り当てます。 ここでもbootstrapのユーザーのアクションに対してのアラートメッセージを提供するalertにより背景をdarkにした形で設定してます。 |