13

I have a PHP script that I need to run as a cron job. However this script needs access to the WP API (get_pages(), get_post_meta() and get_permalink() specifically). I've followed the instructions at http://codex.wordpress.org/Integrating_WordPress_with_Your_Website, but to no avail.

Code:

require_once('../../../wp-blog-header.php');
$args = array(
    'child_of' => 2083
);
$pages = get_pages($args);

However when I run php -q this_file.php from the command-line I get the following output:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Database Error</title>

</head>
<body>
    <h1>Error establishing a database connection</h1>
</body>
</html>

Anyone have any thoughts/suggestions?

4 Answers 4

17

WordPress expects the $_SERVER variables to be setup as if it were a normal web request. Also, I would suggest loading wp-load.php instead of wp-blog-header.php since you probably don't need the WP class or the template loader to run. Here is how I normally start any scripts I need to interact with WP from command line:

define('DOING_AJAX', true);
define('WP_USE_THEMES', false);
$_SERVER = array(
    "HTTP_HOST" => "mysite.com",
    "SERVER_NAME" => "mysite.com",
    "REQUEST_URI" => "/",
    "REQUEST_METHOD" => "GET"
);
require_once('current/wp-load.php');

Update 2018:

Nowadays Wordpress doesn't require $_SERVER at all. If you simply need to access Wordpress API functions (e.g. to read/write to the database), all you need is:

require_once('current/wp-load.php');

# your code goes here...
7
  • To use get_pages, he does need the WP class. so wp-blog-header.php was the right file to call. Commented Dec 14, 2010 at 16:49
  • Tried doing exactly as you've specified here with the correct HTTP_HOST, SERVER_NAME and REQUEST_URI. Also tried with both wp-blog-header.php and wp-load.php. Same error message as stated in original question in all instances. I'm running this from my theme directory - does that matter?
    – ggutenberg
    Commented Dec 14, 2010 at 17:23
  • @goldenapples, he needs it to load, but he doesn't need it to run, which is the extra stuff that wp-blog-header.php does. Commented Dec 14, 2010 at 18:14
  • 2
    @dosboy, are you running this on a server or a development computer running mamp? If you're running it on a computer that has more than one instance of mysql installed, there is a chance that your environment may be using a different php and mysql instance from the command line than it does with normal http requests. Commented Dec 14, 2010 at 18:18
  • Hmm... clever thinking. It is a dev box running MAMP. But I don't have SSH access to my production box. Any idea how to specify a MySQL instance on my dev machine just to make sure the script is working?
    – ggutenberg
    Commented Dec 14, 2010 at 18:34
5

You can use the WP-CLI eval-file command:

@daily /usr/bin/wp --path=/path/to/wp/ eval-file /path/to/that_file.php

This will first load the WP environment, then run your file.

1

The accepted answer by @prettyboymp is about the most helpful and unique information about accessing wordpress from a php script that I have found on the web. It worked perfectly for me with WP core 3.7.1, then 3.9 broke it.

The problem was that wp-load.php changed the way it tested the REQUEST_URI for a valid path. But fortunately it also added a new filter to allow short-circuiting the test.

So to restore the functionality of the answer in 3.9, I added define('SUNRISE', 'on'); to wp-config.php, and created file wp-content/sunrise.php with this content:

add_filter('pre_get_site_by_path', 'my_pre_get_site_by_path', 10, 5 /*null, $domain, $path, $segments, $paths*/ );
    function my_pre_get_site_by_path($input, $domain, $path, $segments, $paths) {
    if ($path == '/') {
        return get_blog_details(array('domain' => $domain, 'path' => PATH_CURRENT_SITE), false);
    }
    return $input;
}
0

A variation to @prettyboymp's answer could be:

if(in_array(php_sapi_name(), ['cli', 'cli-server'])) {
    foreach($_SERVER as $key => $val) {
        if(!getenv($key))
             putenv($key.'='.$val);
    }

    if(!getenv('HTTP_HOST'))
        putenv('HTTP_HOST='.gethostname());

    if(!getenv('SERVER_ADDR'))
        putenv('SERVER_ADDR='.gethostbyname(gethostname()));

    if(!getenv('REQUEST_URI'))
        putenv('REQUEST_URI=/');

    if(!getenv('REQUEST_METHOD'))
        putenv('REQUEST_METHOD=GET');
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.