LaravelでExcelファイルをアップロードする処理のテストする

画像ファイルのアップロードのテストは「UploadedFile::fake()->image()」を使ってテストできますが、Excelファイルのアップロードは同じようにはできません。

Excelファイルをアップロードする処理をテストする方法を紹介します。

PhpSpreadsheetのインストール

Excelファイルの読み書きのためにPhpSpreadsheetをインストールします。

composer require phpoffice/phpspreadsheet

テストコードの作成

テストコードを書いていきます。

use Illuminate\Http\UploadedFile;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Exception;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Tests\TestCase;

class UploadTest extends TestCase
{
    public function testStore()
    {
    }
}

Excelファイルの作成

テストコードでアップロードするExcelファイルを作成します。

Excelファイルを作成し、システムの一時ディレクトリに保存します。

# 新しいExcelスプレッドシートオブジェクトを作成
$spreadsheet = new Spreadsheet();
# 作成したスプレッドシートからアクティブなシートを取得
$sheet = $spreadsheet->getActiveSheet();
# シートのセルに値を設定
$sheet->setCellValue('A1', '森');
$sheet->setCellValue('B1', '一郎');
$sheet->setCellValue('A2', '林');
$sheet->setCellValue('B2', '二郎');
# Excelファイルを作成するためのライターオブジェクトを作成
$writer = new Xlsx($spreadsheet);
# 作成するExcelファイルのファイル名を生成
$filename = tempnam(sys_get_temp_dir(), '');
# ライターオブジェクトを使用して、先ほど作成したファイル名で保存
$writer->save($filename);

UploadedFileオブジェクトの作成

UploadedFileオブジェクトを作成します。

先ほど作成したExcelファイルをアップロードするようにします。

# アップロードされたファイルを表すUploadedFileオブジェクトを作成
$file = new UploadedFile(
    # ファイルのパス
    $filename,
    # ファイル名
    'sample.xlsx',
    # MIMEタイプ
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    null,
    true);

アップロード処理のテスト

ファイルをアップロードし、結果を確認します。

$this->post(route('upload.store'), [
    'excel' => $file,
])
    ->assertSuccessful()
    ->assertSeeText('登録しました');

Terraformをインストールする

Terraformをインストールする

tfenvを使ってTerraformをインストールする

プロジェクトによって使用するTerraformを切り替えることができるように、tfenvを使用します。

tfenvをインストールする

brew install tfenv

tfenvでインストール可能なTerraformのバージョンを確認する

tfenv list-remote

tfenvでTerraformをインストールする

tfenv install 1.5.5

インストールされているTerraformのバージョンを確認する

tfenv list

使用するTerraformのバージョンを切り替える

tfenv use 1.5.5

AWS CLIをインストールする

AWS CLIをインストールする

brew install awscli

AWS CLIがインストールされていることを確認する

aws --version

プロファイルを作成する

aws configure --profile プロファイル名

例:プロファイル名を「terraform」にした場合

aws configure --profile terraform

プロファイルの設定を入力する

AWS Access Key ID [None]: アクセスキーID
AWS Secret Access Key [None]: シークレットアクセスキー
Default region name [None]: ap-northeast-1
Default output format [None]: json

作成したプロファイルを使用する

export AWS_PROFILE=プロファイル名

プロファイルを確認する

aws configure list

Laravelで複数の画像ファイルのアップロードのバリデーション

次のようinputタグにmultiple属性をつけて複数のファイルをアップロードするときのリクエストの検証方法について。

<input type="file" class="form-control" name="images[]" multiple>

アップロードされたファイルがPNGファイルであることを検証する例です。

1つ以上のファイルがアップロードされていることを検証します。
バリデーションルールには「required」「array」を指定します。

$request->validate([
    'images' => 'required|array',
], [
    'images.required' => '画像ファイルを選択してください。',
]);

次に、配列の各要素が画像であることを検証します。
配列中の属性のバリデーションには「ドット記法」を使用します。
バリデーションルールには「required」「file」「mimes」を指定します。

$request->validate([
    'images.*' => 'required|file|mimes:png'
], [
    'images.*.required' => '画像ファイルを選択してください。',
    'images.*.file' => '画像ファイルを選択してください。',
    'images.*.mimes' => 'PNGファイルを選択してください。',
]);

全体のコードは次のようになります。

public function upload(Request $request)
{
    $request->validate([
        'images' => 'required|array',
        'images.*' => 'required|file|mimes:png'
    ], [
        'images.required' => '画像ファイルを選択してください。',
        'images.*.required' => '画像ファイルを選択してください。',
        'images.*.file' => '画像ファイルを選択してください。',
        'images.*.mimes' => 'PNGファイルを選択してください。',
    ]);

LaravelでTypetalkに投稿する

LaravelからTypetalkに投稿するコード。

class TypeTalkJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    private const TYPETALK_TOKEN = 'YOUR_TYPETALK_TOKEN';
    private const TYPETALK_URL = 'https://typetalk.com/api/v1/topics/:topicId';
    /** @var string 投稿するメッセージ。最大4000文字 */
    protected string $message;

    /**
     * TypeTalkJob constructor.
     * @param  string  $message  メッセージ
     */
    public function __construct(string $message)
    {
        $this->message = $message;
    }

    /**
     * Execute the job.
     *
     * @throws GuzzleException
     * @see https://developer.nulab.com/ja/docs/typetalk/api/1/post-message/
     */
    public function handle(): void
    {
        (new Client())
            ->request(
                'POST',
                self::TYPETALK_URL,
                [
                    'form_params' => ['message' => substr($this->message, 0, 4000)],
                    'headers' => ['X-Typetalk-Token' => self::TYPETALK_TOKEN,],
                ]
            );
    }
}