Laravel CRUD Using WordPress REST API with JWT Tutorial

Reading Time: 14 minutes
481 Views

Creating a Laravel CRUD application that interacts with WordPress through its REST API using JWT authentication offers a robust solution for managing WordPress content from an external application.

In this tutorial, we’ll explore the process of integrating Laravel’s CRUD operations with WordPress’s RESTful API, securing the communication using JSON Web Tokens (JWT). You will see the complete guide to create WordPress posts, list posts and their update operations with Laravel.

WordPress’s REST API provides a way to access and modify WordPress content externally, while JWT authentication ensures secure and authenticated communication between Laravel and WordPress.

Read More: How To Upgrade My Laravel Project to Latest Version?

Let’s get started.

WordPress Configuration

Set up a WordPress setup and configure the REST API with JWT authentication Using plugins like “JWT Authentication for WP REST API

>> Install this plugin and activate.

Configure the JWT Secret Key

The JWT needs a secret key to sign the token this secret key must be unique and never revealed.

To add the secret key edit your wp-config.php file and add a new constant called JWT_AUTH_SECRET_KEY

define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key');

Configure CORS Support

To enable the CORs Support edit your wp-config.php file and add a new constant called JWT_AUTH_CORS_ENABLE

define('JWT_AUTH_CORS_ENABLE', true);

Generate JWT Auth Token (Use in Calling APIs)

Once you install plugin, you will get a route by which we can get JWT authentication token value. But we need to pass username and password while calling that.

Auth API URL,

http://example.com/wp-json/jwt-auth/v1/token

Example,

Copy JWT Auth token value for calling REST APIs.

Read More: How To Integrate ChatGPT API in Laravel 10 Tutorial

Laravel Installation

Open terminal and run this command to create a laravel project.

composer create-project laravel/laravel myblog

It will create a project folder with name myblog inside your local system.

To start the development server of laravel –

php artisan serve

URL: http://127.0.0.1:8000

Assuming laravel already installed inside your system.

Application Basic Variables Settings

Open .env file from project folder,

WP_JWT_AUTH_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciO..."

WP_JSON_POST_URL="https://yourwordpresssite.com/wp-json/wp/v2/posts"

Change your keys values according to your application.

Resource Routes Setup

Open web.php file from /routes folder.

//...
use App\Http\Controllers\PostController;

Route::resource('posts', PostController::class);
//...

Setup CRUD Controller

Back to project terminal and run this command into it,

php artisan make:controller PostController

It will create a PostController.php file inside /app/Http/Controllers folder.

Controller file contains these methods for,

  • index(): To list all posts
  • create(): To open layout to create post
  • store(): To save post data to wordpress database
  • edit(): Open edit layout to update post
  • update(): Update method to update existing data of post
  • destroy(): Delete post method

Open file and write this code into it,

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class PostController extends Controller
{
    // Page: Post list
    public function index()
    {
        $response = Http::get(getenv("WP_JSON_POST_URL"));

        if ($response->successful()) {

            $posts = $response->json();

            $postArr = collect($posts)->map(function ($post) {
                return [
                    'id' => $post['id'],
                    'title' => $post['title']['rendered'],
                    'content' => $post['content']['rendered'],
                    // Add more fields as needed
                ];
            })->toArray();

            return view('post-list', compact('postArr'));
            
        } else {
            // Handle error if the request was not successful
            $error = $response->status(); // Get the HTTP status code
            // You can also fetch error messages or details using $response->body()
        }
    }

    // Page: Post create
    public function create(){

        return view('post-create');
    }

    // Function: Post create
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
            'status' => 'required',
        ]);
        
        $response = Http::withHeaders([
            'Authorization' => 'Bearer '.getenv("WP_JWT_AUTH_TOKEN"), // Replace with your authentication method and token
            'Content-Type' => 'application/json',
        ])
            ->post(getenv("WP_JSON_POST_URL"), [
                'title' => $request->title,
                'content' => $request->content,
                'status' => $request->status, // Set the post status (publish, draft, etc.)
                // Add other post fields as needed
            ]);

        // Check the response
        if ($response->successful()) {
            
            $post = $response->json(); // Retrieve the created post data

            return redirect()->route('posts.index')->with('success','Post has been created successfully.');

        } else {
            // Handle errors
            $error = $response->json();
            
            return redirect()->route('posts.create')->with('error','Failed to create post');
        }
    }

    // Page: Update post
    public function edit(Request $request)
    {
        $postId = $request->post;

        $url = getenv("WP_JSON_POST_URL") . "/" . $postId;

        $response = Http::get($url);

        if ($response->successful()) {
            $post = $response->json();
            // Process the retrieved post data as needed
            return view('post-edit',compact('post'));
        } else {
            // Handle the error response
            return $response->status();
        }
    }

    // Function: Update post
    public function update(Request $request)
    {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
            'status' => 'required',
        ]);
        
        // ID of the post to update
        $postId = $request->post; // Replace with the actual post ID you want to update

        // Data to be updated (example: updating the post title)
        $updateData = [
            'title' => $request->title, // Replace with the new title
            'content' => $request->content,
            'status' => $request->status
        ];

        $response = Http::withHeaders([
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer '.getenv("WP_JWT_AUTH_TOKEN"),
        ])->put( getenv("WP_JSON_POST_URL") . "/" . $postId, $updateData);

        if ($response->successful()) {
            // Post updated successfully
            $updatedPost = $response->json();

            return redirect()->route('posts.index')->with('success','Post Has Been updated successfully');
        } else {
            // Handle error if the request was not successful
            $error = $response->status(); // Get the HTTP status code

            return redirect()->route('posts.index')->with('error','Failed to update post');
        }
    }

    public function destroy(Request $request)
    {
        // ID of the post to delete
        $postId = $request->post; // Replace with the actual post ID you want to delete

        $response = Http::withHeaders([
            'Content-Type' => 'application/json',
            // Add authorization headers if needed for authentication
             'Authorization' => 'Bearer '.getenv("WP_JWT_AUTH_TOKEN"),
        ])->delete(getenv("WP_JSON_POST_URL") . "/" . $postId);

        if ($response->successful()) {
            // Post deleted successfully
            $deletedPost = $response->json();

            return redirect()->route('posts.index')->with('success','Post has been deleted successfully');
        } else {
            // Handle error if the request was not successful
            $error = $response->status(); // Get the HTTP status code
            
            return redirect()->route('posts.index')->with('success','Failed to delete post');
        }
    }
}

Next, we need to create front-end view files for CRUD operation.

Setup CRUD Blade Layout Views

Create these blade template files inside /resources/views folder,

  • post-list.blade.php
  • post-create.blade.php
  • post-edit.blade.php

Read More: How To Validate Image Upload in Laravel 10 Example

Open each file and write these code

Post list template file: “post-list.blade.php”,

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Laravel CRUD Using WordPress REST API with JWT Tutorial</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>

<body>
    <div class="container mt-2">
        <div class="row">
            <div class="col-lg-12 margin-tb">
                <div class="pull-left">
                    <h3>Laravel CRUD Using WordPress REST API</h3>
                </div>
                <h4 class="text-center">Post List</h4>
                <div class="pull-right mb-2" style="float: right;">
                    <a class="btn btn-success" href="{{ route('posts.create') }}">Create Post</a>
                </div>
            </div>
        </div>
        @if ($message = Session::get('success'))
        <div class="alert alert-success">
            <p>{{ $message }}</p>
        </div>
        @endif
        <table class="table table-bordered">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Post Title</th>
                    <th>Post Content</th>
                    <th width="280px">Action</th>
                </tr>
            </thead>
            <tbody>
                @foreach ($postArr as $post)
                <tr>
                    <td>{{ $post['id'] }}</td>
                    <td>{{ $post['title'] }}</td>
                    <td>{{ substr($post['content'], 0, 100) }}</td>
                    <td>
                        <form action="{{ route('posts.destroy',$post['id']) }}" method="Post">
                            <a class="btn btn-primary" href="{{ route('posts.edit',$post['id']) }}">Edit</a>
                            @csrf
                            @method('DELETE')
                            <button type="submit" onclick="return confirm('Are you sure want to delete?')" class="btn btn-danger">Delete</button>
                        </form>
                    </td>
                </tr>
                @endforeach
            </tbody>
        </table>
    </div>
</body>

</html>

Create Post template file: “post-create.blade.php”,

It will give us an interface such as for Title, Content and Status to create post.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Laravel CRUD Using WordPress REST API with JWT Tutorial</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>

<body>
    <div class="container mt-2">
        <div class="row">
            <div class="col-lg-12 margin-tb">
                <div class="pull-left">
                    <h3>Laravel CRUD Using WordPress REST API</h3>
                </div>
                <h4 class="text-center">Add Post</h4>
                <div class="pull-right" style="float: right;">
                    <a class="btn btn-primary" href="{{ route('posts.index') }}"> Back</a>
                </div>
            </div>
        </div>
        @if(session('status'))
        <div class="alert alert-success mb-1 mt-1">
            {{ session('status') }}
        </div>
        @endif
        <form action="{{ route('posts.store') }}" method="POST">
            @csrf
            <div class="row">
                <div class="col-xs-12 col-sm-12 col-md-12">
                    <div class="form-group">
                        <strong>Title:</strong>
                        <input type="text" name="title" class="form-control" placeholder="Post Title">
                        @error('title')
                        <div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
                        @enderror
                    </div>
                </div>
                <div class="col-xs-12 col-sm-12 col-md-12">
                    <div class="form-group">
                        <strong>Content:</strong>
                        <input type="text" name="content" class="form-control" placeholder="Post Content">
                        @error('content')
                        <div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
                        @enderror
                    </div>
                </div>
                <div class="col-xs-12 col-sm-12 col-md-12">
                    <div class="form-group">
                        <strong>Status</strong>
                        <select name="status" class="form-control">
                            <option value="">-- Status --</option>
                            <option value="draft">Draft</option>
                            <option value="publish">Publish</option>
                        </select>
                        @error('status')
                        <div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
                        @enderror
                    </div>
                </div>

                <button type="submit" class="btn btn-primary ml-3">Submit</button>
            </div>
        </form>
    </div>
</body>

</html>

Update Post template file: “post-edit.blade.php”,

It will give us an interface such as for Title, Content and Status to update post.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Laravel CRUD Using WordPress REST API with JWT Tutorial</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>

<body>
    <div class="container mt-2">
        <div class="row">
            <div class="col-lg-12 margin-tb">
                <div class="pull-left">
                    <h3>Laravel CRUD Using WordPress REST API</h3>
                </div>
                <h4 class="text-center">Edit Post</h4>
                <div class="pull-right" style="float: right;">
                    <a class="btn btn-primary" href="{{ route('posts.index') }}">
                        Back</a>
                </div>
            </div>
        </div>
        @if(session('status'))
        <div class="alert alert-success mb-1 mt-1">
            {{ session('status') }}
        </div>
        @endif
        <form action="{{ route('posts.update',$post['id']) }}" method="POST">
            @csrf
            @method('PUT')
            <div class="row">
                <div class="col-xs-12 col-sm-12 col-md-12">
                    <div class="form-group">
                        <strong>Title:</strong>
                        <input type="text" name="title" value="{{ $post['title']['rendered'] }}" class="form-control"
                            placeholder="Post Title">
                        @error('name')
                        <div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
                        @enderror
                    </div>
                </div>
                <div class="col-xs-12 col-sm-12 col-md-12">
                    <div class="form-group">
                        <strong>Content:</strong>
                        <input type="text" name="content" value="{{ $post['content']['rendered'] }}" class="form-control"
                            placeholder="Content">
                        @error('address')
                        <div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
                        @enderror
                    </div>
                </div>
                <div class="col-xs-12 col-sm-12 col-md-12">
                    <div class="form-group">
                        <strong>Status:</strong>
                        <select name="status" id="status" class="form-control">
                            <option value="">-- Status --</option>
                            <option {{ $post["status"] == "draft" ? "selected" : "" }} value="draft">Draft</option>
                            <option {{ $post["status"] == "publish" ? "selected" : "" }} value="publish">Publish</option>
                        </select>
                        @error('address')
                        <div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
                        @enderror
                    </div>
                </div>

                <button type="submit" class="btn btn-primary ml-3">Submit</button>
            </div>
        </form>
    </div>
</body>

</html>

Application Testing

Run this command into project terminal to start development server,

php artisan serve

URL: http://127.0.0.1:8000/posts

Lists Post,

It will list all posts of wordpress.

Create Post,

When you click on Create Post button, it will open layout to create post.

Update Post,

When you click on Edit button in List Post page, it will open layout to update post with existing data

Delete Post

When click on Delete button of List Post page,

WordPress backend admin panel for Posts data,

That’s it.

We hope this article helped you to learn about Laravel CRUD Using WordPress REST API with JWT Tutorial Example in a very detailed way.

Online Web Tutor invites you to try Skillshike! Learn CakePHP, Laravel, CodeIgniter, Node Js, MySQL, Authentication, RESTful Web Services, etc into a depth level. Master the Coding Skills to Become an Expert in PHP Web Development. So, Search your favourite course and enroll now.

If you liked this article, then please subscribe to our YouTube Channel for PHP & it’s framework, WordPress, Node Js video tutorials. You can also find us on Twitter and Facebook.