もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

LaravelのHasOneOfManyを今更試した

はじめに

こんばんは。今回もLaravelネタです。

結構前から触ってたのに全然気づいてなかったのですが、 1:Nな関係のテーブルに対して擬似的に1:1を定義して取得できる機能がありました。

laravel.com

本題

テーブル定義

CREATE TABLE `users` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(255) NOT NULL COMMENT 'メールアドレス',
  `password` varchar(255) COMMENT 'パスワード',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


CREATE TABLE `articles` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) unsigned NOT NULL COMMENT 'ユーザーID',
  `type` int unsigned NOT NULL COMMENT 'タイプ',
  `title` varchar(255) NOT NULL COMMENT 'タイトル',
  `body` text COMMENT '本文',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `articles_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ユーザーが持っている記事で最新のもの

    /**
     * @return HasOne<Article>
     */
    public function latestArticle(): HasOne
    {
        return $this
            ->hasOne(Article::class, 'user_id', 'id')
            ->latestOfMany('created_at');
    }

ユーザーが持っている記事で最古のもの

    /**
     * @return HasOne<Article>
     */
    public function oldestArticle(): HasOne
    {
        return $this
            ->hasOne(Article::class, 'user_id', 'id')
            ->oldestOfMany('created_at');
    }

ユーザーが持っている記事で最新のもので type が2のもの

    /**
     * @return HasOne<Article>
     */
    public function latestArticleType2(): HasOne
    {
        return $this
            ->hasOne(Article::class, 'user_id', 'id')
            ->ofMany(
                ['created_at' => 'max'],
                static fn (Builder $query) => $query->where('type', 2)
            );
    }

終わりに

便利な機能があっていいですね。

簡単ですが以上です。