Dostęp do WordPress API poza WordPress (PHP z wiersza poleceń)

13

Mam skrypt PHP, który muszę uruchomić jako zadanie CRON. Jednak to skrypt potrzebuje dostępu do API (WP get_pages(), get_post_meta()a get_permalink()konkretnie). Postępowałem zgodnie z instrukcjami na stronie http://codex.wordpress.org/Integrating_WordPress_with_Your_Website , ale bezskutecznie.

Kod:

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

Jednak po uruchomieniu php -q this_file.phpz wiersza polecenia otrzymuję następujące dane wyjściowe:

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

Czy ktoś ma jakieś przemyślenia / sugestie?

Ggutenberg
źródło

Odpowiedzi:

17

WordPress oczekuje, że zmienne $ _SERVER zostaną skonfigurowane tak, jakby były normalnym żądaniem internetowym. Sugeruję również ładowanie wp-load.php zamiast wp-blog-header.php, ponieważ prawdopodobnie nie potrzebujesz do uruchomienia klasy WP ani modułu ładującego szablony. Oto jak zwykle uruchamiam skrypty, których potrzebuję do interakcji z WP z wiersza poleceń:

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

Aktualizacja 2018:

Obecnie Wordpress wcale nie wymaga $ _SERVER. Jeśli potrzebujesz po prostu uzyskać dostęp do funkcji API Wordpress (np. Do odczytu / zapisu do bazy danych), wszystko czego potrzebujesz to:

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

# your code goes here...
prettyboymp
źródło
Aby użyć get_pages, potrzebuje klasy WP. więc wp-blog-header.php był odpowiednim plikiem do wywołania.
goldenapples
Próbowałem robić dokładnie tak, jak określiłeś tutaj z poprawnymi HTTP_HOST, SERVER_NAMEi REQUEST_URI. Próbowałem także z obu wp-blog-header.phpi wp-load.php. Ten sam komunikat o błędzie, jak podano w pierwotnym pytaniu we wszystkich przypadkach. Uruchamiam to z katalogu motywów - czy to ma znaczenie?
ggutenberg
@goldenapples, potrzebuje go do załadowania, ale nie musi go uruchamiać, co jest dodatkową rzeczą, którą robi wp-blog-header.php.
prettyboymp
2
@dosboy, używasz tego na serwerze lub komputerze deweloperskim z uruchomionym mampem? Jeśli uruchamiasz go na komputerze z zainstalowaną więcej niż jedną instancją mysql, istnieje prawdopodobieństwo, że twoje środowisko może korzystać z innej instancji php i mysql niż z wiersza poleceń niż z normalnymi żądaniami HTTP.
prettyboymp
Hmm ... mądre myślenie. To jest dev box z MAMP. Ale nie mam dostępu SSH do mojej skrzynki produkcyjnej. Masz pomysł, jak określić instancję MySQL na moim komputerze deweloperskim, aby upewnić się, że skrypt działa?
ggutenberg
4

Możesz użyć polecenia wp-cli eval-file :

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

Spowoduje to najpierw załadowanie środowiska WP, a następnie uruchomienie pliku.

scribu
źródło
1

Akceptowana odpowiedź @prettyboymp dotyczy najbardziej pomocnych i unikalnych informacji na temat uzyskiwania dostępu do wordpress ze skryptu php, który znalazłem w sieci. Działa dla mnie idealnie z rdzeniem WP 3.7.1, a następnie 3,9 go zepsuło.

Problem polegał na tym, że wp-load.phpzmienił sposób, w jaki testował REQUEST_URIprawidłową ścieżkę. Ale na szczęście dodano także nowy filtr, aby umożliwić zwarcie testu.

Tak aby przywrócić funkcjonalność odpowiedzi w 3.9, dodałem define('SUNRISE', 'on');do wp-config.php, a utworzony plik wp-content/sunrise.phpz tej zawartości:

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
źródło
0

Wariacją odpowiedzi @ prettyboymp może być:

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
źródło