{"id":159854,"date":"2016-10-17T13:00:01","date_gmt":"2016-10-17T13:00:01","guid":{"rendered":"https:\/\/premium.wpmudev.org\/blog\/?p=159854"},"modified":"2017-05-12T11:10:25","modified_gmt":"2017-05-12T11:10:25","slug":"advanced-wordpress-development-wordpress-wp-cli","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/advanced-wordpress-development-wordpress-wp-cli\/","title":{"rendered":"Advanced WordPress Development: WordPress Automation With WP-CLI"},"content":{"rendered":"<p>Whether you&#8217;re a developer or an admin overseeing multiple WordPress sites, I&#8217;m sure you&#8217;ve thought to yourself: &#8220;I wish I could do this faster.&#8221; From creating a fresh install for testing to updating the same plugin on multiple sites, there are <em>so<\/em> many tasks you&#8217;ll find yourself doing over and over again.<\/p>\n<p><a href=\"https:\/\/wp-cli.org\/\" target=\"_blank\">WP-CLI<\/a> is the answer to your woes and one of my favorite time-saving tools for web development.<\/p>\n<p>This is the final post in our six-part series focusing on WordPress for advanced developers. This series follows on from our popular <a href=\"https:\/\/wpmudev.com\/blog\/wordpress-development-intermediate-theme-development-in-detail\/\" target=\"_blank\">WordPress Development for Intermediate Users<\/a>, which introduced you to some meaty coding topics, including theme development in detail, making themes customizer-ready, building plugins, custom post types and taxonomies, queries and loops, custom fields and metadata, and localization.<\/p>\n<p>WP-CLI is a command-line utility (hence the CLI part) that gives you control over many aspects of WordPress. In this tutorial, I&#8217;ll show you how to use WP-CLI, how to create powerful bash scripts for even more powerful automation, and how to manage multiple WordPress sites at once.<\/p>\n<p>That&#8217;s a tall order; we&#8217;d better get started!<\/p>\n<p><em>Note: It\u2019s important that you have a working knowledge of <a href=\"https:\/\/wpmudev.com\/blog\/getting-started-with-wordpress-development\/\" target=\"_blank\" rel=\"noopener\">PHP<\/a> as this is the foundational language of WordPress for this series, which covers advanced topics aimed at developers. I\u2019ll be referring to code snippets throughout this series.<\/em><\/p>\n<h2>Installing WP-CLI<\/h2>\n<p>Installing WP-CLI is super-easy. Just issue the following commands, which can also be found on the WP-CLI home page:<\/p>\n<div class=\"gist\" data-gist=\"071f0d29a37a62f1d78ff09dda004383\" data-gist-file=\"install.sh\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/071f0d29a37a62f1d78ff09dda004383.js?file=install.sh\">Loading gist 071f0d29a37a62f1d78ff09dda004383<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p><strong><em>Regretfully, Windows has limited support; you get the most mileage out of WP-CLI on Unix-like environments. You can find some additional notes on Windows installation in the <a href=\"https:\/\/make.wordpress.org\/cli\/handbook\/guides\/installing\/\" target=\"_blank\">documentation<\/a>. If you&#8217;re having trouble, use what we learned in the terminal tutorial and <a href=\"https:\/\/wpmudev.com\/blog\/what-is-ssh-wordpress\/\" target=\"_blank\" rel=\"noopener\">SSH<\/a> into a remote server, which is most likely to be a Unix environment, and practice there.<\/em> <\/strong><\/p>\n<h2>Basic WP-CLI Usage<\/h2>\n<p>The use of WP-CLI is easy and intuitive once you&#8217;ve used a few commands. It always starts with the base <code>wp<\/code> command, followed by one or more subcommands. Subcommands are used for grouping, which makes things logical. For example, here are commands to get and update a specific option in the database:<\/p>\n<div class=\"gist\" data-gist=\"ef639adde53571f8e951511620f1e5a0\" data-gist-file=\"option.sh\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/ef639adde53571f8e951511620f1e5a0.js?file=option.sh\">Loading gist ef639adde53571f8e951511620f1e5a0<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>One of my favorite \u2013 and most frequently used \u2013 commands is <code>search-replace<\/code>. This enables you to search-replace a term within the WordPress database. It handles serialized strings properly; unserializing them, making the replacement and then re-serializing them.<\/p>\n<div class=\"gist\" data-gist=\"0742cfb4e7151f170e2886a7dfdaa785\" data-gist-file=\"search-replace.sh\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/0742cfb4e7151f170e2886a7dfdaa785.js?file=search-replace.sh\">Loading gist 0742cfb4e7151f170e2886a7dfdaa785<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>As you can see, using WP-CLI is not difficult. Take a look at the <a href=\"https:\/\/developer.wordpress.org\/cli\/commands\/\" target=\"_blank\">WP-CLI commands documentation<\/a>\u00a0for more information. I&#8217;ll be going through some more commands shortly, but first I want to show you some advanced setup and options.<\/p>\n<h2>Global Parameters<\/h2>\n<p>WP-CLI has a bunch of global parameters that can be added to any command. You can read about them on any documentation page in the right-hand sidebar block. I&#8217;ll go through the most useful ones.<\/p>\n<h3>&#8211;quiet<\/h3>\n<p>This parameter will suppress info messages that are normally displayed when executing a command. I use this when creating bash scripts that execute a bunch of WP-CLI commands at once. More on this later.<\/p>\n<h3>&#8211;ssh<\/h3>\n<p>By adding this parameter, you can execute the WP-CLI command on a remote server instead of locally. This is what we&#8217;ll be using to control multiple WordPress instances by issuing local commands.<\/p>\n<h3>&#8211;path<\/h3>\n<p>You can explicitly set the path of the WordPress installation. Normally, WP-CLI is run from within the root directory of the WP installation. If this isn&#8217;t the case, you can use <code>--path<\/code> to tell WP-CLI where WP is.<\/p>\n<h3>&#8211;prompt<\/h3>\n<p>This will prompt you to fill out all parameters. Useful if you don&#8217;t know the parameters off the top of your head or if you add WP-CLI as part of a larger script that others will use.<\/p>\n<h3>&#8211;allow-root<\/h3>\n<p>Not a global parameter per se because it doesn&#8217;t apply to all commands, but I use it sometimes on remote servers where I must use sudo for some reason. If you use sudo, you must use this parameter to make sure WP-CLI performs this action. That said: try to avoid using sudo for commands when possible.<\/p>\n<h2>Configuring WP-CLI<\/h2>\n<p>If you use these parameters a lot, you can set them in a configuration file. There are three configuration files that are parsed and used (if found) in the following order:<\/p>\n<ol>\n<li><code>wp-cli.local.yml<\/code> inside the current directory or above<\/li>\n<li><code>wp-cli.yml<\/code> inside the current directory or above<\/li>\n<li><code>~\/.wp-cli\/config.yml<\/code><\/li>\n<\/ol>\n<p>Use the first two for project-specific configuration. The final file can be used to configure global options that you want to use on every project. The config file can also include defaults for sub-commands. Let&#8217;s look at an example:<\/p>\n<div class=\"gist\" data-gist=\"8b4a39bb10b60921433727eef609c34e\" data-gist-file=\"wp-cli.yml\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/8b4a39bb10b60921433727eef609c34e.js?file=wp-cli.yml\">Loading gist 8b4a39bb10b60921433727eef609c34e<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Note how I&#8217;ve used the global parameters. There are a couple of global parameters like <code>disabled_commands<\/code> which can not be set inline with commands; you must use the yml file.<\/p>\n<p>I&#8217;ve added some defaults for the <code>wp core config<\/code> command which sets up the <code>wp-config.php<\/code> file. This is a setup I&#8217;d use for development; I&#8217;ve added my database username\/password and additional PHP constants to define which can be useful while developing.<\/p>\n<h2>Using SSH With WP-CLI to Automate WordPress Tasks<\/h2>\n<p>As of version 0.24.0, WP-CLI natively supports <a href=\"https:\/\/wpmudev.com\/blog\/what-is-ssh-wordpress\/\" target=\"_blank\" rel=\"noopener\">SSH<\/a>. Previously you needed a third party command to get things done. WP-CLI has implemented SSH usage extremely efficiently. Let&#8217;s see how it works.<\/p>\n<p>Let&#8217;s think like a WordPress agency that hosts websites for clients might think for a minute. Our websites all have a common &#8220;agency&#8221; plugin, which gives our users some useful information and a common control panel. We now have three client websites and a local test site, which we use to test the agency plugin. Let&#8217;s see how we can manage all of these sites at once.<\/p>\n<p>Our first task is to make sure WP-CLI is available on all servers. Once that&#8217;s done, let&#8217;s go into the <code>wp-cli.yml<\/code> file within the local WordPress installation.<\/p>\n<div class=\"gist\" data-gist=\"ad025c51329254ca241612ca81521bb9\" data-gist-file=\"ssh.yml\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/ad025c51329254ca241612ca81521bb9.js?file=ssh.yml\">Loading gist ad025c51329254ca241612ca81521bb9<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>I&#8217;ve added aliases for each website, followed by another alias that groups all websites together. I could update all plugins on all sites using the following command:<\/p>\n<div class=\"gist\" data-gist=\"0fb8c9987d0f3c2fcda64aa1776e86b0\" data-gist-file=\"all.sh\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/0fb8c9987d0f3c2fcda64aa1776e86b0.js?file=all.sh\">Loading gist 0fb8c9987d0f3c2fcda64aa1776e86b0<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Just replace &#8220;@all&#8221; with the alias for a specific site to execute a command against that single site.<\/p>\n<h2>Further Automation With Bash Scripts<\/h2>\n<p>Bash scripts are available in Unix environments and are like bat files in windows. I use them frequently to bundle together commands that can then be run at once using a single command.<\/p>\n<h3>BASH Scripts: The Basics<\/h3>\n<p>Navigate to one directory above your WordPress root folder and create a file named <code>test.sh<\/code>. Edit this file, adding the following content:<\/p>\n<div class=\"gist\" data-gist=\"8512c55bd8bcdefa424f0bac8ae4fe4a\" data-gist-file=\"test.sh\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/8512c55bd8bcdefa424f0bac8ae4fe4a.js?file=test.sh\">Loading gist 8512c55bd8bcdefa424f0bac8ae4fe4a<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>You should be familiar with both lines. The first one creates a directory named &#8220;test&#8221; and navigates into it. The second line downloads the core files needed for WordPress using WP-CLI.<\/p>\n<p>To execute both commands at once simply run <code>bash test.sh<\/code>.<\/p>\n<h3>Creating a New Installation<\/h3>\n<p>When testing plugins and themes it&#8217;s always a good idea to see what happens using a fresh installation of WordPress. You might have already added some options that your product relies on but doesn&#8217;t check for \u2013 all sorts of things could go wrong.<\/p>\n<p>Here&#8217;s a little script that you can use to create or remove-and-recreate a WordPress installation in a given folder:<\/p>\n<div class=\"gist\" data-gist=\"0e5cea558cc4c888ceb32a65a3a0bda3\" data-gist-file=\"new-install.sh\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/0e5cea558cc4c888ceb32a65a3a0bda3.js?file=new-install.sh\">Loading gist 0e5cea558cc4c888ceb32a65a3a0bda3<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>It takes one parameter: the name of the directory you want your WordPress installation in. If it doesn&#8217;t exist it creates the directory, goes into it and configures and installs WordPress. If it already exists it just resets the database and reinstalls WordPress.<\/p>\n<p>You can run it using <code>bash install.sh mydir<\/code>. Super simple and super helpful. You can add all the bells and whistles in there like adding PHP constants.<\/p>\n<h2>Streamlining Your Web Development Workflow With WP-CLI<\/h2>\n<p>WP-CLI is a worthy addition to any WordPress power user&#8217;s toolbox. As a site manager, it allows you to perform common tasks across multiple sites. And as a developer, it provides you with automation tools to lessen your workload.<\/p>\n<p>When combined with bash scripts it becomes even more powerful allowing you to define your own workflow, creating shortcuts that can shave hours off your day.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Whether you&#8217;re a developer or an admin overseeing multiple WordPress sites, I&#8217;m sure you&#8217;ve thought to yourself: &#8220;I wish I could do this faster.&#8221; From creating a fresh install for testing to updating the same plugin on multiple sites, there are so many tasks you&#8217;ll find yourself doing over and over again. WP-CLI is the [&hellip;]<\/p>\n","protected":false},"author":344049,"featured_media":159985,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"blog_reading_time":"","wds_primary_category":0,"wds_primary_tutorials_categories":0,"footnotes":""},"categories":[557,263],"tags":[9770,10189],"tutorials_categories":[],"class_list":["post-159854","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","category-tutorials","tag-development-2","tag-wp-cli"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/159854","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/users\/344049"}],"replies":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/comments?post=159854"}],"version-history":[{"count":12,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/159854\/revisions"}],"predecessor-version":[{"id":198611,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/159854\/revisions\/198611"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/159985"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=159854"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=159854"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=159854"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=159854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}