Using WordPress as API for Laravel (1) – WordPress setup

Nowadays, we mainly build custom websites, webshops and web apps using Laravel, a great framework with a lot of flexibility. Many of those websites have info pages or blog posts where the owners/administrators are in charge of the content themselves. We usually add a wysiwyg editor to the admin panel so our customers are able to create and edit the content of these pages.

We tried different plugins to incorporate wysiwyg editors, but we were never fully happy with the result: The functionality is often too limited, it’s easy to mess up the markup and layout of the page and occasionally, the wysiwyg plugin had some issue with other javascript on the page.

In the past, we mainly developed our websites using WordPress. Although WordPress is no longer our default framework of choice, the admin panel lends itself perfectly to create pages and posts, keep track of revisions, structure posts using categories and tags, manage media like file uploads and handle comments on blog posts.

Would it not be cool to use WordPress as a headless CMS and combine it with the flexibility of Laravel to build custom websites and web apps?

WordPress as API for Laravel

Our personal cycling blog

Besides our daily job as a web developer, we do a lot of cycling. We have a blog where we write about our adventures. The blog was set up in WordPress five years ago and would benefit from a major update. It had an outdated design, the performance was bad and the user experience could be greatly improved. We would like to develop the new cycling blog in Laravel, because it gives us the flexibility to add new (custom) features in the future.

However, in five years time we wrote a lot of stories which are all in the WordPress system. We would like to keep them in WordPress, because migrating them is a lot of work and we like the WordPress interface to create and edit the posts. And with the recent release of WordPress 5.0, editing posts is even more intuitive.

With this in mind, this project is the ideal candidate to explore the use of WordPress as an API for Laravel. The first step is to display the existing contents of our WordPress blog in Laravel.

Options to export data from WordPress

We considered three options to transfer data from WordPress to Laravel.

  1. Using the WP REST API. Since version 4.7, the REST API is part of the WordPress core. This makes it easy to extract data. It basically means that we use WordPress as a headless CMS, because all we need is the API and admin panel.
  2. Using corcel, which is a php package that contains wrappers to easily extract posts and other post types from a WordPress database.
  3. Sync data from a WordPress database to a custom database using a scheduled command. This setup is also chosen by Laravel news.

Although all three options seem suitable, we chose the first one. We didn’t choose Corcel, because it would be an additional dependency of an external package. For option 3 we had to write some kind of syncing script. Additionally, data is synced only at predefined times, so new blog posts or changes in existing ones are not directly visible. This doesn’t fit our normal workflow, where we write a post, inspect it visually, and make some changes. And when the WordPress core or one of its plugins receives an update, this may lead to changes in the WordPress database that should also be reflected in our syncing script.

Using the WordPress API seemed the most future proof option. We considered that using WordPress and its API as is, changes in the WordPress core would either not affect the API, or will be announced in case of breaking changes. Therefore, WordPress updates shouldn’t lead to a breakdown of our blog.

Changing the domain

We have an existing WordPress blog, and we now want to use this as a headless CMS, so we have to make some modifications. The blog was originally at train-mee.nl, but in the new setup this will be the domain for the Laravel website. However, the WordPress admin panel should still be available and needs another domain, e.g. api.train-mee.nl.

Hence, we moved our existing WordPress blog to this new domain. To make the blog working, we had to modify some fields in the wp_options table of the WordPress database: Look for the fields ‘siteurl’ and ‘home’ and adjust the values to the new domain name.

WordPress plugins

We like to use as few plugins as possible. All plugins that were used for the public part of the old blog can now be removed, because we will build the public part ourselves in Laravel. For example, in our cycling blog we used a WordPress plugin to display sociable buttons and to avoid spam via the contact forms. Those are no longer needed. Some plugins are still important or useful, and we will discuss some of them below.

Security

By default, the api routes of WordPress are publicly accessible for everyone. This is not desirable, because we only want to allow authorized users to extract data via the API. We use the ithemes security plugin to block the api routes for unauthorized users and protect the rest of the WordPress system. To manage access to the REST API, go the section ‘WordPress tweaks’ and scroll down to REST API and choose for ‘limited access’.

OAuth2 authentication

With limited access to the API endpoints, we need some way to authorize our Laravel app, because the Laravel app should display the posts that we wrote in the WordPress app. Although WordPress comes with a REST API, Oauth authentication is not included by default at the time of writing. Luckily, there is a plugin which handles this: WP OAuth Server. The configuration of the plugin will be described in the follow-up posts, where we make the connection between Laravel and WordPress.

Custom fields

The Advanced Custom Fields plugin is used to add additional (custom) fields to posts or (custom) post types. Those fields are not included in the API response by default. If you want the WordPress API to return those fields, you need another plugin: ACF-to-REST-API.

Installation is simple and the plugin automatically adds the custom fields to the API response. However, there is one thing to take care of. The plugin creates an extra endpoint to retrieve the advanced custom fields of a post (without the default fields) without authentication. Unfortunately, this endpoint is not protected by the ithemes security plugin.

You can find this endpoint under settings > permalinks (section ACF to REST API). In my opinion, the best option is to block this url on your web webserver, because it is not used in this setup. How to do this depends on your webserver. We use nginx, so we modify the nginx configuration file for the WordPress app. Go to the server block and add the following code:

location /wp-json/acf/v3 {
    deny all;
}

Custom post types

Another plugin that is often used in WordPress is the custom post types plugin. In our cycling blog we have a post type ‘mountain’ that includes the statistics of mountains that we climbed, like length, steepness and altitude of the top and a description.

Those custom post types (including its custom fields) can be retrieved by the REST API when you have the settings correct. Go to the CPT UI section of the WordPress admin, select the post type you want to include in the API and scroll down to settings. Set the ‘show in REST API’ to yes, and choose a REST API base slug in the field below. This slug will be used in the API endpoints for this custom post type.

Now, the same endpoints are available for custom post types as for the default entities like posts and pages. We will discuss the end points in more detail in one of the follow-up posts, but the endpoints are the typical REST endpoints to retrieve, edit and update posts, pages, or custom post types.

Making WordPress headless

We will make the public part of the blog ourselves in Laravel. This means we don’t need the public part of our WordPress system at api.domainname.com.

To hide the public parts of the WordPress system, we apply a blank theme. Creating a blank theme is easy. First, create a new folder called ‘blank’ in the wp-content/themes directory. In this new directory, add three files:

index.php

<meta content="0; URL='https://domainname.com'" http-equiv"refresh">

<!-- just in case the meta tag is not read properly, here is plan B: a JS redirect -->
<script type="text/javascript">
  window.location = 'https://domainname.com';
</script>

style.css

/*
Theme Name: blank
Author: Somebody
*/

functions.php
Here we will add some methods that will modify the response of the REST API. This will be described in later parts of this series.

The last step is to go to the themes section in the WordPress admin, where the new blank theme should now be visible. Activate the blank theme and you made WordPress a headless CMS.

Summary

By following these steps, we made the WordPress website a headless CMS which is now ready to serve as an API for our new Laravel website. In the next post, we will describe how to connect the Laravel app to WordPress and setup the authentication. Then, we will describe how to retrieve and display data from WordPress in the Laravel website.

Meanwhile, we already finished the upgrade of our cycling blog, so if you’re interested have a look at Train-mee (it’s in dutch only).


Mijn Twitter profiel Mijn Facebook profiel
Leonie Derendorp Webdeveloper and co-owner of PLint-sites in Sittard, The Netherlands. I love to create complex webapplications using Laravel! All posts
View all posts by Leonie Derendorp

4 thoughts on “Using WordPress as API for Laravel (1) – WordPress setup

  1. Klaas

    Hi Leonie, nice article. I also consider to dump my own CMS for WordPress. Question: do you upload the WordPress files to a completely different folder on the server? I normally combine Laravel with my own CMS (Still not laravel based) and decide what to show based on the subdomain in use. I assume you are using a different root folder for the subdomain?

    Reply
    1. Leonie Derendorp Post author

      Hi Klaas, thanks! I upload the WordPress files to the default wp-content/uploads folder and retrieve them in the Laravel app. I will describe this in more detail in the third part of this blog series, which will be ready in the coming weeks.

      Reply
  2. Roshan

    Hi Leonie, i read your article completely.nice article . I want to launch a new website, and there may be questions where i need your help.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *