Доступ к WordPress API за пределами WordPress (командная строка PHP)

13

У меня есть PHP-скрипт, который мне нужно запустить как задание cron. Однако этот сценарий необходим доступ к WP API ( get_pages(), get_post_meta()и в get_permalink()частности). Я следовал инструкциям на http://codex.wordpress.org/Integrating_WordPress_with_Your_Website , но безрезультатно.

Код:

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

Однако при запуске php -q this_file.phpиз командной строки я получаю следующий вывод:

<!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>

У кого-нибудь есть какие-нибудь мысли / предложения?

ggutenberg
источник

Ответы:

17

WordPress ожидает, что переменные $ _SERVER будут настроены так, как если бы это был обычный веб-запрос. Кроме того, я бы предложил загрузить wp-load.php вместо wp-blog-header.php, так как вам, вероятно, не нужен класс WP или загрузчик шаблонов для запуска. Вот как я обычно запускаю любые скрипты, которые мне нужны для взаимодействия с WP из командной строки:

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');

Обновление 2018:

В настоящее время Wordpress вообще не требует $ _SERVER. Если вам просто нужен доступ к функциям Wordpress API (например, для чтения / записи в базу данных), все, что вам нужно, это:

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

# your code goes here...
prettyboymp
источник
Для использования get_pagesему нужен класс WP. поэтому wp-blog-header.php был правильным файлом для вызова.
золотые яблоки
Пытался делать точно так, как вы указали здесь с правильным HTTP_HOST, SERVER_NAMEи REQUEST_URI. Также пробовал с обоими wp-blog-header.phpи wp-load.php. То же сообщение об ошибке, как указано в исходном вопросе во всех случаях. Я запускаю это из моего каталога тем - это имеет значение?
Ггутенберг
@goldenapples, ему нужно, чтобы он загружался, но ему не нужно, чтобы он запускался, что является дополнительным материалом, который делает wp-blog-header.php.
prettyboymp
2
@ Dosboy, вы запускаете это на сервере или на компьютере разработчика под управлением mamp? Если вы запускаете его на компьютере, на котором установлено более одного экземпляра mysql, есть вероятность, что ваша среда может использовать другой экземпляр php и mysql из командной строки, чем при обычных запросах http.
prettyboymp
Хм ... умное мышление. Это Dev Dev работает с MAMP. Но у меня нет доступа SSH к моей производственной коробке. Любая идея, как указать экземпляр MySQL на моем компьютере разработчика, чтобы убедиться, что скрипт работает?
Ггутенберг
4

Вы можете использовать команду wp-cli eval-file :

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

Это сначала загрузит среду WP, а затем запустит ваш файл.

scribu
источник
1

Принятый ответ @prettyboymp о наиболее полезной и уникальной информации о доступе к WordPress из php-скрипта, которую я нашел в Интернете. У меня отлично работало с WP core 3.7.1, потом 3.9 сломал.

Проблема заключалась в том, что он wp-load.phpизменил способ проверки REQUEST_URIправильности пути. Но, к счастью, он также добавил новый фильтр, позволяющий замкнуть накоротко тест.

Таким образом , чтобы восстановить функциональные возможности ответа на 3.9, я добавил define('SUNRISE', 'on');к wp-config.php, и создал файл wp-content/sunrise.phpс этим содержимым:

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;
}
sootsnoot
источник
0

Вариант ответа @ prettyboymp может быть следующим:

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');
}
ewake
источник