Loading...
+880 1736 699819 Mon - Sat: 9:00 AM - 8:00 PM
Follow us:
Home Blog Article
Blog

Laravel Vue 3 Draft Post Save - WordPress JSON API

Laravel Vue 3 Draft Post Save - WordPress JSON API

 Laravel Migration & Model

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content')->nullable();
            $table->string('status')->default('draft'); // draft, published
            $table->foreignId('author_id')->constrained('users')->cascadeOnDelete();
            $table->timestamps();
        });
    }

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

//Model namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Post extends Model { use HasFactory; protected $fillable = [ 'title', 'content', 'status', 'author_id', ]; // Author relationship public function author() { return $this->belongsTo(User::class, 'author_id'); } }

Laravel Controller (API)

<?php
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Post;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class PostController extends Controller
{
    // Save draft
    public function saveDraft(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|string|max:255',
            'content' => 'nullable|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'message' => $validator->errors(),
            ], 422);
        }

        $post = Post::updateOrCreate(
            ['id' => $request->id], // update if ID exists
            [
                'title' => $request->title,
                'content' => $request->content ?? '',
                'status' => 'draft',
                'author_id' => Auth::id() ?? 1, // Auth user or default
            ]
        );

        return response()->json([
            'status' => 'success',
            'message' => 'Post saved as draft',
            'data' => [
                'id' => $post->id,
                'title' => $post->title,
                'content' => $post->content,
                'status' => $post->status,
                'author_id' => $post->author_id,
                'created_at' => $post->created_at,
                'updated_at' => $post->updated_at,
            ],
        ]);
    }
}

API Route

<?php
use App\Http\Controllers\Api\PostController;

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

Vue.js 3 Component

<?php
<template>
  <div class="p-4">
    <input v-model="title" placeholder="Post Title" class="border p-2 w-full mb-2"/>
    <textarea v-model="content" placeholder="Post Content" class="border p-2 w-full mb-2"></textarea>
    <button @click="saveDraft" class="bg-blue-500 text-white px-4 py-2 rounded">Save Draft</button>

    <div v-if="response" class="mt-4 p-2 border">
      <pre>{{ response }}</pre>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

const title = ref('');
const content = ref('');
const response = ref(null);

const saveDraft = async () => {
  try {
    const res = await axios.post('/api/posts/draft', {
      title: title.value,
      content: content.value,
    });
    response.value = res.data;
  } catch (err) {
    response.value = err.response?.data || err.message;
  }
};
</script>

<style scoped>
/* optional tailwind styling already used */
</style>

Features:

  1. Supports update draft if ID is provided.
  2. Returns JSON similar to WordPress.
  3. Status is fixed to "draft".
  4. Ready to integrate with Laravel Sanctum for auth.


Tags: Blog
Share this post

Encoderbase Team

Author

Articles and insights from the Encoderbase editorial team covering web development, software engineering, and digital solutions.

Enjoyed this article?

Get more articles like this delivered to your inbox — no spam, unsubscribe any time.

Link copied to clipboard!