Sometimes the usual web-based WordPress tools aren't enough, and you need a better control over your blog's maintenance process. In these cases, if your hosting provider allows SSH access, a custom command line script can do the best.
Let's say that you need to import or export from a very big WordPress backup file, with more or less 50.000 posts and 200.000 categories and tags, and each entry must be processed in some way (eg. cleaning text, downloading images, etc).
Using a web-based script can lead to some problems, such as:
- the script's execution lasts too long and it's terminated by the server
- the script needs more memory than that allocated by the web server
If you have a similar problem, the command line is what you need. Also, depending on your hosting permissions, you can set a real cron script instead of relying on WordPress' pseudo-cron feature. But let's write some code.
Step 1 - Setup your environment
The first thing to do is to setup a command line space in your WordPress installation. One viable solution is a directory named wp-content/bin. In this directory we'll place all our script files.
The first and most important script is called cli.php, it contains the common library (it's only one statement at the moment) and it must be included in all the other scripts, here's why:
if ('cli' != php_sapi_name()) exit("Not this way babe!\n");
This line tells our PHP parser that the script must be executed only if the current environment is the command line. This script can be extended to include other useful functions, but this is the most important statement. And now we can build our first script, called test-posts.php which will fetch a list of most recent posts.
Step 2 - Provide some security hooks
This step is not required but it's strongly recommended: the script can be configured to be executed only by certain users and can require a password.
Important: In order to prevent unauthorized access you should set the script's permissions accordingly. For example, by setting permissions to 600 only the file owner can run the script using the command
$ php -f test-posts.php
With the following lines of code we can restrict the execution of the script to a list of users.
$users = array('someuser', 'anotheruser'); $cli_user = exec('whoami'); if (!empty($users)) { if (!in_array($cli_user, $users)) { echo "Your username ({$cli_user}) is not in my list babe!\n"; exit(1); } // end if } // end ifThen we could also ask for a secret key in order to run the script, for example we may want to use:
$ php -f test-posts.php -- --key=SuperSecretKeyWe can obtain this using the next code snippet:
if (!defined('CLI_SECRET')) define('CLI_SECRET', 'SuperSecretKey'); if (CLI_SECRET !== '') { // Check for arguments if ($argc < 2) { echo "Invalid arguments: a super secret code is needed to run this script!\n"; printf("Usage: /path/to/php -f %s -- --key=<supersecret>\n", basename(__FILE__)); exit(2); } // end if // Parsing arguments: move the secret key (if present) to $_GET['key'] var. $args = split('=', $argv[1]); if ('--key' == $args[0]) $_GET['key'] = $args[1]; // Do stuff if(CLI_SECRET !== $_GET["key"]){ echo "Access denied!\n"; exit(3); } // end if } // end ifStep 3 - Loading WordPress
Now we can load the WordPress' environment inside our script, and with the next step we will run our custom code.
Take into account that some plugins could interfere with this step, for example plugins that make use of cookies or HTTP headers may complain if we output something before WordPress is fully loaded.
The following line prevents unwanted cached output from plugins like WPSuperCache and similar.
$_POST['wp_cache_status'] = 'none';Then we include and use the WordPress's loader (the exact path may depend on your site's layout on the server).
$wpLoader = realpath(dirname(__FILE__) . '/../../wp-load.php'); require_once($wpLoader);At this point, if there are no errors, we can interact with our site's database.
Step 4 - Get your data
We can use all the APIs provided by WordPress and all the active plugins. This example fetches the most recent posts:
$posts = get_posts(); foreach ($posts as $post) { setup_postdata($post); echo " - "; the_title(); echo "\n"; } // end foreachWe can execute the script with the command:
php -f test-posts.php -- --key=SuperSecretKeyAnd the output would be similar to:
WordPress successfully loaded!- Lorem ipsum dolor sit amet- Consectetur adipisicing elit- Duis aute irure dolor in reprehenderit- ...- Last post of the listA good starting point
By using this simple example as a template, you can do more or less what you want with your blog. The limit is, as always, your fantasy.
If you have any comment and/or suggestion it's highly appreciated, in the mean time you can get the full code from here.
