Akses WordPress API Di Luar WordPress (baris perintah PHP)

13

Saya memiliki skrip PHP yang harus saya jalankan sebagai tugas cron. Namun skrip ini membutuhkan akses ke WP API ( get_pages(), get_post_meta()dan get_permalink()khususnya). Saya telah mengikuti instruksi di http://codex.wordpress.org/Integrating_WordPress_with_Your_Website , tetapi tidak berhasil.

Kode:

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

Namun ketika saya menjalankan php -q this_file.phpdari command-line saya mendapatkan output berikut:

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

Adakah yang punya pemikiran / saran?

ggutenberg
sumber

Jawaban:

17

WordPress mengharapkan variabel $ _SERVER disetel seolah-olah itu adalah permintaan web biasa. Juga, saya akan menyarankan memuat wp-load.php daripada wp-blog-header.php karena Anda mungkin tidak memerlukan kelas WP atau loader template untuk dijalankan. Inilah cara saya biasanya memulai skrip yang saya perlukan untuk berinteraksi dengan WP dari baris perintah:

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

Pembaruan 2018:

Saat ini Wordpress tidak memerlukan $ _SERVER sama sekali. Jika Anda hanya perlu mengakses fungsi Wordpress API (mis. Untuk membaca / menulis ke database), yang Anda butuhkan adalah:

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

# your code goes here...
prettyboymp
sumber
Untuk menggunakannya get_pages, ia memang membutuhkan kelas WP. jadi wp-blog-header.php adalah file yang tepat untuk dipanggil.
goldenapples
Sudah mencoba melakukan persis seperti yang Anda tentukan di sini dengan yang benar HTTP_HOST, SERVER_NAMEdan REQUEST_URI. Juga mencoba dengan keduanya wp-blog-header.phpdan wp-load.php. Pesan kesalahan yang sama seperti yang dinyatakan dalam pertanyaan asli dalam semua kasus. Saya menjalankan ini dari direktori tema saya - apakah itu penting?
ggutenberg
@goldenapples, dia membutuhkannya untuk memuat, tetapi dia tidak membutuhkannya untuk dijalankan, yang merupakan hal-hal ekstra yang wp-blog-header.php lakukan.
prettyboymp
2
@dosboy, apakah Anda menjalankan ini di server atau komputer pengembangan yang menjalankan mamp? Jika Anda menjalankannya di komputer yang memiliki lebih dari satu contoh mysql diinstal, ada kemungkinan lingkungan Anda mungkin menggunakan contoh php dan mysql berbeda dari baris perintah daripada dengan permintaan http normal.
prettyboymp
Hmm ... pemikiran cerdas. Ini adalah kotak dev yang menjalankan MAMP. Tapi saya tidak punya akses SSH ke kotak produksi saya. Adakah yang tahu bagaimana menentukan contoh MySQL di mesin dev saya hanya untuk memastikan skrip berfungsi?
ggutenberg
4

Anda dapat menggunakan perintah wp-cli eval-file :

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

Ini pertama-tama akan memuat lingkungan WP, kemudian jalankan file Anda.

scribu
sumber
1

Jawaban yang diterima oleh @prettyboymp adalah tentang informasi yang paling bermanfaat dan unik tentang mengakses wordpress dari skrip php yang saya temukan di web. Ini bekerja dengan baik untuk saya dengan WP core 3.7.1, lalu 3.9 memecahnya.

Masalahnya adalah bahwa wp-load.phpmengubah cara mengujiREQUEST_URI jalur yang valid. Namun untungnya itu juga menambahkan filter baru untuk memungkinkan hubungan pendek tes.

Jadi untuk mengembalikan fungsi jawabannya dalam 3,9, saya menambahkan define('SUNRISE', 'on');untuk wp-config.php, dan membuat file wp-content/sunrise.phpdengan konten ini:

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
sumber
0

Variasi jawaban @ prettyboymp dapat berupa:

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');
}
bangun
sumber