Acesse a API do WordPress fora do WordPress (PHP da linha de comando)

13

Eu tenho um script PHP que eu preciso executar como um trabalho cron. No entanto, este script precisa acesso à API WP ( get_pages(), get_post_meta()e get_permalink()especificamente). Eu segui as instruções em http://codex.wordpress.org/Integrating_WordPress_with_Your_Website , mas sem sucesso.

Código:

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

No entanto, quando executo a php -q this_file.phppartir da linha de comando, recebo a seguinte saída:

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

Alguém tem alguma opinião / sugestão?

Ggutenberg
fonte

Respostas:

17

O WordPress espera que as variáveis ​​$ _SERVER sejam configuradas como se fosse uma solicitação da Web normal. Além disso, eu sugiro carregar o wp-load.php em vez do wp-blog-header.php, pois você provavelmente não precisa da classe WP ou do carregador de modelos para executar. Aqui está como eu normalmente inicio os scripts necessários para interagir com o WP na linha de comando:

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

Atualização 2018:

Atualmente, o Wordpress não requer $ _SERVER. Se você simplesmente precisar acessar as funções da API do Wordpress (por exemplo, ler / gravar no banco de dados), tudo o que você precisa é:

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

# your code goes here...
prettyboymp
fonte
Para usar get_pages, ele precisa da classe WP. então wp-blog-header.php era o arquivo certo para chamar.
goldenapples
Tentei fazer exatamente como você especificou aqui com o correto HTTP_HOST, SERVER_NAMEe REQUEST_URI. Também tentei com ambos wp-blog-header.phpe wp-load.php. A mesma mensagem de erro como indicado na pergunta original em todas as instâncias. Estou executando isso no meu diretório de temas - isso importa?
ggutenberg
@ goldenapples, ele precisa carregá-lo, mas ele não precisa ser executado, que é o material extra que o wp-blog-header.php faz.
prettyboymp
2
@dosboy, você está executando isso em um servidor ou em um computador de desenvolvimento executando o mamp? Se você o estiver executando em um computador com mais de uma instância do mysql instalada, é possível que seu ambiente esteja usando uma instância php e mysql diferente da linha de comando do que com as solicitações HTTP normais.
prettyboymp
Hmm ... pensamento inteligente. É uma caixa de desenvolvimento executando o MAMP. Mas não tenho acesso SSH à minha caixa de produção. Alguma idéia de como especificar uma instância do MySQL na minha máquina de desenvolvimento apenas para garantir que o script esteja funcionando?
ggutenberg
4

Você pode usar o comando wp-cli eval-file :

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

Isso primeiro carregará o ambiente WP e, em seguida, execute seu arquivo.

scribu
fonte
1

A resposta aceita por @prettyboymp é sobre as informações mais úteis e exclusivas sobre como acessar o wordpress a partir de um script php que encontrei na web. Funcionou perfeitamente para mim com o WP core 3.7.1, depois o 3.9 quebrou.

O problema foi que wp-load.phpmudou a maneira como testou REQUEST_URIum caminho válido. Mas, felizmente, ele também adicionou um novo filtro para permitir um curto-circuito no teste.

Assim, para restaurar a funcionalidade da resposta em 3,9, acrescentei define('SUNRISE', 'on');a wp-config.php, e criou arquivo wp-content/sunrise.phpcom este conteúdo:

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;
}
fuligem
fonte
0

Uma variação da resposta de @ prettyboymp pode 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');
}
acordar
fonte