The first step is to get your local development environment set up for your WordPress site. There are quite a few ways I have setup this environment in the past. For the last year or so, I’ve been using Wodby’s Docker-based WordPress Stack with its many options.

Docker Compose

Update the docker-compose.yml volume paths to mount the codebase to ./wordpress instead of the root of the site folder. This step is needed for the build configuration. For example, replace ./:/var/www/html with ./wordpress:/var/www/html.

...
volumes:
- ./wordpress:/var/www/html

Create a volume definition to persist the mysql data. At the bottom of the docker-compose.yml file, uncomment and update the volumes node. For example, replace #volumes: with the following:

volumes:
mysql:

Update the mariadb service to use the mysql volume. For example, under the mariadb service, uncomment and update the volumes node. For example:

services:
mariadb:
...
volumes:
- mysql:/var/lib/mysql

With Docker running, from the site directory run docker-compose up -d to start containers.

If you’re in Windows and get the following error:

ERROR: for traefik Cannot create container for service traefik: Mount denied: The source path \\\\var\\\\run\\\\docker.sock:/var/run/docker.sock is not a valid Windows path

This worked for me using Cygwin. Before running docker-compose up -d, run export COMPOSE_CONVERT_WINDOWS_PATHS=1. For PowerShell, use $Env:COMPOSE_CONVERT_WINDOWS_PATHS=1 More info: github.com/docker/for-win/issues/1829

The WordPress install page should appear. After selecting your language, on the following screen, if using the default settings in .env file, enter wordpress for Database Name, Username and Password. The Database Host value is the service name defined in the docker-compose.yml, e.g., mariadb.

WordPress Install – Database Configuration

Custom Theme

To demonstrate getting a custom theme into the build, let’s make a copy of twentyseventeen and customize it.

style.css

Login to the site and activate mytheme to see the change to the site title font size when you adjust the width of the browser below 768 pixels wide.

Plugins

To demonstrate the inclusion of plugins in the docker build, install a plugin that will be included in the codebase. For example, I like the Yoast SEO plugin. Instead of installing it using the dashboard, download and extract it. Copy the wordpress-seo folder into the wordpress/wp-content/plugins folder. You can verify the installation by logging into the site dashboard and inspecting the plugins page.

Docker Image

The docker image we build for staging and production will be based off the official WordPress image and will only need our themes, plugins and any other changes from the development environment. I created some build scripts to accept some parameters and copy files from the development environment into respective staging and production build folders.

Aside from making the container configuration easier to understand, Docker Compose coordinates the creation, start and stop of the containers used together in the environment.

The environment has multiple sites served on various ports including at least one WordPress site, a phpmyadmin site and mysql. For virtual host names, nginx-proxy is being used for containers with virtual host environment properties set in their docker compose data. Additionally, the mysql db container is accessible from the host at 127.0.0.1:8001

Create this docker compose yaml file in the projects root directory with the nginx-proxy configuration.

nginx-proxy.yml

Create this docker compose yaml file for the WordPress stack. This includes the linked MariaDB database and phpMyAdmin containers from their official repositories. Xdebug is not included in the official WordPress image on Docker Hub and will not be included in this configuration since it is using unmodified images. Adding xdebug and rebuilding the image is covered on page two.

hosts

Create the Containers

Create new nginx-proxy and WordPress containers using the up command with docker-compose.

docker-compose -f nginx-proxy.yml -f wp.yml up

The -f flags specify the compose files to use. Multiple compose files are combined into a single configuration. This multiple file solution is for demonstration purposes. Here is a single file example that can be run without a file flag.

Stop Containers

Stop the containers without removing them.

docker-compose -f wp.yml -f nginx-proxy.yml stop

Start Containers

Start the stopped containers. Include the nginx-proxy.yml first so when the WordPress containers are started the virtual hosts can be dynamically configured.

docker-compose -f nginx-proxy.yml -f wp.yml -f start

If you have restarted your computer and another process is using the nginx-proxy port, e.g., 80, you will need to halt that process before starting the container.

Shutdown Containers

Shutdown the environment using the down command. If your data is not stored in a volume, it will not persist since this will remove the containers.

docker-compose -f wp.yml -f nginx-proxy.yml down

The next page covers adding Xdebug and configuring VS Code for remote debugging.

Development

The original proof of concept details building the WordPress plugin, installing Vue.js, Webpack and configuring for development. Also included is information on creating the front end slug where the Vuejs app will run. The end product is a simple form to submit new posts from a custom WordPress page template. It is recommended that you read these aforementioned prerequisites:

List Posts

App.vue

Above the form, replace the hardcoded heading text with a placeholder to render heading data that will be adding to the data model.

Below the form, add this markup to display the messages for loading and errors along with the list element for the posts. Note the vue.js v-if attributes to control visibility of the elements depending on the data model values. This is called conditional rendering.

Note that an ellipsis … in the code snippets are not a part of the code and are there only to denote code that is being skipped and not applicable to the example. To view the entire file, examine the source code.

In the App.vue component script block, update the data model for the new elements.

App.vue

Development Build

In your CLI, build in development mode which enables watch on the files and incrementally recompiles as needed. This is faster than a prodcution build. Additionally, this unminified build is compatible with the Vue DevTools extension for Chrome for debugging and object inspection.

npm run dev

After the build is completed and watch is running, reload the page. Submit a new post to make sure it is working and gets added to the list.

Edit / Add Posts

In the markup that lists posts, the titles link contains a @click='editPost(post) attribute to call the editPost method passing it the post object. Insert the editPost method to accept the post object from the list and set the properties of the data model. Since this is a simple proof of concept, we are not comparing the post against the version on the server to make sure it is hasn’t been modified since the last fetch. Note that the heading property is being set as well to display the appropriate text.

When you save the changes to the App.vue file, the watch detects the changes and incrementally rebuilds the code. Refresh the browser, select a post from the list and verify that it is working as expected.

We need a way to Submit New Post without reloading the page. Add this markup to the bottom of the form under the submit input so we have a link that will call a newPost method.

This post is a simple proof of concept for using the new WordPress REST API to submit a new post draft from the front end. The form and user inputs are built using the Vue.js framework and vue-cli to create a simple Webpack build configuration.

Class for Front End Page Request

In the class of the plugin entry point file above, the includes function contains a request type check. When the request is made from the front end, include the class file for the page. Let’s create that class file now, for example,

touch class-api-vpoc-page.php

Add the following php code to create the class. The constructor method is called on the newly-created class object where we are subscribing to events using hooks.

The action hook is called during the page processing event for script loading, at this point, call our page_scripts function to load the app javascript.

The filter hook is called during data processing, when the content is being loaded, call our page_content function to create the app bootstrap element.

I wanted a front-end page template to play around with the new REST API that is now in WordPress 4.7 core. A custom page template gives me the latitude I want at this stage of development, so here is how I did it.

Create the Template File

There are a couple of ways to do this.

Option 1

Clone and edit the existing page.php template. Open page.php in an editor and Save As…api-test.php. Remove the guts of the page containing the while loop for iterating through and displaying posts. For example, my clone of wp-content/themes/twentyseventeen/page.php saved as api-test.php looks like this:

The original page meta data properties in the comment at the top have been removed.

Option 2

Start from scratch with a completely blank slate. Create a new php file in the root of your active theme with a single line of code to set the Template Name meta data. Now we have a new custom template that can selected for pages when editing.

api-test.php

<?php /* Template Name: api-test */ ?>

Option 3

This is nearly the same as option 1, only with addition of the meta data property to set the Template Name property like option 2.

Clone and edit the existing page.php template. Open page.php in an editor and Save As… api-test.php. Edit api-test.php replacing the meta data at the top with the Template Name property used in the blank slate option above. Then remove the guts of the page containing the while loop for iterating through and displaying posts. For example, my clone of wp-content/themes/twentyseventeen/page.php saved as api-test.php looks like this:

Resources

These Sass modules make customizing the style.css a lot easier for the new business focused Twenty Seventeen default theme for WordPress 4.7 released a couple weeks ago.

The individual Sass modules in this repository represent each of the WordPress Twenty Seventeen style.css stylesheet numbered and annotated sections. The responsive media queries have also been split out into modules for each of the 5 breakpoints. As was done with the Twenty Sixteen Sass modules, all of the fonts and colors have been converted into Sass variables for quick and easy customization.

Custom Dashboard

Custom Homepage

Clone and edit the existing theme index.php template. Open index.php in an editor and Save As…home.php. This file will automatically take over the themes index.php, and it will be displayed as the homepage.

Development Environments

Vagrant

Laravel Homestead
If you develop Laravel apps on Homestead, you can also install WordPress on the same Virtual Machine. This example Homestead.yaml file has a configuration for 4 different sites. Two Laravel sites, a WordPress site and a phpmyadmin site.

Vagrant configuration designed for development of WordPress plugins, themes, or websites.

I recently created individual Sass modules for each of the WordPress Twenty Sixteen style.css stylesheet numbered and annotated sections. Additionally, the fonts and colors have been converted into Sass variables. All of this makes customizing this theme easier.

I wanted an efficient way to load page or post specific stylesheets and or scripts which lead me to see if I could utilize custom fields for this. Using custom fields combined with wp_enqueue_style and wp_enqueue_script worked perfectly. This solution allows me to link css or javascript files for only the posts or pages I want.

1. Add a couple of custom fields, one for styles and one for scripts to a page using the editor:

3. After the last stylesheet is queued for loading, add the code that checks for and loads our styles custom_field stylesheets. In this example, add the code after wp_style_add_data( ‘twentyfifteen-ie7’, ‘conditional’, ‘lt IE 8’ ); as shown here:

Handle Script Dependencies

A nice feature of the wp_enqueue_script function is that it allows us to pass in dependencies as a parameter. The optional dependencies parameter consists of an array of handles that map to javascript files. To apply this feature to our scripts custom field code, we need to create a $deps array that will retrieve optional handles added to the custom field value. Replace the code block at the bottom of function twentyfifteen_scripts() as follows:

7. Now the bn_scripts custom field can be updated to include dependencies. List the dependency handles after the script separated by a comma as shown below.

WordPress editor – bn_scripts custom field dependencies added

More often than not jQuery will already be loaded. However, if your script is dependent upon jQuery you should add its handle to the dependencies comma separated list in the bn_scripts custom field value. wp_enqueue_script prevents double loading of scripts and their dependencies.

Given the default theme location, if you view source of the page that has the custom fields added and search for tree.css or tree.js, they should be linked to /wp-content/themes/twentyfifteen/css/tree.css and /wp-content/themes/twentyfifteen/js/tree.js. Any dependencies will also be linked.

I have created a new WordPress starter theme for building custom themes designed for WordPress version 4.1 and later. The theme uses the Bourbon Sass library and it’s Neat semantic grid components for a lightweight and modular responsive design. The header and footer designs were taken from the Bourbon Refills collection. Also included are IcoMoon font icons which can be easily updated using the IcoMoon app. Gulp’s build system is used to compile and minify Sass and Javascript modules into optimized CSS and Javascript. Clone, fork or download this responsive starter theme at GitHub and modify it as you wish into the theme you want.

Menus

The theme contains four wp_nav_menu’s, the main menu supports nested drop downs. Below are desktop previews of these responsive menus which collapse as needed on mobile screen sizes.

Main Menu preview (header.php)

The footer contains three of the four registered wp_nav menus. Social links and terms menus are shown below. Also shown here above the footer is the pagination nav courtesy of WordPress – Twenty Fifteen. This is a new feature available in WordPress 4.1 and later.

Social and Terms Menu preview (footer.php)

Populating the social links menu is easy. All that is needed is a menu that contains custom links to social networks. The href attribute of the link is selected to determine which icon is rendered. Here is a snippet of the Sass that shows how this works:

This post shows how to combine and minify multiple javascript files in a WordPress theme into one javascript file. The benefit is a single request to a javascript file that has been compressed by minification instead of multiple request to larger javascript files.

package.json

The package.json file contains meta data about your app or module and it includes the list of dependencies to install from Node Package Manager (NPM) when running npm install. NPM is bundled with Node.js; if you have not done so already, install Node.js so you have it. Then create and save this file in your themes root directory, for example /wp-content/my-theme/package.json. Then when you run npm install, the package.json file is read and the respective node modules are installed. More information is available here.

file structure

Here is what the themes javascript file structure looks like for this example. The /js/src folder contains all of the individual javascript files for your theme. When you run grunt, these are all combined and minified into /js/main.js

Partial view of themes files showing location of javascript

functions.php

The functions.php file controls the loading of the themes javascript resources. In the functions.php file, the wp_enqueue_script() function links the script to the page. The pre-existing wp_enqueue_script() function calls are no longer valid since the javascript files have been moved to the /js/src/ folder. Here is an example of the code from the pre-existing functions.php that was linking the scripts:

Here is an example of the code from functions.php after making the changes to link /js/main.js instead. Since /js/src/deflist.js depends on jQuery, so does /js/main.js and the $deps array parameter is set to ‘jquery’. For more information, refer to the wp_enqueue_script function reference

This blog post addresses a common scenario — a local LAMP development environment on your Windows or OS X computer. You could use XAMPP on either Windows or OS X, MAMP on OS X or native Apache in OS X. Here, we will create a Linux virtual machine with Samba configured to share the Virtual Machine file system with the host computer. We will also create virtual hosts, install and configure WordPress and Xdebug.

First thing you will need is Virtual Machine software. For my Virtual Machine, I chose to install the free VMware Player. If your host operating system is OS X, you can install VirtualBox if you do not want to purchase VMware Fusion or Parallels. You could also use VirtualBox on a Windows host instead of VMware if you prefer.

Next, you will need to create a Linux virtual machine. I decided to Download Ubuntu Server 32 bit since it is compatible with the intel processor of my host computer.

Install SSH

After creating a new VM and installing Linux, time to get our dev environment setup. Install SSH so we can run commands from the host. Later we will use ssh to to tunnel the Xdebug connection from the VM back to the host.

Edit your hosts file in your host operating system to map to the virtual hosts you specified in the Apache config of the Linux virtual machine.

192.168.59.129 ubuntu.vm
192.168.59.129 wordpress.vm

Since we have set the hosts file to map 192.168.59.129 to ubuntu.vm, once you disconnect your current ssh session (Ctrl+D), you will need to use the host alias you specified in the hosts file to reconnect.

ssh jim@ubuntu.vm

Samba Network Share

You can use Samba to share the /var folder in you virtual machine.

# install Samba
$ sudo apt-get install samba

Linux system permissions take precedence over Samba permissions. For example if a directory does not have Linux write permission, setting samba writeable = Yes will not allow to write to shared directory / share.

phpMyAdmin

If phpMyAdmin is installed, you can use it to create the wordpress database as described in this next section. Read my earlier blog post if you need help doing this,
Mint LAMP Development Environment

In the browser, goto http://ubuntu.vm/phpmyadmin/. Select the Databases tab and under “Create new database”, enter in a database name such as “wordpress”, and select Create. Collation will automatically be assigned by MySQL when the database tables are created, during the WordPress installation.

When debugging from the host computer, use ssh to tunnel the debug-connection back to it.

# ssh remote port forwarding
ssh -R 9000:localhost:9000 jim@ubuntu.vm

Using the “-R” argument tells ssh to listen on TCP port 9000 on the ubuntu server and forward it back through the ssh connection to the TCP port specified (localhost:9000). So from Xdebug’s perspective on the Ubuntu server, it is talking to localhost on the local computer.

This post by Chris Coyier shows how to use jQuery inside a WordPress post. This helped me work around an Apache web server security configuration issue that was not allowing me to post SQL code snippets inside of my posts.

403 response when I try to post certain SQL code snippets:

Forbidden

You don’t have permission to access /wp-admin/post.php on this server.

First, follow the instructions in Chris’s post which basically has you modify the your themes header.php to load jQuery that is included with WordPress just before the wp_head() function call as follows.

Replace

<?php wp_head(); ?>;

With

<?php wp_enqueue_script("jquery");
wp_head(); ?>;

Next, create a htm file to hold SQL code snippets. The pre element id attribute allows for jQuery loading of individual fragments instead of the entire .htm file. Additional SQL code snippets can be added to this file each separated by a pre element with a unique id attribute: