Acceda a la API de WordPress fuera de WordPress (línea de comandos PHP)

13

Tengo un script PHP que necesito ejecutar como trabajo cron. Sin embargo, este script necesita el acceso a la API de WP ( get_pages(), get_post_meta()y get_permalink()en concreto). He seguido las instrucciones en http://codex.wordpress.org/Integrating_WordPress_with_Your_Website , pero fue en vano.

Código:

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

Sin embargo, cuando ejecuto php -q this_file.phpdesde la línea de comandos obtengo el siguiente resultado:

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

Alguien tiene alguna idea / sugerencia?

Ggutenberg
fuente

Respuestas:

17

WordPress espera que las variables $ _SERVER se configuren como si fuera una solicitud web normal. Además, sugeriría cargar wp-load.php en lugar de wp-blog-header.php, ya que probablemente no necesite la clase WP o el cargador de plantillas para ejecutarse. Así es como normalmente inicio los scripts que necesito para interactuar con WP desde la línea de comandos:

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

Actualización 2018:

Hoy en día, Wordpress no requiere $ _SERVER en absoluto. Si simplemente necesita acceder a las funciones de la API de Wordpress (por ejemplo, leer / escribir en la base de datos), todo lo que necesita es:

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

# your code goes here...
prettyboymp
fuente
Para usarlo get_pages, necesita la clase WP. entonces wp-blog-header.php fue el archivo correcto para llamar.
goldenapples
Intenté hacer exactamente lo que especificó aquí con la correcta HTTP_HOST, SERVER_NAMEy REQUEST_URI. También probé con ambos wp-blog-header.phpy wp-load.php. Mismo mensaje de error como se indica en la pregunta original en todos los casos. Estoy ejecutando esto desde mi directorio de temas, ¿eso importa?
ggutenberg
@goldenapples, lo necesita para cargar, pero no lo necesita para ejecutarse, que es lo que hace wp-blog-header.php.
prettyboymp
2
@dosboy, ¿estás ejecutando esto en un servidor o una computadora de desarrollo con mamp? Si lo está ejecutando en una computadora que tiene más de una instancia de mysql instalada, existe la posibilidad de que su entorno esté usando una instancia de php y mysql diferente de la línea de comandos que con las solicitudes http normales.
prettyboymp
Hmm ... pensamiento inteligente. Es un cuadro de desarrollo que ejecuta MAMP. Pero no tengo acceso SSH a mi caja de producción. ¿Alguna idea de cómo especificar una instancia de MySQL en mi máquina de desarrollo solo para asegurarme de que el script funciona?
ggutenberg
4

Puede usar el comando wp-cli eval-file :

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

Esto primero cargará el entorno WP, luego ejecutará su archivo.

scribu
fuente
1

La respuesta aceptada por @prettyboymp es sobre la información más útil y única sobre el acceso a WordPress desde un script php que he encontrado en la web. Funcionó perfectamente para mí con WP core 3.7.1, luego 3.9 lo rompió.

El problema fue que wp-load.phpcambió la forma en que probó REQUEST_URIuna ruta válida. Pero afortunadamente también agregó un nuevo filtro para permitir el cortocircuito de la prueba.

Así que para restaurar la funcionalidad de la respuesta en 3.9, he añadido define('SUNRISE', 'on');a wp-config.php, y el archivo creado wp-content/sunrise.phpcon este contenido:

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;
}
hollín
fuente
0

Una variación de la respuesta de @ prettyboymp podría ser:

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');
}
despertar
fuente