PHP初心者がつまづいた画像ファイルを上げる際に倒さねばならぬエラーたち



PHP学習を始め３カ月がたち、簡単なphpのコードやSQL文を扱える様になってきました。
その中で、あれ!?となってしまいがちな処理に画像のアップロードがあります。

今回は初心者がつまづきやすい画像をアップロードする際の
代表的なエラーとその対応をまとめました。

今回はサンプルファイルとデータベーステーブルを作成し実際にこのエラーを粉砕していきます。

<h1>テストファイルの作成</h1>
まずは今回テストするために作成したファイル構成から
![スクリーンショット 2015-12-06 16.02.57.png](https://qiita-image-store.s3.amazonaws.com/0/80553/98e17343-a369-efbf-387b-c3c9b25ff9e0.png "スクリーンショット 2015-12-06 16.02.57.png")

今回はfile_uploadというサンプルファイルの中に

```
image       //画像を溜め込むファイル
sample.php //テストコードを書くphpファイル
```
を作成しています。
sample.phpには画像ファイルのアップロードに必要な

formタグ
move_uploaded_file
INSERT文
を書いています。
![スクリーンショット 2015-12-06 17.09.46.png](https://qiita-image-store.s3.amazonaws.com/0/80553/089b4316-f92c-1b17-cfce-1a12f3e1ec2d.png "スクリーンショット 2015-12-06 17.09.46.png")


このコードからスタートして実際にデータベースに上げることができる様に
エラーを解消していきます。
ブラウザはこのように表示されます。
![スクリーンショット 2015-12-06 15.28.22.png](https://qiita-image-store.s3.amazonaws.com/0/80553/77a2a6ca-9d0d-ccb1-4115-d2b07968fecc.png "スクリーンショット 2015-12-06 15.28.22.png")
なおデータベースは
![スクリーンショット 2015-12-06 15.29.08.png](https://qiita-image-store.s3.amazonaws.com/0/80553/d239fdb2-df0c-3321-0896-a01b26e317d4.png "スクリーンショット 2015-12-06 15.29.08.png")
このように簡単に作成しておきました。

<h1>画像がアップロードされない!</h1>
ではまずこの状態からファイルを送ってみましょう！
・・・・なんの反応もありません。
この状態ではもちろんDBには入りませんね。
まずformタグから見直します。
今の状態では、画像をアップロードするために一つ記述が足りません。
まずはformタグに

````HTML
enctype="multipart/form-data"
````
を記述します。
これで画像ファイルのアップロードであることを明示します。

<h1>アップロードした画像がファイルに格納されない</h1>
これでアップロードの準備が整いました。
早速アップロードしましょう！

![スクリーンショット 2015-12-06 16.27.10.png](https://qiita-image-store.s3.amazonaws.com/0/80553/6daabe79-0e0e-cca0-9450-89f6c5363468.png "スクリーンショット 2015-12-06 16.27.10.png")



・・・できません。
今度はブラウザにエラーが表示されています。
どうやらファイルのパーミッションに問題があるようです。

では実際にターミナルを開いてパーミションを確認しています。
`vagrant up`しているディレクトリ内に入って確認してみます。

````
vagrant ssh // ディレクトリ内にはいる
cd /var/www/html/file_upload  //今回作成したfile_uploadに移動
ls -la //ディレクトリの詳細情報を確認

````
![スクリーンショット 2015-12-06 16.38.02.png](https://qiita-image-store.s3.amazonaws.com/0/80553/cad918f7-11a1-bf70-88e6-e380cee6b704.png "スクリーンショット 2015-12-06 16.38.02.png")

この状態ではimageフォルダを操作できるのは`vagrant`権限のみです。
ブラウザからこフォルダを操作するためには
`apache`権限に変更しなくてはなりません。
これを忘れてコードとひたすら向き合うとこのエラーは解消できません。
このコードをターミナルで入力しましょう。

````
sudo chown apache:apache image
//sudoで権限を上位にて次の処理の実行
//chownでimageファイルの権限をapachに
````

![スクリーンショット 2015-12-06 16.43.06.png](https://qiita-image-store.s3.amazonaws.com/0/80553/4d30ccad-b524-21da-436d-c4964483cf12.png "スクリーンショット 2015-12-06 16.43.06.png")
これでimageファイルの権限がapacheに変更できました。

<h1>sprintfの使い方がおかしい</h1>
ここまでなおしたら`04.jpg`という画像ファイルを挿入してみます。
これでデータベースに挿入されたはずです！
![スクリーンショット 2015-12-06 16.56.01.png](https://qiita-image-store.s3.amazonaws.com/0/80553/64c39d0a-062f-12bd-e3d3-0b699c55e696.png "スクリーンショット 2015-12-06 16.56.01.png")


・・・・・おかしい
データベースに挿入したのは04.jpgというデータのはずですが、
データベースには4と挿入されています。
コードを確認してみましょう。
![スクリーンショット 2015-12-06 16.59.40.png](https://qiita-image-store.s3.amazonaws.com/0/80553/800562bb-ec9d-37b8-b11e-07a34f0d599c.png "スクリーンショット 2015-12-06 16.59.40.png")

デバックのためアップロードしたファイル名が正しいのか

````PHP
echo $image //$imageの中身を確認
````
で確認します。

`01.jpg`を今度はアップロードしてみます。

![スクリーンショット 2015-12-06 17.01.48.png](https://qiita-image-store.s3.amazonaws.com/0/80553/84ef2d9b-7de4-678b-30eb-e0f73c106d19.png "スクリーンショット 2015-12-06 17.01.48.png")

ブラウザにはアップロードのした画像の名前が正しく表示されています。

ではINSERT文ないの記述を確認します。
現在は

````PHP
$sql = sprintf('INSERT INTO upload_sample SET image=%d',$image);

````
`sprinf`を使ってimageカラムに$image(ファイルの名前)を挿入しています。
ここで確認しなくてはならないのがデータの形式です。
現在のコードでは`sprintf`でデータを購入したい箇所に`%d`を指定しています。
`%d`はint型を挿入する際に用います。

そこでコードを

````PHP
$sql = sprintf('INSERT INTO upload_sample SET image="%s"',$image);

````

`%d`の箇所を`%s`に変更します。
これで文字列型を格納できるようにしましょう。
文字列型なのでコーテーション`""`でくくるのもお忘れなく。
実際に画像を挿入してみましょう。

![スクリーンショット 2015-12-06 17.13.36.png](https://qiita-image-store.s3.amazonaws.com/0/80553/ce8f3599-a5ff-7810-6603-5ec81bdf2506.png "スクリーンショット 2015-12-06 17.13.36.png")

0.1.jpgが正しく表示されています。

<h1>画像が表示されない</h1>
では次にデータベースにあげた0.6.jpgをブラウザに表示させます。

````PHP
 $sql = 'SELECT * FROM upload_sample WHERE id = 6';
 //upload_sample　テーブルの中からidが6のものを表示
 $sql = mysqli_query($db,$sql) or die (mysqli_error($db)); 
 $image = mysqli_fetch_assoc($sql);
````

````HTML
 <img src="<?php echo $image['image'];?>" >
 //imgタグで画像の表示
````

これでブラウザを見てみましょう。

![スクリーンショット 2015-12-06 17.26.25.png](https://qiita-image-store.s3.amazonaws.com/0/80553/9be35c05-50e7-d40e-a28f-5808d8110ac5.png "スクリーンショット 2015-12-06 17.26.25.png")


はい、表示されていません。
原因を確認するために要素を検証してみます。
![スクリーンショット 2015-12-06 17.28.21.png](https://qiita-image-store.s3.amazonaws.com/0/80553/6c96f7d9-e967-934d-907a-e38965de6b5a.png "スクリーンショット 2015-12-06 17.28.21.png")

そしてこれをこのようにいじってみましょう。

![スクリーンショット 2015-12-06 17.29.32.png](https://qiita-image-store.s3.amazonaws.com/0/80553/e10e1069-db3a-0cf4-350e-d06207d7f103.png "スクリーンショット 2015-12-06 17.29.32.png")


つまりはパスの指定が間違っていたのですね。
コードを正しいパスに書き換えたら表示されました。
ではこのように変更しましょう。

````HTML
<img src="<?php echo 'image/'.$image['image'];?>">

//'image/'でファイルが格納されているフォルダを明示
//.で文字連結
//$image['image']で画像ファイルの名前を指定
//変数$imageは上のPHPコードで指定したカラムの内容を連想配列で格納しているのでその中のimageを指定
````

これでOKですね。

<h1>まとめ</h1>
これで最初のコードから画像をアップロードするまでのエラーを解消することができました。

確認したいことは

ファイルをフォームに入力する際の`enctype`の明示
ファイルの書き込み権限の確認 し`apache`に変更
使っている関数の使い方は正しいか。　今回は`srintf`の使い方です。
指定しているファイルのパスは正しいか。　
フォルダが増えたりフレームワークをつかったりするとさらに複雑になります。
`file_uploaded_move`関数にも正しく指定しましょう。

このくらいを確認すれば画像を上げる際に発生したエラーを解消する手がかりになりそうです。
こちらが最終的なコードです。
![スクリーンショット 2015-12-06 17.52.45.png](https://qiita-image-store.s3.amazonaws.com/0/80553/fb141643-7e02-f5f6-91c2-00bbeab45eae.png "スクリーンショット 2015-12-06 17.52.45.png")


*この記事は[IPU Advent Calender](http://qiita.com/advent-calendar/2015/ipu)に
投稿しています。

先輩方の優良な記事の骨休めになってくれたらなとも思います。

では！