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?

Day23 — 投稿作成APIを実装し、Reactから投稿できるようにする

Last updated at Posted at 2025-12-22

はじめに

Day22 では、

✅ 投稿一覧 API
✅ React で一覧表示

を実装しました。

今日はついに、

「データを作る」= Create

を実装します。

今日のゴール

・投稿作成 API を Laravel で実装する

・認証ユーザーに紐づいた投稿を保存する

・React から投稿を送信できる

・投稿後に一覧へ反映される

今回作る機能

・ログインユーザーのみ投稿可能

・タイトル・本文を送信

・投稿者は自動的に認証ユーザー

ルーティング定義

routes/api.php

Route::middleware('auth:api')->group(function () {
    Route::post('/posts', [PostController::class, 'store']);
});

PostController に処理を追加

use Illuminate\Http\Request;
use App\Models\Post;

public function store(Request $request)
{
    $request->validate([
        'title' => 'required|string|max:255',
        'body' => 'nullable|string',
    ]);

    $post = Post::create([
        'title' => $request->title,
        'body' => $request->body,
        'user_id' => auth('api')->id(),
    ]);

    return response()->json([
        'status' => 'success',
        'data' => $post
    ], 201);
}

なぜ user_id をフロントから受け取らない?

❌ フロント送信

{
  "user_id": 999
}

👉 なりすまし可能

✅ サーバで決定

'user_id' => auth('api')->id()

Post モデル設定

protected $fillable = [
    'title',
    'body',
    'user_id',
];

Postman で動作確認

POST /api/posts
Authorization: Bearer xxx
{
  "title": "新しい投稿",
  "body": "本文です"
}

React 側:投稿フォーム

import { useState } from 'react';

const PostForm = ({ onCreated }) => {
  const [title, setTitle] = useState('');
  const [body, setBody] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();

    const token = localStorage.getItem('token');

    const res = await fetch('http://localhost/api/posts', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`
      },
      body: JSON.stringify({ title, body })
    });

    const data = await res.json();

    if (data.status === 'success') {
      setTitle('');
      setBody('');
      onCreated(data.data);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        placeholder="タイトル"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <textarea
        placeholder="本文"
        value={body}
        onChange={(e) => setBody(e.target.value)}
      />
      <button type="submit">投稿</button>
    </form>
  );
};

export default PostForm;

投稿後に一覧を更新する

const [posts, setPosts] = useState([]);

const addPost = (newPost) => {
  setPosts([newPost, ...posts]);
};
<PostForm onCreated={addPost} />

UX 的に良いポイント

・投稿後リロード不要

・即座に一覧へ反映

・SPA らしい操作感

よくあるエラー

❌ 422 Validation Error

・title 未入力

・文字数オーバー

👉 フロントで表示改善すると良い

❌ 401 Unauthorized

・トークン期限切れ

・Authorization ヘッダー忘れ

実装のポイント

・認証ユーザーに必ず紐づける

・バリデーションは必須

・レスポンス形式を揃える

・フロントは成功だけを見ればOK

今日のまとめ

・投稿作成 API を実装した

・認証ユーザーの投稿を保存できた

・React から投稿できた

・CRUD の「C」が完成した

次回 Day24

いよいよ CRUD 完成です。

Day24 — 投稿編集・削除APIを実装し、権限制御を入れる

「誰でも編集できる」を防ぎます。

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?