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


13

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

Код:

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>

У когось є якісь думки / пропозиції?

Відповіді:


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

Для використання get_pagesйому потрібен клас WP. тому wp-blog-header.php був правильним файлом для виклику.
goldenapples

Намагався робити саме так, як ви вказали тут із правильним HTTP_HOST, SERVER_NAMEі REQUEST_URI. Також спробував і з wp-blog-header.phpі wp-load.php. Те саме повідомлення про помилку, яке зазначено в оригінальному запитанні у всіх випадках. Я запускаю це у своєму тематичному каталозі - це має значення?
ggutenberg

@goldenapples, він потрібен для завантаження, але він не потребує його запуску, що є додатковим матеріалом, який робить wp-blog-header.php.
prettyboymp

2
@dosboy, це ти працюєш на сервері чи на розробницькому комп’ютері під керуванням mamp? Якщо ви запускаєте його на комп'ютері, на якому встановлено більше одного екземпляра mysql, є ймовірність, що ваше середовище може використовувати інший екземпляр php та mysql з командного рядка, ніж це робиться для звичайних запитів http.
prettyboymp

Хм ... розумне мислення. Це поле для розробників, на якому працює MAMP. Але у мене немає доступу до SSH до моєї виробничої коробки. Будь-яка ідея, як вказати екземпляр MySQL на моїй машині розробки, щоб переконатися, що сценарій працює?
ggutenberg

4

Ви можете використовувати команду wp-cli eval-file :

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

Це спочатку завантажить середовище WP, а потім запустіть файл.


1

Прийнята відповідь від @prettyboymp - це про найкориснішу та унікальну інформацію про доступ до WordPress із сценарію php, який я знайшов в Інтернеті. Для мене це чудово працювало з ядром WP 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;
}

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');
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.