PHPで画像をアップロードする


##はじめに
個人的なメモです。断片的な情報なのでよくわからないかもしれません。

##ファイルをアップロード
###手順的
1. フォームなどからファイルをPOSTやPUTする。
2. フォームから連携された``$_FILES``からファイル名を取得
3. move_uploaded_fileでファイルを任意の位置に移動

```
<?php
function upload(){
	//<input type="file" name="image">なので$_FILES['image']になる
	move_uploaded_file($_FILES['image']['tmp_name'],ファイルの移動先);
}
?>

<!DOCTYPE html>
<html lang="ja">
<body>
<form action="" method="POST" enctype="multipart/form-data">
    <input type="file" name="image">
    <input type="submit" value="upload">
  </form>
</body>
</html>
```

##画像のファイル名を生成

ファイルをアップロード時に、アップロードされたファイル名ではなく、ハッシュ化されたファイル名を付けたい場合がある。
その場合は下記のようのな方法がある。

###sprintfを使って画像のファイル名を生成

####sprintfとは
フォーマットされた文字列を返す。
ベースとなる文字列（$format）を指定の引数（$str,$num）で置き換える感じでしょうか。


```lang:php
$format = '%sさんが、%d歳になりました。';
$str = '佐藤';
$num = 40;

echo sprintf($format, $str,$num);//佐藤さんが、40歳になりました。
```

$formatの``%s``（string)、``%d``(integer)はそれぞれ変数の型を指定しています。

他にも沢山あるので、詳しくは下記を参照
>[sprintf](http://php.net/manual/ja/function.sprintf.php)


javascriptのときも文字の置き換えで同じようなことをやってましたが、
sprintfのほうが簡単に思えました。

```lang:js
var format = '%sさんが、%d歳になりました。';
var str = '佐藤';
var num = 40;

format = format.replace('%s',str).replace('%d',num);

console.log(format);//佐藤さんが、40歳になりました。

```



#####挿入される型と、挿入する型が違う場合
型を指定しているので、挿入する変数の型が異なる場合は正しく処理されません。
``%d``(integer)にstringを入れていみます。

```lang:php
$format = '%sさんが、%d歳になりました。';
$str = '佐藤';
$num = 40;

echo sprintf($format,$num,$str);//40さんが、0歳になりました。
```

#####挿入位置の順番と、引数の順番が異なる場合
置換文字列の位置が、引数の順番と異なる場合先の書いたやり方だと上手く動きません。

そんな時は、置換文字列の指定の仕方を少し変更します。

```
$format = '%2$sさんが、%1$d歳になりました。';
$str = '佐藤';
$num = 40;

echo sprintf($format,$num,$str);//佐藤さんが、40歳になりました。
```

同じ変数を複数使う場合も上記の方法で対応できます。

```
$format = '%2$sさんが、%1$d歳になりました。%1$d歳なのに、これだとヤバイです。';
$str = '佐藤';
$num = 40;

echo sprintf($format,$num,$str);//佐藤さんが、40歳になりました。40歳なのに、これだとヤバイです。
```

###画像のファイル名を生成

```
$format = '%s_%s.%s';
$time = time();
$sha1 = sha1(uniqid(mt_rand(),true));

//$extはファイル連携時に取得した拡張子
$file_path = sprintf($format,$time,$sha1,$ext);

//こんな感じの文字列ができる
//1465616468_b4185a37d1fa98b2eaf888ca229091d89e4e5f42.jpg
```




##アップロードしたファイルタイプを取得

```
exif_imagetype(ファイル名);
```

exif_imagetypeで取得できる値（他にも沢山あります）

| 値 | 定数 |
|--------|--------|
| 1    |   IMAGETYPE_GIF     |
| 2    |   IMAGETYPE_JPEG     |
| 3    |   IMAGETYPE_PNG    |



##新しい画像を、縦横サイズを指定して作成する

###手順
1. imagecreatefromgif()、imagecreatefromjpeg()、imagecreatefrompng()で新しい画像をファイル作成する
2. imagecreatetruecolor()でTrueColorイメージを作成する
3. imagecopyresampled()で、手順１で作成した画像ファイルを手順２で作成したイメージにコピーする
4. 画像を出力する。


####手順１
画像ファイルを作成

```
imagecreatefromgif({ファイルもしくはURL});
imagecreatefromjpeg({ファイルもしくはURL});
imagecreatefrompng({ファイルもしくはURL});
```
####手順２
TrueColorイメージを作成

```
imagecreatetruecolor (画像の幅 , 画像の高さ);
```

####手順3
イメージの矩形の部分 を別のイメージにコピーする。

```
imagecopyresampled (
	コピー先の画像, 
	コピー元の画像, 
	コピー先のx座標,
	コピー先のy座標,
	コピー元のx座標,
	コピー元のy座標,
	コピー先の幅,
	コピー先の高さ,
	コピー元の幅,
	コピー元の高さ
 )
```

####手順4 
画像をファイルに出力する。

```
imagegif(image, filename);
imagejpeg(image, filename);
imagepng(image, filename);

//image　・・・imagecreatetruecolor() のような画像作成関数が返す画像リソース
//filename　・・・保存するファイルへのパス　
```



```
$imagType = exif_imagetype($_FILES['image']['tmp_name']);
$imageFileName = $_FILES['image']['tmp_name'];

switch (imagType) {
      case IMAGETYPE_GIF:
        $srcImage = imagecreatefromgif($savePath);
        break;
      case IMAGETYPE_JPEG:
        $srcImage = imagecreatefromjpeg($savePath);
        break;
      case IMAGETYPE_PNG:
        $srcImage = imagecreatefrompng($savePath);
        break;
}

$thumbHeight = round($height * THUMBNAIL_WIDTH / $width);
    
$thumbImage = imagecreatetruecolor(THUMBNAIL_WIDTH, $thumbHeight);
    
imagecopyresampled($thumbImage,$srcImage,0,0,0,0,THUMBNAIL_WIDTH,$thumbHeight,$width,$height);
    switch (imagType) {
      case IMAGETYPE_GIF:
        imagegif($thumbImage,THUMBNAIL_DIR . '/' . imageFileName);
        break;
      case IMAGETYPE_JPEG:
        imagejpeg($thumbImage,THUMBNAIL_DIR . '/' . imageFileName);
        break;
      case IMAGETYPE_PNG:
        imagepng($thumbImage,THUMBNAIL_DIR . '/' . imageFileName);
        break;
    }

```

##ディレクトリ内のファイル（画像）を取得して表示

###手順
1. opendirでディレクトリを開く（ディレクトリのハンドルを取得）
2. readdirでディレクトリの中のファイルを取得（ディレクトリハンドルからエントリを読み込む）
3. 取得したファイルをエスケープして表示

```
$images = [];
$dir = opendir(ディレクトリのパス);

while(false !==($file = readdir($dir))){
  if($file === '.' || $file === '..'){
       continue;
  }
  $images[] = file;
}

<body>
<?php foreach ($images as $image):?>
   <img src="<?php echo htmlspecialchars($image, ENT_QUOTES, 'UTF-8'); ?>">
<?php endforeach;?>
</body>
```

##終わり
まだまだ理解が浅いです。