Menu Search
Jump to the content X X
Smashing Conf New York

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

Advanced WordPress Management With WP-CLI

The command-line interface 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.

Typing1
(Image credit: Marc Chouinard2) (View large version3)

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 Link

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 Cygwin4 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 Link

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 Link

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 Link

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 Link

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 Link

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=http://www.kouratoras.gr --theme_uri=http://wp.kouratoras.gr --activate

Manipulate Data Link

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 Link

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-cli5 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 Link

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 Link

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 Link

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 Link

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 Link

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 Link

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 Link

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, Putty6 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 website117 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 Link

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 SSH8, 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 'http://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 Link

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 website9. 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 data
  • user
    MySQL database user
  • pass
    MySQL database password
  • localhost
    MySQL host
  • latest
    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 website10 and around the web.

Extending WP-CLI Link

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 Link

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 Link

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 says hello

  • bye
    takes a name as an associative argument and says bye

  • 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: http://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 Link

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 website117.

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 Link

(dp, ml, al)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2015/08/typing-opt.jpg
  2. 2 https://stocksnap.io/photo/YRUO4LCSLB
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2015/08/typing-opt.jpg
  4. 4 https://www.cygwin.com/
  5. 5 https://github.com/trepmal/wp-revisions-cli
  6. 6 http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
  7. 7 http://wp-cli.org/
  8. 8 https://github.com/xwp/wp-cli-ssh
  9. 9 https://github.com/sebastianbergmann/phpunit#installation
  10. 10 https://phpunit.de/documentation.html
  11. 11 http://wp-cli.org/
  12. 12 http://wp-cli.org/
  13. 13 https://github.com/wp-cli/wp-cli
  14. 14 https://github.com/wp-cli/wp-cli/wiki
  15. 15 https://codex.wordpress.org/wp-cli
  16. 16 http://wordpress.stackexchange.com/questions/tagged/wp-cli
  17. 17 https://groups.google.com/forum/?fromgroups=#!forum/wp-cli-commits
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook

Konstantinos Kouratoras is a software engineer based in Crete, Greece. WordPress lover and amateur photographer. You can contact him through personal website or follow him on twitter.

  1. 1

    This was convenient timing – I was just looking for a way to manage WordPress installations and plugins automatically, and this looks like it’ll do just the trick!

    Thank you very much!

    3
  2. 2

    You have a typo in “wp core download” with fix version an locale.
    “wp core download –version=4.2.2 –locale=el_GR”

    0
  3. 4

    This is an awesome article, I have used wp cli for a while, for smaller tasks, but will use it more now. Thanks!

    2
  4. 5

    Alexander Tarkhov

    September 25, 2015 4:29 pm

    You really helped me. Thank you!

    1
  5. 6

    wp generate posts –count=1000 seems wrong?
    it should be “wp post generate –count=1000”

    0
  6. 8

    I’m trying to install the WP-CLI SSH package, but get the below error, I’ve followed your previous steps and have also installed Composer globally.

    [Composer\Downloader\TransportException]The “http://wp-cli.org/package-index/include/all%24cc60c5b828017a7c5627c4edfd8afe1a341d368c.json” file could not be downloaded (HTTP/1.1 404 Not Found)

    Any help would be much appreciated!

    0
  7. 11

    Another issue! now I’m getting “Error: Required file ‘autoload.php’ doesn’t exist” when I try to run a command e.g. “wp core version”. I’ve run “composer install” to install the dependancies but get the same error as before…

    [Composer\Downloader\TransportException]
    The “http://wp-cli.org/package-index/include/all%24cc60c5b828017a7c5627c4edfd8afe1a341d368c.json” file could not be downloaded (HTTP/1.1 404 Not Found)

    Is this linked to the previous issue?

    0
  8. 12

    Hemang Rindani

    November 10, 2015 1:30 pm

    Great article. WordPress is a delight for a developer especially with the inclusion of Command-line along with the graphical interface used for designing. Modules can be easily modified using CLI to create an expected design. Basic programming knowledge is enough to write a command in WordPress. CLI can be effective to increase the website security.

    0
  9. 13

    Hi,great article. I’ve tried to use the $wp shell but i always having an error:
    ************
    $ php wp-cli.phar shell –debug
    Debug: No readable global config found (0.018s)
    Debug: No project config found (0.019s)
    Debug: ABSPATH defined: E:\cygwin64\home\Administrator\bin/ (0.036s)
    Debug: Begin WordPress load (0.037s)
    Debug: wp-config.php path: E:\cygwin64\home\Administrator\bin\wp-config.php (0.037s)
    Debug: Loaded WordPress (0.341s)
    Debug: Running command: shell (0.342s)
    The system cannot find the path specifie
    ********************
    I use Cygwin and this error drives me crazy. Any help appreciated.

    0

↑ Back to top