WP-CLI – Advanced WordPress Management
The command-line interface (CLI) has always been popular in the world of developers, because it provides tools that boost productivity and speed up the development process. At first sight, it might seem hard to believe that using the command line to perform certain tasks is getting easier than using a graphical interface. The purpose of this article is to clear up your doubts about that, at least concerning WordPress tasks.
WordPress provides a graphical user interface for every administrative task, and this has helped to make it the most popular content management system on the web. But in terms of productivity, working with the command line enables you to accomplish many such tasks more efficiently and quickly.
WP-CLI is a set of command-line tools that provide such functionality for managing WordPress websites.
In this tutorial, I’ll describe the benefits of using and extending WP-CLI, and I’ll present several advanced commands to make your life easier when working with WordPress.
Installation
Note: The following steps require a UNIX-like environment (OS X, Linux or FreeBSD). If you are a Windows user, you will need a command-line tool such as Cygwin or a virtual machine.
Installation of WP-CLI is simple. The basic idea is to download a PHP file and put it somewhere in order to be able to run it from anywhere. You can download the WP-CLI script from GitHub repository:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
Then, you need to make the file executable:
chmod +x wp-cli.phar
The final step is to move the file to a folder, so that you can execute it from anywhere. Renaming the file to something easy to remember and type is also a good idea; this is the reason why wp
is the most commonly used name:
sudo mv wp-cli.phar /usr/local/bin/wp
Installation is now over, and you should be able to type WP-CLI commands. You can check whether this process was completed successfully with the following command:
wp --info
If everything went fine, you should get an output similar to this:
PHP binary: /usr/bin/php
PHP version: 5.5.24
php.ini used: /etc/php.ini
WP-CLI root dir: phar://wp-cli.phar
WP-CLI global config: /Users/kouratoras/.wp-cli/config.yml
WP-CLI project config:
WP-CLI version: 0.19.2
Common Tasks
This article is focused on more advanced usage of WP-CLI, but we can start with some ordinary tasks that can be performed on the command line.
Install A WordPress Website
A basic WP-CLI command is core
, which offers a set of powerful tools for managing WordPress installations. The first step in setting up a new WordPress website is to download the package. Navigate to the desired directory and type:
wp core download
This will download the latest version of WordPress in English (en_US
). If you want to download another version or language, use the –version
and –locale
parameters. For example, to use the Greek localization and 4.2.2 version, you would type:
wp core download --version=4.2.2 --locale=el_GR
Once the download is completed, you can create the wp-config.php
file using the core config
command:
wp core config --dbname=databasename --dbuser=databaseuser --dbpass=databasepassword --dbhost=localhost --dbprefix=prfx_
This command will use the arguments and create a wp-config.php
file. Finally, to install WordPress, use the core install
command:
wp core install --url=example.com --title="WordPress Website Title" --admin_user=admin_user --admin_password=admin_password --admin_email="admin@example.com"
Update Core
If your WordPress installation needs to be updated, use the wp core update
and wp core update-db
subcommands to update the core files and the database (if the database needs to be updated).
WordPress updates, especially security fixes, are important. To make them happen more quickly, use the core update
command and (if needed) the core update-db
command:
wp core update
wp core update-db
You can always check the current version of your installation using core version
:
wp core version
Initially, updating in the command line might not seem more efficient than doing it from the dashboard, but if you’re maintaining multiple WordPress installations, it can save a lot of time and clicks. You can create a script and update them all at once:
#!/bin/bash
declare -a sites=('/var/www/wp1' '/var/www/wp2' '/var/www/wp3')
for site in "${sites[@]}";
do
wp --path=$site core update
done
In any case, backing up your database before any update process is recommended:
wp db export backup.sql
Manage Plugins
Similarly, managing plugins is a matter of a single command. For example, plugin status
returns information about installed plugins and their status — A
means active, I
means inactive and UA
means update available — outputting like this:
5 installed plugins:
UA smooth-scroll-up 0.8.9
I wordpress-beta-tester 1.0
A wordpress-importer 0.6.1
A wpcli-commands 1.0
Other plugin-related subcommands are install
, activate
, deactivate
, update
, delete
and search
, which can be used like in the following example:
wp plugin install wordpress-importer --activate
wp plugin deactivate wordpress-importer
wp plugin delete wordpress-importer
wp plugin update --all
wp plugin search import
Manage Themes
Generally, the same commands can be used to handle a website’s theme just by replacing plugin
with theme
, so there is no point going deeper into this. One noteworthy command is scaffold
, which creates an empty child theme, making that process much shorter:
wp scaffold child-theme my-child-theme --parent_theme=twentyfifteen --theme_name='My Child Theme' --author='Konstantinos Kouratoras' --author_uri=https://www.kouratoras.gr --theme_uri=https://wp.kouratoras.gr --activate
Manipulate Data
Apart from simple commands like post create
, post edit
and post delete
, WP-CLI provides tools to manage posts. If you need a lot of posts to test your code in a plugin or theme, you can use the post generate
command:
wp post generate --count=1000
You can also export your current content and migrate it to another WordPress installation. To do so, you need to install the Importer plugin:
wp plugin install wordpress-importer --activate
And then you would use the export
and import
commands to complete the transfer:
wp export
wp import test.xml --authors=create
Manage Post Revisions
By default, WordPress stores every revision of a post in the database. This means that eventually you will have a huge amount of information in the posts table of your website.
To handle this issue, you can use the wp-revisions-cli plugin, which is an extension of WP-CLI that adds functionality for managing post revisions. This can be installed as a common WordPress plugin, and it offers a set of commands such as clean
, list
and status
. For example, using wp wp revisions list
, you can get a list of revisions to current posts:
+--------------+-------------+-----+
| post_title | post_parent | ID |
+--------------+-------------+-----+
| Hello world! | 1 | 894 |
+--------------+-------------+-----+
Media
Some administrative tasks that are hard to perform relate to images and media in general. WP-CLI provide some tools to save you time here.
Bulk Import Images
It’s not unusual for a client to provide a set of images and ask you to import them into their website. Doing that through the administrator’s panel is painful. Instead, using the media tool of WP-CLI, you can complete this task in a single command:
wp media import images_folder/*
Regenerate Media
You need to regenerate thumbnails when you create new image sizes during the development process. Of course, you could use a third-party plugin or custom PHP code to achieve this, but both ways require significantly more time than a WP-CLI command:
wp media regenerate
There are infinite possibilites, because you can combine several commands to specify the target images to edit. For example, to regenerate the featured images for posts of a particular category, you can use the following command:
wp media regenerate $(wp eval 'foreach( get_posts(array("category" => 2,"fields" => "ids")) as $id ) { echo get_post_thumbnail_id($id). " "; }')
Database Operations
When we talk about advanced WordPress management using the command line, database operations always come in mind. WP-CLI provides tools for these kinds of tasks. You can run simple queries:
wp db query "SELECT id FROM wp_users;"
And you can handle database operations such as importing, exporting and optimizing:
wp db export
wp db import backup.sql
wp db optimize
The export command can be also used in a script or a cron job to handle and schedule database backups.
Search And Replace
Developing a website on a local or development server and then moving to another server when everything is ready is a common practice. Copying the files and migrating the database are the easy steps. Replacing the old URLs with the new ones in the database records is a trickier part of this procedure, because URLs also exist in serialized data, for which a simple search and replace will not work.
WP-CLI helps you perform this task. The search-replace
command replaces the old URL with the new one in all database entries, including those that contain serialized data.
wp search-replace 'dev.example.com' 'www.example.com'
In this case, WP-CLI unpacks JSON data, executes the replace action and packs the data again into the database entry.
If you want to see how many instances of this search action are in your database without performing the replace command, you can run the previous command using the –dry-run
:
wp search-replace --dry-run 'dev.example.com' 'www.example.com'
The resulting output will be something like the following:
+---------------------+-----------------------+--------------+------+
| Table | Column | Replacements | Type |
+---------------------+-----------------------+--------------+------+
| wpcli_options | option_value | 2 | PHP |
| wpcli_posts | post_content | 1 | SQL |
| wpcli_posts | guid | 28 | SQL |
+---------------------+-----------------------+--------------+------+
Working With WordPress Multisite
A huge advantage of WP-CLI and the command line in general is the ability to automate repetitive tasks using scripts. This also applies to WordPress Multisite networks. Instead of visiting each website’s dashboard to perform a task, you can simplify the process using some lines of code. For example, you can use the following script to install WordPress’ Importer plugin:
#!/bin/bash
for site in $(wp site list --field=url)
do
wp plugin install wordpress-importer --url=$site --activate
done
If you want to avoid the additional steps of creating and running a script file, you can execute the previous example using a single command:
for site in $(wp site list --field=url); do wp plugin install wordpress-importer --url=$site --activate; done
Using WP-CLI Remotely With SSH
If you have already installed WP-CLI on your remote server or if your hosting provider supports this, then you can connect via an SSH terminal and use WP-CLI commands. The only things you’ll need are an SSH client and your host credentials to connect to your server.
Linux and Mac OS X users do not need any additional software, because this can be done using the Terminal application. For Windows users, there are third-party tools, Putty being the most popular one. Using any of the tools mentioned above, you can connect to your server using this command:
ssh username@host
You will be prompted for your password and, if you connect successfully, you will have a command-line interface to use WP-CLI tools for your websites with this host. In case WP-CLI is not available, you can follow the steps described on the official website to install it. At the end of the process, you can verify that it was successfully installed by typing the following command:
wp cli version
If everything went fine, you will get the current version.
Run Commands Seamlessly
Connecting to a server and navigating to the right path in order to execute WP-CLI commands is a bit boring. Instead, you can use WP-CLI SSH, which is a package that allows you to invoke WP-CLI from your local shell, without having to log into your remote host.
Before moving to the installation steps of WP-CLI SSH, you need to set up WP-CLI’s package index in the ~/.wp-cli
folder. (If it does not exists, create this directory.)
cd ~/.wp-cli
You’ll have to install Composer, if you have not done so before:
curl -sS 'https://getcomposer.org/installer' | php
Create (or use the existing) composer.json
file:
php composer.phar init --stability dev --no-interaction
php composer.phar config bin-dir bin
php composer.phar config vendor-dir vendor
Add the WP-CLI package index:
php composer.phar config repositories.wp-cli composer 'https://wp-cli.org/package-index/'
Create (or use the existing) config.yml
file, and put these lines inside it:
require:
- vendor/autoload.php
Everything should now be ready for you to install the WP-CLI SSH package:
php composer.phar global require x-team/wp-cli-ssh dev-master
It’s time to create the configuration file and set up the hosts. Create a wp-cli.yml
file and insert the following settings:
ssh:
production:
# The %pseudotty% placeholder gets replaced with -t or -T depending on whether you're piping output
# The %cmd% placeholder is replaced with the originally invoked WP-CLI command
cmd: ssh %pseudotty% production.example.com %cmd%
# Passed to WP-CLI on the remote server via --url
url: production.example.com
# We cd to this path on the remote server before running WP-CLI
path: /var/www/production
# WP-CLI over SSH will stop if one of these is provided
disabled_commands:
- db drop
- db reset
In the previous example, replace production.example.com
with your server’s URL and /var/www/production
with the path to your WordPress installation. In the disabled commands
section, you can set WP-CLI commands that will not be allowed on the remote server. You can create as many hosts as you wish, using different names for each one.
If everything has been set up correctly, you will be able to run commands using the ssh
subcommand and providing the host argument:
wp ssh plugin status --host=production
In case you’ll be working mainly on the remote server, there is also the option to create an alias in your ~/.bash_profile
file, so that the wp
command will use this host by default:
alias wp="wp ssh --host=production"
Unit Tests
Unit tests can be very beneficial to plugin developers. They can reveal bugs very quickly and ensure that a new version of your software will not break anything. However, creating tests is a complicated process because you have to set up PHPUnit, set up WordPress’ testing library and test configuration files. For the last two tasks, WP-CLI can make your life easier and generate the required files automatically.
First things first. You need to install PHPUnit; follow the guide on the official website. After this, WP-CLI will take action and help you to create the files needed to run PHPUnit tests with a single command:
wp scaffold plugin-tests my-plugin
If you navigate to your plugin’s directory, you will see some new folders and files:
.travis.yml
bin/
phpunit.xml
tests/
You can use the install-wp-tests.sh
file in the bin
folder to initialize the testing environment:
bash bin/install-wp-tests.sh test_database user 'pass' localhost latest
The parameters used are:
test_database
the database that will be used to insert test datauser
MySQL database userpass
MySQL database passwordlocalhost
MySQL hostlatest
the WordPress version you are using
The previous command would set up an example unit test that actually does nothing, but it can be used as a starter file to create your own test. The file is tests/test-sample.php
and contains the following source code:
class SampleTest extends WP_UnitTestCase {
function test_sample() {
// replace this with some actual testing code
$this->assertTrue( true );
}
}
Everything is now ready, and you can run your plugin’s unit test:
phpunit
We won’t go any further into unit tests because they’re beyond the scope of this article, but you can find a ton of resources on PHPUnit’s official website and around the web.
Extending WP-CLI
If you have gotten to this point, you might be convinced that WP-CLI is a powerful tool in the hands of a developer. But this is not the end of the story, because you can also extend built-in functionality using your code. There are two ways to do that. You can either load and execute PHP code from a file or build your own plugin that creates a custom command.
Execute PHP File
If you want to test a PHP snippet, there is no need to include it in a WordPress file. WP-CLI provides the eval-file
command, which executes common PHP files, having loaded WordPress before. For example, if you want to print the title from a random WordPress post, the source code for this action would be something like this:
global $wpdb;
$random_post = $wpdb->get_var(
"SELECT post_title
FROM $wpdb->posts
WHERE post_type = 'post'
AND post_status = 'publish'
ORDER BY rand()
LIMIT 1"
);
echo "Random post: $random_post";
Save it in a file named script.php
and check the output, typing this command:
wp eval-file ./script.php
Create Custom Commands Using Plugin
Moving one step further, you can create custom WordPress plugins to extend WP-CLI’s built-in functionality and create your own commands. Your plugin file should have a class for each command and public methods for each subcommand.
Let’s see it in action. Let’s assume you want to create a command that contains three subcommands:
hello
takes a name as a positional argument and sayshello
bye
takes a name as an associative argument and saysbye
random
prints the title of a random WordPress post
We’d create a class, named My_Commands
, that contains three public functions: hello
, bye
and random
. These functions take two arguments: $args
, which contains the positional arguments, and $assoc_args
, which contains the associative arguments.
In our example, the first subcommand would have a name
positional argument, which would take as input to print the hello
:
function hello( $args, $assoc_args ) {
list( $name ) = $args;
WP_CLI::success( "Hello, $name!" );
}
The second subcommand would have a name
associative argument, which would be extracted from the $assoc_args
array:
function bye( $args, $assoc_args ) {
$name = 'name';
if( $assoc_args[ 'name' ] ) {
$name = $assoc_args[ 'name' ];
}
WP_CLI::success( "Bye, $name!" );
}
The third subcommand would take no arguments. It would just execute a database query, fetch a random post and print the title:
function random ( $args, $assoc_args ) {
global $wpdb;
$random_post = $wpdb->get_var(
"SELECT post_title
FROM $wpdb->posts
WHERE post_type = 'post'
AND post_status = 'publish'
ORDER BY rand() LIMIT 1"
);
WP_CLI::success( "Random post: $random_post" );
}
Finally, you would have to register your class as a WP-CLI command, using an add_command
call. This function takes as arguments the name of the command and the name of the class:
WP_CLI::add_command( 'mycommands', 'My_Commands' );
Wrapping the whole code in a WordPress plugin, you would end up with the following file:
/*
Plugin Name: WP-CLI Commands
Version: 1.0
description: >-
Extending WP-CLI with custom commands
Author: Konstantinos Kouratoras
Author URI: https://www.kouratoras.gr
*/
if( defined( 'WP_CLI' ) && WP_CLI ) {
class My_Commands {
function hello( $args, $assoc_args ) {
list( $name ) = $args;
WP_CLI::success( "Hello, $name!" );
}
function bye( $args, $assoc_args ) {
$name = 'name';
if( $assoc_args[ 'name' ] ) {
$name = $assoc_args[ 'name' ];
}
WP_CLI::success( "Bye, $name!" );
}
function random ( $args, $assoc_args ) {
global $wpdb;
$random_post = $wpdb->get_var("SELECT post_title FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' ORDER BY rand() LIMIT 1");
WP_CLI::success( "Random post: $random_post" );
}
}
WP_CLI::add_command( 'mycommands', 'My_Commands' );
}
You can confirm that your command has been registered successfully by typing the following:
wp mycommands
This outputs the list of all available commands:
usage: wp mycommands bye --name=name
or: wp mycommands hello name
or: wp mycommands random
Everything is ready to execute your first WP-CLI custom commands:
wp mycommands hello world
wp mycommands bye --name="Joe"
wp mycommands random
Respectively, the output would be:
Success: Hello, world!
Success: Bye, Joe!
Success: Random post: This is a title of a post
Conclusion
You now have a good idea of the possibilities of WP-CLI. These possibilities are becoming endless, if you consider that you can extend core functionality and create your own commands. Of course, many more built-in tools were not mentioned in this article. You can find more about them on the official website.
In case you want to see WP-CLI in action and integrate it in your daily workflow, you will find some resources below to get started.
Resources From Around The Web
- WP-CLI (official website)
- WP-CLI, GitHub
- WP-CLI wiki
- WP-CLI, WordPress Codex
- WP-CLI, StackExchange (questions)
- WP-CLI Commits, Google Groups (mailing list)
Further Reading
- Meet ImageOptim-CLI, A Batch Compression Tool
- Powerful Command Line Tools For Developers
- Proper WordPress Filesystem Permissions And Ownerships
- How To Host A WordPress Site On Amazon Lightsail