0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Laravel】ページネーション用に「若いIDを古く」生成するFactory実装

0
Posted at

やりたい状態

「若いIDほど古い記事」にする。

例:12件生成する場合

IDが小さいほど古いデータ

id created_at
1 12日前
2 11日前
3 10日前
... ...
12 1日前

実際のコード

/database/factories/ArticleFactory.php
$article_total = 12;

Article::factory()
    ->count($article_total)
    ->sequence(function ($sequence) use ($article_total) {
    
        $offset_days = $article_total - $seq->index;

        return [
            'created_at' => now()->subDays($offset_days),
            'updated_at' => now()->subDays($offset_days),
        ];
    })
    ->create();

なぜこれで実現できるのか?

① Factoryは内部でループしている

概念的にはこう:

for ($i = 0; $i < 12; $i++) {
    // レコード生成
}

このとき ↓

ループ番号 ($i) 実際のID
0 1
1 2
2 3

② $sequence->index の正体

sequence()を使うと、Laravel内部ではこうなっています。

$sequence = new Sequence($i);

Sequenceクラス(簡略化):

class Sequence
{
    public $index;

    public function __construct($index)
    {
        $this->index = $index;
    }
}

つまり:

$sequence->index = ループ番号

③ なぜ引き算しているのか?

$offset_days = $article_total - $sequence->index;

12件の場合:

index 計算 subDays
0 12 - 0 12日前
1 12 - 1 11日前
2 12 - 2 10日前
... ... ...
11 12 - 11 1日前

だから:

id created_at
1 12日前
12 1日前

になる。

ページネーションでどうなる?

Article::orderBy('created_at', 'desc')->paginate(5);

1ページ目:

id 12, 11, 10, 9, 8

2ページ目:

id 7, 6, 5, 4, 3

3ページ目:

id 2, 1

並びが直感的でテストが安定します。

もし引き算しなかったら?

now()->subDays($sequence->index)

この場合:

id created_at
1 今日
2 1日前
3 2日前

若いIDが一番新しくなってしまう。

本質まとめ

今回のコードは実質これと同じ:

for ($i = 0; $i < 12; $i++) {

    $days = 12 - $i;

    $created_at = now()->subDays($days);
}

Laravelが内部でループして、
そのループ番号を $sequence->index として渡しているだけ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?