S3 operation using AWS SDK for PHP
Tags: php, aws
Published: 2020-09-10 12:25:07

Since I had a chance to touch it, I will organize the S3 operation using the AWS SDK for PHP.

An example of building the necessary resources on AWS and operating S3 with an application that uses FuelPHP.

### Work environment
・MacOS
・Composer 1.10.13
・FuelPHP 1.8.2
・AWS SDK for PHP 3.152.1

---

### Environment
#### infrastructure
I often see examples of hard-coding IAM user access keys and secret access keys on personal blogs.

It's an anti-pattern, and I don't think it will be used in actual operation, so I'll summarize an example using an IAM role.

Set an IAM user who has given S3 access authority to EC2 for verification, and use it in EC2.
Use CloudFormation for construction.

##### EC2
* CloudFormation definition will be described.

##### S3
* CloudFormation definition will be described.

##### IAM
* CloudFormation definition will be described.

##### EC2 instance profile
* CloudFormation definition will be described.

---

#### App
##### composer installation

Since composer is not included in mac, install it using Homebrew.

```
brew install composer
```

---

##### FuelPHP project creation

The framework uses FuelPHP. Create a project with composer.

```
composer create-project fuel/fuel:1.8.2 aws_php_sdk
```

As an aside, `composer create-project` seems to git clone the specified project and then composer install.

https://getcomposer.org/doc/03-cli.md#create-project

---

##### AWS SDK for PHP installation

https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/getting-started_installation.html

Execute the following under the project directory.
Sdk is installed under fuel/vendor/aws/aws-sdk-php

```
composer require aws/aws-sdk-php
```

---

### App development
Create and arrange the file according to the source configuration.
Actually, I feel that it is better to create a class and make it a wrapper function individually.
Below, only the code is summarized.

```php
<?php
// Import settings
require 'fuel/vendor/autoload.php';  // Set according to FuelPHP path

use Aws\S3\S3Client;  // Set to operate S3
use Aws\Exception\AwsException;  // SDK general exceptions
use Aws\S3\Exception\S3Exception;  // S3 specific exceptions

// Get credentials
use Aws\Credentials\CredentialProvider;  // Set to get credentials

try {
    $provider = CredentialProvider::instanceProfile();
    $memoizedProvider = CredentialProvider::memoize($provider);
} catch (AwsException $e) {
    echo $e->getMessage();
}

// S3 client credentials settings
$client = new S3Client([
    'region'      => 'ap-northeast-1',
    'version'     => 'latest',
    'credentials' => $memoizedProvider,
    'debug'   => true  // If debug is specified, the error log can be seen in detail at the time of verification.
]);

// S3 StreamWrapper registration
try {
    $client->registerStreamWrapper();
} catch (S3Exception $e) {
    echo $e->getMessage();
}

// Bucket list display
try {
    $iter = Aws\recursive_dir_iterator('s3://bucket/key');
    foreach ($iter as $filename) {
        echo $filename . "\n";
    }
} catch (S3Exception $e) {
    echo $e->getMessage();
}

// Download data
try {
    $data = file_get_contents('s3://bucket/key');
} catch (S3Exception $e) {
    echo $e->getMessage();
}

// Upload data
try {
    file_put_contents('s3://bucket/key', 'Hello!');
} catch (S3Exception $e) {
    echo $e->getMessage();
}

// Move data
try {
    rename('s3://bucket/src', 's3://bucket/dist');
} catch (S3Exception $e) {
    echo $e->getMessage();
}

```

#### Import settings

https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/getting-started_basic-usage.html

Add import settings.

---

#### Get credentials

https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials_provider.html

Get credentials. This time, get it from the instance profile.

---

#### S3 Client Credential Settings

Define an S3 client and set credentials

---

#### S3 stream wrapper registration

https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-stream-wrapper.html

Register to use S3 stream wrapper for S3 operation.

---

#### Bucket list display

How to get recursively with few HTTP requests.

---

#### Download / upload / move data

It is difficult to understand how to use the move if it is a document.
You can use it like an mv command by passing the path of the move source and move destination.

---