📌  相关文章
📜  laravel 多对多按类别获取相关帖子 - TypeScript (1)

📅  最后修改于: 2023-12-03 14:43:47.801000             🧑  作者: Mango

Laravel 多对多按类别获取相关帖子 - TypeScript

在这篇文章中,我们将讨论如何使用 Laravel 中的多对多关系以及 TypeScript 来按类别获取相关帖子。我们还将讨论如何使用 TypeScript 和其他一些最佳实践来编写清晰、可维护、易于理解的代码。

前置知识

在继续阅读本文之前,我们假设您已经熟悉了以下技术:

  • Laravel
  • TypeScript
步骤
1. 数据库模型

首先我们需要定义两个数据库模型,一个用于帖子,一个用于类别。这可以在 Laravel 中的 app/Models 目录下定义。

// app/Models/Category.ts

import { Model } from "sequelize-typescript";

class Category extends Model {
  // Define the category model here
}

export default Category;

我们还需要定义帖子模型,在同一个目录下创建 Post.ts 文件。

// app/Models/Post.ts

import { Model } from "sequelize-typescript";

class Post extends Model {
  // Define the post model here
}

export default Post;

这里我们使用了 sequelize-typescript 来定义模型。如果您使用的是原生的 sequelize,请参考官方文档了解更多。

2. 定义中间表

使用多对多关系时,我们需要定义一个中间表来存储对应关系。在这里,我们称之为 category_post。在 Laravel 和 TypeScript 中,我们可以使用 Eloquent 和 Sequilize 分别来定义此关联表。

在 Laravel 中,我们可以使用 Artisan 命令 make:migration 来创建迁移文件。

php artisan make:migration create_category_post_table --create=category_post

这将在 database/migrations 目录下创建一个文件,我们可以在里面描述 category_post 表的结构。

// database/migrations/2021_06_28_000000_create_category_post_table.php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCategoryPostTable extends Migration
{
    public function up()
    {
        Schema::create('category_post', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('category_id');
            $table->unsignedBigInteger('post_id');
            $table->timestamps();

            $table->foreign('category_id')->references('id')->on('categories');
            $table->foreign('post_id')->references('id')->on('posts');
        });
    }

    public function down()
    {
        Schema::dropIfExists('category_post');
    }
}

在 TypeScript 中,我们可以使用 Sequilize 来定义中间表。

// app/Models/CategoryPost.ts

import { Model } from "sequelize-typescript";

class CategoryPost extends Model {
  // Define the category_post model here
}

export default CategoryPost;

然后我们需要告诉 Sequelize CategoryPost 模型与 CategoryPost 模型之间的关联,并定义中间表中的字段。

// app/Models/CategoryPost.ts

import { Model, BelongsToMany, ForeignKey, Column } from "sequelize-typescript";
import Category from "./Category";
import Post from "./Post";

class CategoryPost extends Model<CategoryPost> {
  @Column
  @ForeignKey(() => Category)
  categoryId!: number;

  @Column
  @ForeignKey(() => Post)
  postId!: number;

  @BelongsToMany(() => Category, { through: CategoryPost })
  category!: Category;

  @BelongsToMany(() => Post, { through: CategoryPost })
  post!: Post;
}

export default CategoryPost;

这段代码告诉 Sequelize categoryIdpostId 分别与 categorypost 模型之间的关联,同时通过 belongsToMany 方法定义了多对多关系的关联类型。

3. 模型之间的关联

接下来,我们需要在我们的模型之间定义关联类型。在 Category 模型中,我们可以使用 belongsToMany 方法来定义帖子模型和中间表模型之间的关联。同样的,我们也需要在 Post 模型中定义与类别模型和中间表模型之间的关联。

在 Laravel 中,我们可以在模型类中的 categoryposts 方法中加入以下代码来定义关联。

// app/Models/Category.php

class Category extends Model {
  public function posts()
  {
    return $this->belongsToMany(Post::class);
  }
}

// app/Models/Post.php

class Post extends Model {
  public function categories()
  {
    return $this->belongsToMany(Category::class);
  }
}

而在 TypeScript 中,我们可以在 CategoryPost 模型中分别定义以下代码来定义关联。

// app/Models/Category.ts

import { Model, BelongsToMany } from "sequelize-typescript";
import Post from "./Post";
import CategoryPost from "./CategoryPost";

class Category extends Model<Category> {
  @BelongsToMany(() => Post, { through: CategoryPost })
  posts!: Post[];
}

export default Category;

// app/Models/Post.ts

import { Model, BelongsToMany } from "sequelize-typescript";
import Category from "./Category";
import CategoryPost from "./CategoryPost";

class Post extends Model<Post> {
  @BelongsToMany(() => Category, { through: CategoryPost })
  categories!: Category[];
}

export default Post;
4. 查询帖子

我们已经定义了数据库模型以及它们之间的关联关系,现在我们可以开始按类别获取相关帖子了。在 Laravel 中,我们可以使用以下代码来查询与给定类别相对应的所有帖子。

// Get all posts by category
$posts = Category::find($categoryId)->posts;

在 TypeScript 中,我们也可以使用以下代码来查询与给定类别相对应的所有帖子。

// Get all posts by category
const posts = await Category.findByPk(categoryId, {
  include: [Post],
});

const relatedPosts = posts.posts;

这段代码将在 Category 表中查找具有 categoryId 的行,以及它们相关联的所有帖子行。注意这里我们使用了 Sequelize 提供的 findByPk 方法查找特定行,通过 { include: [Post] } 可以让 Sequelize 对 Post 模型进行预加载,以避免 N+1 查询问题。

结论

在上面的步骤中,我们演示了如何在 Laravel 和 TypeScript 中使用多对多关系来按类别获取相关帖子。我们也使用了以下工具和最佳实践:

  • Laravel 框架
  • Sequelize ORM
  • 迁移文件
  • Eloquent 模型
  • TypeScript 类型检查
  • 利用 Sequelize 预加载来避免 N+1 查询问题

这里的示例只是一个简单的演示,实际上您可能会遇到更复杂的查询需求。但是,掌握了这些基础知识之后,您已经具备处理大多数多对多关系的能力。