You hate WordPress?
This can reunite you!


WordPress

WordPress and the love of developers!

Everyone knows WordPress, and everyone knows that developing with WordPress is a pain is the ass ( If not, I can’t do anything for you 🙁 ).
The most common answer about people loving WordPress so much is: extensibility.
From the past years WordPress provide a lots of themes and plugins and this is why people will choose WordPress compared to other CMS.

However WordPress as a big dark sides for developers, it use old and deprecated stuff, do not use a template engine for rendering views, and so on about many things…

It’s 2016, why not using new features?

Let’s now see how we can integrate in WordPress some cool stuff, already used by many developers.

Composer

Composer is a dependency manager for PHP that has been gaining steam lately. Your first question is most likely what is a dependency manager and why do I need one?. Almost any code you write probably ends up depending on 3rd party libraries. All of these libraries (projects, frameworks, files, etc) become dependencies of your project. Composer lets you declare the dependencies for a project and it will install and manage them.

1. Installing composer

Installing Composer is pretty simple with one caveat: It requires PHP 5.3 to run. Follow the instructions for either *nix, OSX or Windows.
I suggest installing Composer globally and then you can just use the composer command from anywhere.

2. Project Setup

To start using Composer in your project, all you need is a composer.json file.
This file describes the dependencies of your project and may contain other metadata as well.

In this example bellow, we will add some optional metadata to name properly your WordPress application:

  1. your WordPress app name
  2. a WordPress app description
  3. finally, some informations about yourself
{
    "name": "davidsanchez/sources",
    "description": "Package to build WordPress sources for davidsanchez.me",
    "authors": [
        {
            "name": "David Sanchez",
            "email": "david38sanchez@gmail.com"
        }
    ]
}

Integrating with WordPress

We are now ready to see how to use Composer with WordPress. When you think about a typical WP site, the easiest example of dependencies are plugins. But there’s something more fundamental to realize: WordPress itself is a dependency.

If we think about it, we’re creating a site, or application, that depends on WordPress. The WordPress core is a 3rd party library that is required for your application to work. This is difficult to understand at first due to how WordPress sites are usually structured.

The best solution right now is to use a fork of WordPress with a already added composer.json file.
https://github.com/johnpbloch/wordpress is currently the most popular/accepted package.

It’s simply an auto-updating fork (syncs every 15 minutes with the official WP repo) that includes composer.json wordpress-core-installer package. You can view it here.

Under, your authors metadata, we will add the next lines to require WordPress core:

{
    "require": {
        "johnpbloch/wordpress": "~4.5"
    },
    "extra": {
        "wordpress-install-dir": "wp"
    }
}

That’s it.
We just require johnpbloch/wordpress with the version of WordPress that we want and then tell Composer we want WordPress installed to wp.

WordPress Packagist

Fortunately, the awesome people at Outlandish have created a repository of WordPress plugins called WordPress Packagist.

Basically, they mirror every WordPress plugin and add a composer.json file that requires composer-installers and sets their package type to wordpress-plugin or wordpress-theme.

Their instructions are simple too:

  1. Add the repository to your composer.json
  2. Add the desired plugins and themes to your requirements using wpackagist-plugin or wpackagist-theme as the vendor name.
  3. Run composer update
  4. Plugins and themes are installed in wp-content/plugins/ and wp-content/themes/

So, we will now add the require metadata to tell Composer to get the WordPress plugins and themes from the WordPress Packagist:

{
    "repositories": [
        {
            "type": "composer",
            "url": "https://wpackagist.org"
        }
    ],
    "extra": {
        "installer-paths": {
            "content/mu-plugins/{$name}/": [
                "type:wordpress-muplugin"
            ],
            "content/plugins/{$name}/": [
                "type:wordpress-plugin"
            ],
            "content/themes/{$name}/": [
                "type:wordpress-theme"
            ]
        }
    }
}

After that, you will be able to go to the WordPress Packagist and add your WordPress plugins and themes into your composer.json file.

Restructuring WordPress

Like we said before, with Composer WordPress will be a depency, this is why people choose to put the WordPress’s core into a directory named wp/.

No matter which direction you choose when installing WordPress in a subdirectory there is a certain amount of restructuring that needs to be done to make it work. Mainly three things need changed:

  1. WordPress needs to be bootstrapped from the new location using an index.php file
  2. The wp-content folder will only contain the default plugins and themes from WordPress
  3. Any environment/config files (e.g. .htaccess/wp-config.php) also need to be in the root path

So our directory structure should now look something like this:

/
|
|-- wp-content/
|-- wp/    <-- Our directory install location for WordPress (not stored in Git repo)
|-- .htaccess
|-- index.php
|-- wp-config.php
|-- .gitignore
|-- composer.json    <-- If using Composer
`-- local-config.sample.php

Bootstrap index.php

This part is relatively simple. We’re going to install WordPress into the wp subdirectory, so we need to tell our webserver where to find WordPress. As everything is routed through the main index.php file (see .htaccess) we can simply create a bootstrap index.php file with the following contents:

<?php
// WordPress bootstrap
define('WP_USE_THEMES', true);
require __DIR__ . DIRECTORY_SEPARATOR . 'wp/wp-blog-header.php';

Environment config

You’ll notice the local-config.sample.php file in the root directory above. While this is not technically necessary it’s a good idea to split up environment-specific config information (such as database credentials and secret keys) from the “global” config information stored in wp-config.php (such as the table prefix and the wp-content location).

The idea here is that the wp-config.php file will hold any “global” config information and then load the correct “environment” config file as required. So for your production site you can deploy a production-config.php file which can be loaded by wp-config.php if it exists (we don’t store it in the Git repo though for security purposes) and if production-config.php doesn’t exist fall back to local-config.php which assumes you are working on a local development environment.

The content of our new wp-config.php file should look like:

<?php
// ===================================================
// Load database info and local development parameters
// ===================================================
if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'production-config.php')) {
    define('WP_LOCAL_DEV', false);
    include __DIR__ . DIRECTORY_SEPARATOR . 'production-config.php';
}
else {
    define('WP_LOCAL_DEV', true);
    include __DIR__ . DIRECTORY_SEPARATOR . 'local-config.php';
}

// ========================
// Custom Content Directory
// ========================
define('WP_CONTENT_DIR', __DIR__ . DIRECTORY_SEPARATOR . 'content');
define('WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] . '/content');

// ================================
// Language
// Leave blank for American English
// ================================
define('WPLANG', '');

// =========================
// Disable automatic updates
// =========================
define('AUTOMATIC_UPDATER_DISABLED', false);

// =======================
// Load WordPress Settings
// =======================
$table_prefix = TABLE_PREFIX;

if (!defined('ABSPATH')) {
    define('ABSPATH', __DIR__ . DIRECTORY_SEPARATOR . 'wp' . DIRECTORY_SEPARATOR);
}
require ABSPATH . 'wp-settings.php';

Sample config

You will need to rename the local-config.sample.php to local-config.php to use it. It should look something like this:

<?php
/** The name of the database for WordPress */
define('DB_NAME', 'local_db_name');

/** MySQL database username */
define('DB_USER', 'local_db_user');

/** MySQL database password */
define('DB_PASSWORD', 'local_db_password');

/** MySQL hostname */
define('DB_HOST', 'localhost'); // Probably 'localhost'

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8mb4');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

/** The Database tables prefix */
define('TABLE_PREFIX', 'wp_');

/**
 * https://codex.wordpress.org/Editing_wp-config.php#Debug
 */
define('WP_DEBUG_DISPLAY', true);
define('WP_DEBUG', true);

/**
 * Salts, for security
 * https://codex.wordpress.org/Editing_wp-config.php#Security_Keys
 */
define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
define('AUTH_SALT', 'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT', 'put your unique phrase here');
define('NONCE_SALT', 'put your unique phrase here');

/**
 * https://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants
 */
define('FS_METHOD', 'direct');

Install WordPress using Composer

Now that we have our working composer.json file, let’s actually install WordPress and his dependencies by running composer install in a terminal.