Zugriff auf die WordPress-API außerhalb von WordPress (Befehlszeilen-PHP)


13

Ich habe ein PHP-Skript, das ich als Cron-Job ausführen muss. Allerdings muss dieses Skript Zugriff auf die WP - API ( get_pages(), get_post_meta()und get_permalink()speziell). Ich habe die Anweisungen unter http://codex.wordpress.org/Integrating_WordPress_with_Your_Website befolgt , aber ohne Erfolg.

Code:

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

Wenn ich jedoch php -q this_file.phpvon der Kommandozeile aus starte, erhalte ich folgende Ausgabe:

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

Hat jemand irgendwelche Gedanken / Vorschläge?

Antworten:


17

WordPress erwartet, dass die $ _SERVER-Variablen so eingerichtet werden, als wäre es eine normale Webanfrage. Außerdem würde ich vorschlagen, wp-load.php anstelle von wp-blog-header.php zu laden, da Sie wahrscheinlich weder die WP-Klasse noch den Template-Loader zum Ausführen benötigen. So starte ich normalerweise alle Skripte, die ich für die Interaktion mit WP benötige, über die Befehlszeile:

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:

Heutzutage benötigt Wordpress überhaupt nicht mehr $ _SERVER. Wenn Sie lediglich auf die Funktionen der Wordpress-API zugreifen müssen (z. B. zum Lesen / Schreiben in der Datenbank), brauchen Sie nur Folgendes:

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

# your code goes here...

Zur Verwendung get_pagesbenötigt er die WP-Klasse. Also war wp-blog-header.php die richtige Datei zum Aufrufen.
Goldenapples

Versuchte genau das tun , wie Sie hier mit dem richtigen angegeben haben HTTP_HOST, SERVER_NAMEund REQUEST_URI. Auch mit beiden wp-blog-header.phpund ausprobiert wp-load.php. In allen Fällen dieselbe Fehlermeldung wie in der ursprünglichen Frage angegeben. Ich rufe dies von meinem Themenverzeichnis aus auf - ist das wichtig?
ggutenberg

@goldenapples, er braucht es zum Laden, aber er braucht es nicht zum Laufen. Das ist das zusätzliche Zeug, das wp-blog-header.php macht.
Prettyboymp

2
@dosboy, läufst du das auf einem Server oder einem Entwicklungscomputer, auf dem mamp läuft? Wenn Sie es auf einem Computer ausführen, auf dem mehr als eine Instanz von mysql installiert ist, verwendet Ihre Umgebung möglicherweise eine andere PHP- und mysql-Instanz als bei normalen http-Anforderungen.
Prettyboymp

Hmm ... kluges Denken. Es ist eine Entwickler-Box, auf der MAMP läuft. Ich habe jedoch keinen SSH-Zugriff auf meine Produktionsbox. Haben Sie eine Idee, wie Sie eine MySQL-Instanz auf meinem Entwicklungscomputer angeben können, um sicherzustellen, dass das Skript funktioniert?
ggutenberg

4

Sie können den Befehl wp-cli verwenden eval-file :

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

Dadurch wird zuerst die WP-Umgebung geladen und dann Ihre Datei ausgeführt.


1

Die akzeptierte Antwort von @prettyboymp handelt von den hilfreichsten und einzigartigsten Informationen zum Zugriff auf WordPress über ein PHP-Skript, das ich im Web gefunden habe. Es funktionierte perfekt für mich mit WP Core 3.7.1, dann brach 3.9 es.

Das Problem war, dass wp-load.phpsich die Art und Weise geändert hat, in der REQUEST_URIein gültiger Pfad ermittelt wurde. Glücklicherweise wurde ein neuer Filter hinzugefügt, um den Test kurzschließen zu können.

So die Funktionalität der Antwort wiederherstellen in 3.9, habe ich define('SUNRISE', 'on');zu wp-config.php, und erstellen Datei wp-content/sunrise.phpmit folgendem Inhalt:

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

Eine Variation der Antwort von @ prettyboymp könnte sein:

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');
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.