PHP 画像アップロード


「画像アップロード」についてです。
間違っている部分があれば指摘していただけると助かります。よろしくお願いいたします。

さて本題ですが、phpの画像アップロードはhtml側とphp側で2つに分かれています。
まずはhtml側からです。

##1,HTML側でやること

###(1)methodは必ず「get」ではなく「post」にします。

 　　理由としては、下記の方の記事が参考になります。
　　　　https://qiita.com/kanataxa/items/522efb74421255f0e0a1

私自身,postというメソッドは、登録、アップデート、新規書き込みなど後に更新されることが予想されるものに対してはpostが適しているというように解釈しました。

###(2)enctype="multipart/form-data"をformタグに指定する

　　　　この部分に関しては、下記の方の記事がとても参考になります。
　　　　https://mugenup-tech.hatenadiary.com/entry/2014/08/28/100910

この部分は、のちに書くinputtype=fileと関係があり、enctypeを指定せずにfileを選択し、送信した場合画像ファイル名だけが送信され、肝心の中身は送られないと解釈しました。

###(3)inputタグを作成し、typeにfileを指定する。

このタグを作ると、見たことある方もいらっしゃるかもしれませんが下記の画像のようなボタンが作られます。

![ADD055A3-34F2-45BA-8D74-4D16E7346E44_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/76627b68-be17-d5b4-49a1-19edaa3a8a82.jpeg)

このボタンを押すと、macだとfinderが開かれ添付ファイルを選択できるようになります。
またname属性を指定すると、グローバル変数$_FILESのキー名として指定でき、変数などに代入できます。


html側は以上です。まとめると、、、
1,methodはpost
2,enctype="multipart/form-data"
3,inputタグを作成し、typeにfileを指定する。
となります。

##2,PHP側でやること

まず前提として、上記で送られたフォームデータはPHP側のグローバル変数の中に送られていることを理解します。また、ファイル名、画像の拡張子、画像の容量、サーバ上に一時保存される際の仮のファイル名など複数のデータがsubmitされているとイメージしておくと理解しやすいと思います。

|名前　|解説|
|:------------------|:--------------------|
|$_FILES[‘name属性名’][‘name’]|部分自身のパソコン上でのファイル名|
|$_FILES[‘name属性名’][‘size’]|ファイルの容量(バイト)|
|$_FILES[‘name属性名’][‘type’]|ファイルの拡張子|
|$_FILES[‘name属性名’][‘tmp_name’]|サーバ上に一時保存される際の仮のファイル名|
|$_FILES[‘name属性名’][‘error’]|ファイルアップロードに関するエラー文|


##(1)$_SERVER['REQUEST_SERVER']でformのメソッドがpost送信かどうかを確認する

書き方としては、、、

```

<?php

if($_SERVER['REQUEST_METHOD'] === 'POST')

?>

```

とします。

##(2)is_uploaded_file関数を実行する

html側で作ったpostフォームで本当にサーバ側に画像ファイルがアップロードされているかを確認します。isset関数の画像バージョンみたいなものですね。確認に使うものは[name属性名][tmp_name]です。

使い方としては、、、

```

<?php 

if(is_uploaded_file($_FILES[name属性名]['tmp_name']) === true)

?>

```

とします。


##(3)拡張子を取得する

これは上記がtrueだった場合のタイミングで行いたいのでif文の{}の中に記述してあげます。

書き方としては、、、

```

if(is_uploaded_file($_FILES[name属性名][tmp_name]) === true){

    $extension = pathinfo($_FILES[name属性名][tmp_name],PATHINFO_EXTENSION)

}

```

とします。

詳細に説明しますと、まずpathinfo関数を使います。
pathinfo関数とは、ファイルに関する情報を配列で返して取得する関数です。
この情報の中には、ファイルパスや拡張子を除いたファイル名、拡張子などが入っています。

これを第1引数に$_FILES[name属性名][tmp_name]を指定することによって画像ファイルに関する情報を取得します。

続けて、第2引数にPATHINFO_EXTENSIONを渡すことで拡張子の情報だけが$extensionに代入されるという流れになっています。


###(4)拡張子の指定とチェック

前項で拡張子の値を代入して作った$extensionを使って拡張子の指定とチェックを行います。

書き方としては、、、

```

if($extension === '使用したい拡張子名')

```

###(5)sha1,uniquid,mt_randを使ってランダムなファイル名の生成

前項がtrueだった場合にif文の中に入れてあげます。

```
$new_imagefile = sha1(uniqid(mt_rand(), true)). '.' . $extension;

```

出てきた関数の簡単な説明はこちらです。

|関数名 |実行内容
|:-----|:-----|
|sha1|数字とアルファベットを使った40桁のランダムな文字列を作る|
|uniquid|現在時刻のマイクロ秒までを元にして、唯一の値を生成します|
|mt_rand|ランダムな文字列を取得・引数を渡さない場合は、0〜32768|

これらを組み合わせて、ランダムなファイル名を自動で生成します。
最終的に同じファイル名で保存してしまった場合、意図しない上書きが発生してしまうのでそれを防ぐためです。

###(5)is_file関数を使って同じファイル名がないか確認をする

is_file関数は引数に画像を保存したいフォルダパス、ファイル名(ここで言う前項で作った変数$new_filenameの事)を渡して使います。

書き方として、、、

```
if(is_file(画像を保存したいディレクトリパス、$new_imagefile) !== true)


```

###(6) move_uploaded_fileを使って画像ファイルを指定のフォルダに保存

ここまで来たら後は、フォルダを指定して画像を保存するだけです。

書き方としては、、、

```

if (move_uploaded_file($_FILES['name属性名']['tmp_name'], 画像を保存したいディレクトリパス . $new_imagefile)) 

```

move_uploaded_fileは、第1引数に仮のファイル名を指定し、第2引数にファイルパスとファイル名を渡します。

以上になります。
プログラミングスクールで習ったことに沿ってやったのでかなり長くなりましたが、本当にアップロード、保存だけと最低限でやるなら(2)と(6)でも実行自体はできます。(前述しましたが、同じ名前にした場合新規ではなく上書きになりますのでご注意ください)

最後に全肯定踏んだバージョンと最低限にの2パターンのコードを書き要点をまとめて終わりにします。変数名や保存に使うディレクトリなどはご自身のお好みによって変更してください。

###全肯定ver

```
//画像保存場所ディレクトリ
$image_dir = ./images/;

//formメソッドの確認
if($_SERVER['REQUEST_METHOD'] === 'POST'){
    
    //アップロードの確認
    if(is_uploaded_file($_FILES['name属性名']['tmp_name']) === true){

    　　　　//アップロードされた画像の拡張子の取得
　　　　　　　　　　　　$extension = pathinfo($_FILES['name属性名'][tmp_name],PATHINFO_EXTENSION);
 
      //使用したい拡張子を指定して確認
      if($extension === '使いたい拡張子'){

          //ファイル名をランダムに生成
          $new_image = sha1(uniquid(mt_rand(),true) . '.' . $extension);

          //同名のファイルの有無の確認
          if(is_file($image_dir,$new_image) !== true){

              //画像を保存したいディレクトリに移動させる
              if(move_uploaded_file($_FILES[name属性名][tmp_name],$image_dir . $new_image) !== true){

                  ※1

              }※1

          }※1

      }※1

    }※1

}※1

※1 elseなどを追加して実行できなかった場合のエラー文を記述しておくと何処で引っかかっているのか対応しやすくなります。
```

続いて、最低限バージョンです。

```
//画像の保存場所
$image_dir = ./images/;

//画像ファイルの名前
$image_name = $_FILES['name属性名']['自身で決めた名前']

//アップロードの確認
if(is_uploaded_file($_FILES[name属性名][tmp_name]) === true){

    //画像を保存する
    if(move_uploaded_file($_FILES[name属性名][tmp_name],$image_dir . $image_name) === true){
    
    ※1
    
    }※1

}※1

※1 保存できた際のメッセージや失敗した際のエラー文を入れる
```

最後まで読んでいただきありがとうございます。お疲れ様でした。