🫠

【備忘録】laravel-dynamodbのpaginate()で詰まった話

に公開

概要

laravel-dynamodbとは、LaravelでDynamoDBを操作できるライブラリです。
https://github.com/baopham/laravel-dynamodb?tab=readme-ov-file

今回はライブラリの機能であるpaginate()で詰まった話をします。

何があったのか

App\Models\Post.php
    protected $casts = [
        'is_opened' => Opened::class,
        'opened_at' => 'datetime',
        'closed_at' => 'datetime',
    ];

    protected $dynamoDbIndexKeys = [
        'opened_index' => [
            'hash' => 'is_opened',
            'range' => 'opened_at',
        ],
    ];

Post内で上記キャストやGSIを設定した状態で、

// ページの最後の項目を取得する
$nextPage = $query->afterKey($items->lastKey())->limit(2)->all();

上記を試したところ、Type mismatch for attribute to updateとエラーが発生しました。

原因は?

https://github.com/baopham/laravel-dynamodb/blob/master/src/DynamoDbQueryBuilder.php#L190-L194
上記afterKey()にある
https://github.com/aws/aws-sdk-php/blob/master/src/DynamoDb/Marshaler.php#L117-L120
marshalItem()で使っている
https://github.com/aws/aws-sdk-php/blob/master/src/DynamoDb/Marshaler.php#L133
marshalValue()にて(長いので頭のみ)、$typeの型がEnumCarbonのせいかうまくいっておらず、インデックスを設定したキーであるis_openedopened_atNULLになっていた。

つまり、内部でDynamoDb::marshalItem($key)を使っているメソッドでEnumCarbonにキャストしてるキーがあると正常に取得できない......。

どうやって解決したのか?

諸事情により少し省略しますが......

            // 現在表示している最後の記事を取得
            $lastPost = Post::findOrFail($lastId);

            // 次のデータを取得
            $items = $query->afterKey([
                'id' => $lastPost->id,
                'is_opened' => $lastPost->is_opened->value,
                'opened_at' => $lastPost->opened_at->format('Y-m-d H:i:s'),
            ])
                ->limit($incrementedNum)
                ->all();

と、afterKey()に渡すキーを文字列で取得するよう修正しました。

いや〜〜〜調査に時間が掛かりました......。

Discussion