LaravelでS3を使用する

ポートフォリオサイトへの導入です。
ALBで運用しているため、`public/storage`への保存ではロードされない場合があるということにようやく気づきました。おばか。

##IAMユーザー作成

当初は`AmazonS3FullAccess`をアタッチしていたのですが、権限が多すぎるため変更します。

参考にさせていただきました。ありがとうございます。
[Laravel による S3 操作に必要な最小限の IAM ポリシー](https://qiita.com/yatsubashi/items/cb13e70d6af5f89d9335)



>The required IAM permissions are:
>>
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1420044805001",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:ReplicateObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name",
                "arn:aws:s3:::your-bucket-name/*"
            ]
        }
    ]
}
```

<img width="1232" alt="スクリーンショット 2020-02-13 22.12.11.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380817/5f86176b-2a9c-9b4b-27ab-4316be4f9709.jpeg">

上記をjsonで指定し、ポリシーを新規作成。

作成したポリシーを早速アタッチ。
<img width="1136" alt="スクリーンショット 2020-02-13 22.15.44.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380817/c1dfbc69-2bad-2b64-476f-5253fa352721.jpeg">

OK！！

##S3バケット作成
アクセス権については、ACLブロックをオフに設定。
```新しいアクセスコントロールリスト (ACL) を介して許可されたバケットとオブジェクトへのパブリックアクセスをブロックする
オフ
任意のアクセスコントロールリスト (ACL) を介して許可されたバケットとオブジェクトへのパブリックアクセスをブロックする
オフ```

##Laravelへ組み込む

パッケージインストール。

```
composer require league/flysystem-aws-s3-v3
```

```composer.json
    "require": {
        "php": "^7.1.3",
        "barryvdh/laravel-debugbar": "^3.2",
        "doctrine/dbal": "^2.9",
        "fideloper/proxy": "^4.0",
        "fzaninotto/faker": "^1.4",
        "laravel/framework": "5.7.*",
        "laravel/tinker": "^1.0",
        "league/flysystem-aws-s3-v3": "^1.0" // 追加を確認
    },
```

`config`から`filesystems.php`を確認

```filesystems.php
      's3' => [
          'driver' => 's3',
          'key' => env('AWS_ACCESS_KEY_ID'),
          'secret' => env('AWS_SECRET_ACCESS_KEY'),
          'region' => env('AWS_DEFAULT_REGION'),
          'bucket' => env('AWS_BUCKET'),
      ],
```

環境変数に登録

```
AWS_ACCESS_KEY_ID= アクセスキーID
AWS_SECRET_ACCESS_KEY= IAMユーザーのシークレットアクセスキー
AWS_DEFAULT_REGION= ap-northeast-1
AWS_BUCKET=　バケット名
```

###アップロード周り

コントローラーに追記

```Controller.php
$name = time().'_'.$file->getClientOriginalName();
$disk = Storage::disk('s3')->putFileAs('/', $file, $name,'public');
```

引数に`public`を指定することで、URLによるアクセスが可能になるとのこと。

試しに保存。エラー発生。

```
Aws \ Exception \ CredentialsException

Error retrieving credentials from the instance profile metadata server. (cURL error 28: Connection timed out after 1001 milliseconds (see https://curl.haxx.se/libcurl/c/libcurl-errors.html))
```

`.env`と`filesystems.php`の変数名が一致していなかったので修正。

→保存できた。


###view周り
```Controller.php
        $user = User::findOrFail($id);

        if($user->photo_id !== null) {
            $path = Storage::disk('s3')->url('profile/'. $user->photo->filename);
        } else {
            $path = 'img/no_image.png';
        }
```

```
<img src="{{ $path }}" alt="ユーザー画像">
```

→表示された。

なんとか実装できました。
これでALBにも対応できそうです。

参考：
[超簡単！LaravelでS3を利用する手順](https://qiita.com/tiwu_official/items/ecb115a92ebfebf6a92f)
[LaravelのFlysystem-aws-s3でAmazon S3と連携しファイル操作を行う](https://www.ritolab.com/entry/8)
[[Laravel] AWS S3 と連携する 2 つの方法](https://atuweb.net/201610_laravel-cooperation-aws-s3/)
[公式](https://laravel.com/docs/5.7/filesystem)