1. 事前準備
1.1 S3バケットの作成
- AWS Management Consoleにログイン
- Amazon S3にアクセス
- 「バケットを作成」を選択
- リージョン(ap-northeast-1)とバケット名(任意だがグローバルで一意であるもの)を設定、他はデフォルトで一旦OK
1.2 IAMポリシーの作成
- 「ポリシーの作成」を選択
- 以下のポリシーを作成(名前: S3BucketCRUDPolicy)※ポリシー名は任意
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::your-bucket-name",
"arn:aws:s3:::your-bucket-name/*"
]
},
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
}
]
}
1.3 IAMユーザーの作成
- ユーザー名: s3-test-user(任意)
- ポリシーを直接アタッチ: S3BucketCRUDPolicy
- アクセスキーの作成: ローカルコード用
- アクセスキーとシークレットアクセスキーをメモしておく
2. Laravelプロジェクトの設定
2.1 AWS SDKのインストール
composer require aws/aws-sdk-php-laravel
2.2 設定ファイルの公開
php artisan vendor:publish --provider="Aws\Laravel\AwsServiceProvider"
2.3 環境設定
.env
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_BUCKET=ap-northeast-1
AWS_BUCKET=your-bucket
2.4 AWS設定ファイル
config/aws.php
<?php
use Aws\Laravel\AwsServiceProvider;
return [
/*
|--------------------------------------------------------------------------
| AWS SDK Configuration
|--------------------------------------------------------------------------
|
| The configuration options set in this file will be passed directly to the
| `Aws\Sdk` object, from which all client objects are created. This file
| is published to the application config directory for modification by the
| user. The full set of possible options are documented at:
| http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/configuration.html
|
*/
'credentials' => [
'key' => env('AWS_ACCESS_KEY_ID', ''),
'secret' => env('AWS_SECRET_ACCESS_KEY', ''),
],
'region' => env('AWS_REGION', 'us-east-1'),
'version' => 'latest',
'ua_append' => [
'L5MOD/' . AwsServiceProvider::VERSION,
],
];
3. テストコマンドの実装
3.1 コマンドの作成
php artisan make:command TestS3SimpleCommand
3.2 コマンドクラスの実装
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Aws\Laravel\AwsFacade as AWS;
use Aws\S3\Exception\S3Exception;
use Illuminate\Support\Facades\Log;
class TestS3SimpleCommand extends Command
{
protected $signature = 'test:s3-simple';
protected $description = 'S3接続テスト';
private $s3;
private $bucket;
private $testPrefix = 'test-connection/';
public function __construct()
{
parent::__construct();
$this->bucket = env('AWS_BUCKET');
}
public function handle()
{
$this->info('S3接続テストを開始します...');
try {
// 設定の表示
$this->showConfiguration();
// S3クライアントの初期化
$this->initializeS3Client();
// バケットアクセステスト
$this->testBucketAccess();
// アップロードテスト
$testFile = $this->createTestFile();
$uploadResult = $this->testFileUpload($testFile);
// ダウンロードテスト
$this->testFileDownload($uploadResult['key']);
// 削除テスト
$this->testFileDeletion($uploadResult['key']);
// テスト成功
$this->showSuccessMessage();
return 0;
} catch (S3Exception $e) {
$this->handleS3Error($e);
return 1;
} catch (\Exception $e) {
$this->error("予期せぬエラーが発生しました: " . $e->getMessage());
return 1;
} finally {
// 一時ファイルの削除
$this->cleanup();
}
}
private function showConfiguration()
{
$this->info('現在の設定:');
$this->table(
['項目', '値'],
[
['Region', env('AWS_DEFAULT_REGION')],
['Bucket', $this->bucket],
['Access Key', $this->maskString(env('AWS_ACCESS_KEY_ID'))],
]
);
}
private function initializeS3Client()
{
$this->info('S3クライアントを初期化中...');
$this->s3 = AWS::createClient('s3', [
'version' => 'latest',
'region' => env('AWS_DEFAULT_REGION'),
'http' => [
'verify' => true,
'timeout' => 15
]
]);
}
private function testBucketAccess()
{
$this->info("バケット '{$this->bucket}' へのアクセスをテスト中...");
$this->s3->headBucket([
'Bucket' => $this->bucket
]);
$this->info('[成功] バケットアクセス確認');
}
private function createTestFile(): string
{
$content = "Test content - " . date('Y-m-d H:i:s');
$tempFile = tempnam(sys_get_temp_dir(), 's3-test-');
file_put_contents($tempFile, $content);
return $tempFile;
}
private function testFileUpload(string $filePath): array
{
$key = $this->testPrefix . 'test-' . time() . '.txt';
$this->info("テストファイルをアップロード中... ({$key})");
$result = $this->s3->putObject([
'Bucket' => $this->bucket,
'Key' => $key,
'SourceFile' => $filePath,
'ServerSideEncryption' => 'AES256',
'Metadata' => [
'uploaded-by' => 'connection-test',
'timestamp' => time()
]
]);
$this->info('[成功] アップロード完了');
return ['key' => $key, 'result' => $result];
}
private function testFileDownload(string $key)
{
$this->info('ファイルのダウンロードをテスト中...');
$result = $this->s3->getObject([
'Bucket' => $this->bucket,
'Key' => $key
]);
$content = (string) $result['Body'];
$this->info('[成功] ダウンロード完了 (サイズ: ' . strlen($content) . ' bytes)');
}
private function testFileDeletion(string $key)
{
$this->info('テストファイルを削除中...');
$this->s3->deleteObject([
'Bucket' => $this->bucket,
'Key' => $key
]);
$this->info('[成功] 削除完了');
}
private function handleS3Error(S3Exception $e)
{
$this->error('S3エラーが発生しました:');
$this->error($e->getMessage());
$this->table(
['エラー詳細', '値'],
[
['Error Code', $e->getAwsErrorCode()],
['Error Type', $e->getAwsErrorType()],
['Request ID', $e->getAwsRequestId()],
['Status Code', $e->getStatusCode()],
]
);
$this->showTroubleshootingGuide($e->getAwsErrorCode());
Log::error('S3 Connection Test Failed', [
'error_code' => $e->getAwsErrorCode(),
'message' => $e->getMessage(),
'request_id' => $e->getAwsRequestId()
]);
}
private function showTroubleshootingGuide(string $errorCode)
{
$this->info("\nトラブルシューティングガイド:");
$guides = [
'AccessDenied' => [
'IAMユーザーの権限を確認してください',
'バケットポリシーを確認してください',
'必要な権限:s3:ListBucket, s3:PutObject, s3:GetObject, s3:DeleteObject'
],
'NoSuchBucket' => [
'バケット名が正しいか確認してください',
'リージョンの設定を確認してください'
],
'InvalidAccessKeyId' => [
'AWS_ACCESS_KEY_IDが正しいか確認してください',
'IAMユーザーが有効か確認してください'
]
];
foreach ($guides[$errorCode] ?? ['AWS Management Consoleで詳細を確認してください'] as $tip) {
$this->line("- {$tip}");
}
}
private function showSuccessMessage()
{
$this->newLine();
$this->info('全てのテストが成功しました');
$this->table(
['テスト項目', '結果'],
[
['バケットアクセス', '[成功]'],
['ファイルアップロード', '[成功]'],
['ファイルダウンロード', '[成功]'],
['ファイル削除', '[成功]']
]
);
}
private function cleanup()
{
// 一時ファイルのクリーンアップ
$tempFiles = glob(sys_get_temp_dir() . '/s3-test-*');
foreach ($tempFiles as $file) {
unlink($file);
}
$this->info('一時ファイルのクリーンアップが完了しました');
// S3ファイルのクリーンアップ
$this->s3->deleteMatchingObjects($this->bucket, $this->testPrefix);
$this->info('S3ファイルのクリーンアップが完了しました');
}
private function maskString(string $string): string
{
if (strlen($string) <= 8) {
return str_repeat('*', strlen($string));
}
return substr($string, 0, 4) . str_repeat('*', strlen($string) - 8) . substr($string, -4);
}
}
3.3 コマンドの実行
# キャッシュのクリア
php artisan config:clear
# テストコマンドの実行
php artisan test:s3-simple
3.4 設定の確認
# 利用可能なコマンドの確認
php artisan list
# AWS設定の確認
php artisan config:show aws
4. テスト機能
このコマンドは以下のテストを実行します:
- S3接続の確認
- バケットへのアクセス確認
- テストファイルのアップロード
- テストファイルのダウンロード
- テストファイルの削除
5. エラーハンドリング
主なエラーケース:
- AccessDenied: IAMユーザーの権限確認
- NoSuchBucket: バケット名とリージョンの確認
- InvalidAccessKeyId: アクセスキーの確認