In this lesson, let's show a column from the relationship in the posts table. We will add a category for every post.
First, we need to create a Category
model and migration.
php artisan make:model Category -m
database/migrations/xxxx_create_categories_table.php:
public function up(): void{ Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps(); });}
app/Models/Category.php:
class Category extends Model{ protected $fillable = [ 'name', ];}
Next, we need to create a migration to add a category_id
column to the Posts
table.
php artisan make:migration "add category to posts table"
database/migrations/xxxx_add_category_to_posts_table.php:
public function up(): void{ Schema::table('posts', function (Blueprint $table) { $table->foreignId('category_id')->after('content')->constrained(); });}
In the model, we also need a relationship.
app/Models/Post.php:
use Illuminate\Database\Eloquent\Relations\BelongsTo; class Post extends Model{ protected $fillable = [ 'title', 'content', 'category_id', ]; public function category(): BelongsTo { return $this->belongsTo(Category::class); } }
Now we don't want to make a N+1 issue. So in the PostController
we need to eager load categories.
app/Http/Controllers/Api/PostController.php:
class PostController extends Controller{ public function index() { $posts = Post::with('category')->paginate(10); return PostResource::collection($posts); }}
We are using API Resources. So it means we need to category to it, otherwise, API won't return the category.
app/Http/Resources/PostResource.php:
class PostResource extends JsonResource{ public function toArray(Request $request): array { return [ 'id' => $this->id, 'title' => $this->title, 'content' => substr($this->content, 0, 50) . '...', 'category' => $this->category->name, 'created_at' => $this->created_at->toDateString() ]; }}
All that is left to show the category in the frontend. Let's show it near the title.
resources/js/components/Posts/Index.vue:
<template> <div class="overflow-hidden overflow-x-auto p-6 bg-white border-gray-200"> <div class="min-w-full align-middle"> <table class="min-w-full divide-y divide-gray-200 border"> <thead> <tr> // ... <th class="px-6 py-3 bg-gray-50 text-left"> <span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Title</span> </th> <th class="px-6 py-3 bg-gray-50 text-left"> <span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Category</span> </th> // ... </tr> </thead> <tbody class="bg-white divide-y divide-gray-200 divide-solid"> <tr v-for="post in posts.data"> // ... <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900"> {{ post.title }} </td> <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900"> {{ post.category }} </td> // ... </tr> </tbody> </table> <TailwindPagination :data="posts" @pagination-change-page="getPosts" class="mt-4" /> </div> </div></template> // ...
That's it. We now show a category in the posts table.