The idea is to separate the WordPress site’s components into their own directories right at the root. This creates a simple modular structure, where parts of a WordPress site are totally on their own. This makes things less complex and less prone to errors.
We will not be touching the WordPress subdirectory, we will only update it when a new version is released. Therefore, we will have to put our configuration and custom development (themes & plugins) outside the WordPress folder.
I’m going to use Composer package manager for PHP to install these packages and this is the directory structure that I want to create.
Directory structure
website/ --config/ --vendor/ --lib/ --www/ wp/ - Will contain the WordPress package wp-content/ - Will contain all my themes and plugins .htaccess index.php wp-config.php composer.json
Composer file
The Composer can be used for both the core and plugins, for plugins we will use wpackagist. After you’ve installed composer, create a composer.json in your root folder that looks something like this:
{ "name": "parse/demo", "description": "Parse: Demo", "license": "proprietary", "repositories": [ { "type":"composer", "url":"http://wpackagist.org" }, { "type": "package", "package" : { "name": "wordpress", "type": "webroot", "version": "3.7.1", "dist": { "type": "zip", "url": "https://github.com/WordPress/WordPress/archive/3.7.1.zip" }, "require" : { "fancyguy/webroot-installer": "1.1.0" } } } ], "require": { "composer/installers": "1.0.x-dev", "wordpress": "3.7.1", "wpackagist/mp6": "~2.1" }, "require-dev": { "wpackagist/debug-bar": "~0.8", "wpackagist/debug-bar-console": "~0.3" }, "minimum-stability": "dev", "extra": { "wp-content": "www/wp-content", "webroot-dir": "www/wp", "webroot-package": "wordpress", "installer-paths": { "www/wp-content/plugins/{$name}/": ["type:wordpress-plugin"] } } }
This file defines that we want to install WordPress core in a folder www/wp/ and its plugins in www/wp-content/plugins/
index.php
By moving the WordPress core, the index.php that is in www/ will now have to be changed to:
<?php
// WordPress view bootstrapper
define( 'WP_USE_THEMES', true );
require( './wp/wp-blog-header.php' );
wp-config.php
And since we will not use the wp-content/ folder in www/wp/wp-content/, we need to redefine that in wp-config.php:
<?php
define('WP_CONTENT_DIR', dirname(__FILE__) . '/wp-content');
define('WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] . '/wp-content');
Now, we have set up the files, your vhost need to be configured to the www/ folder.
Nginx
After struggling a bit with PHP’s PATH_INFO variable and found a solution, this is the important part:
if (!-e $request_filename) { rewrite /wp-admin$ $scheme://$host$uri/ permanent; rewrite ^(/[^/]+)?(/wp-.*) /wp$2 last; rewrite ^(/[^/]+)?(/.*\.php)$ /wp$2 last; } location / { root /home/username/apps/appname/current/www/; try_files $uri $uri/ /index.php?$args; index index.php; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param SCRIPT_FILENAME /home/username/apps/appname/current/www$fastcgi_script_name; fastcgi_param ENVIRONMENT production; fastcgi_param PATH_INFO $fastcgi_script_name; include /etc/nginx/fastcgi_params; }
Apache
ServerName domainname.com
DocumentRoot "/home/username/apps/appname/current/www/"
<Directory "/home/username/apps/appname/current/www/">
Options Indexes Includes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
The .htaccess in this case will look something like this:
Options -Indexes
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) wp/$2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ wp/$2 [L]
RewriteRule . index.php [L]
To upgrade plugins or core, you simply need to update your composer.json. We still need to add custom plugins into our repository, but you could create your own repositories for them as well.