Dodawanie Postów do WordPressa za pomocą API w PHP

WordPress oferuje bogate API, które umożliwia programistom zdalne zarządzanie treścią na stronie. W tym artykule przedstawię kroki, jakie należy podjąć, aby dodać nowy post do WordPressa za pomocą ich API, wykorzystamy skrypt oparty na PHP i Curl. Gotowy kod przykładu znajduje się w repozytorium GitHub: https://github.com/kamilwyremski/wordpress-create-post-by-api

Przygotowanie środowiska

Na początku w panelu administracyjnym naszej strony opartej o WordPress musimy stworzyć hasło aplikacji. Przechodzimy do zakładki Użytkownicy > Profil. Wyszukujemy pole „Nowa nazwa hasła aplikacji”, wpisujemy dowolną nazwę i klikamy na „Dodaj nowe hasło aplikacji”. Zostanie nam wyświetlone pole z nowym hasłem aplikacji.

Teraz w katalogu z naszym projektem tworzymy plik konfiguracyjny .env, który zawierać będzie dane uwierzytelniające oraz adres domeny WordPressa. Poniżej znajdziesz przykład pliku .env:

WORDPRESS_DOMAIN=http://twoja-domena.pl 
WORDPRESS_USERNAME=twoja-nazwa-uzytkownika 
WORDPRESS_PASSWORD=wygenerowane-haslo

Gdzie WORDPRESS_DOMAIN to adres URL naszego bloga, WORDPRESS_USERNAME to nazwa którą wpisaliśmy w polu „Nowa nazwa hasła aplikacji” a hasła to hasło które zostało nam wyświetlone po dodanu hasła aplikacji.

Klasa WordPressAPI

Następnie, tworzymy klasę WordPressApi w pliku wordpress-api.class.php. Poniżej jej szkielet:

class WordPressApi
{
    private $domain;
    private $username;
    private $password;

    public function __construct(string $domain, string $username, string $password)
    {
        $this->domain = $domain;
        $this->username = $username;
        $this->password = $password;
    }

    // Metoda dodająca media do WordPressa
    public function addMedia(string $url, string $filename = '')
    {
        // ... (kod metody)
    }

    // Metoda dodająca tag do postu
    public function addTag(string $tag)
    {
        // ... (kod metody)
    }

    // Metoda zamieniająca linki do obrazków w treści posta
    private function replaceImageLinks(array $matches)
    {
        // ... (kod metody)
    }

    // Metoda dodająca post do WordPressa
    public function addArticle(string $title, string $body = '', string $lid = '', array $tags = [], string $thumbnail_id = null)
    {
        // ... (kod metody)
    }
}

W metodzie konstruktora, która inicjalizuje obiekt WordPressApi ustawiajamy domenę, nazwę użytkownika i hasło ze zmiennych środowiskowych.

Metoda addMedia

Ta metoda służy do dodawania obrazków do WordPressa. Jest ona nam potrzebna jeśli chcemy później móc dodać miniaturkę do wpisu. Poniżej jej kod:

function addMedia(string $url, string $filename = ''){
    $image_data = file_get_contents($url);
    if ($image_data === false) {
      throw new \Exception('Error fetching image from URL.');
    }
    $boundary = uniqid();
    if(!$filename){
      $filename = pathinfo(basename($url), PATHINFO_FILENAME);
    }
    $filename = mb_strtolower($filename);
    $data = "--$boundary\r\n" .
      "Content-Disposition: form-data; name=\"file\"; filename=\"".$filename.".jpg\"\r\n" .
      "Content-Type: image/jpeg\r\n\r\n" .
      "$image_data\r\n" .
      "--$boundary--\r\n";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->domain . '/wp-json/wp/v2/media');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Basic '. base64_encode($this->username . ':' . $this->password),
      'Content-Type: multipart/form-data; boundary=' . $boundary,
      'Content-Length: ' . strlen($data),
    ]);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $response = curl_exec($ch);
    if ($response === false) {
      throw new \Exception(curl_error($ch));
    }
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($http_code == 201) {
      return json_decode($response ,true);
    } else {
      throw new \Exception($http_code);
    }
  }

Metoda ta przyjmuje URL obrazu i opcjonalny argument z nazwą pliku. Pobiera obraz z podanego URL, tworzy dane w formacie wieloczęściowym (multipart form-data) i wysyła żądanie POST do endpointa WordPress API odpowiedzialnego za dodawanie mediów. Następnie zwraca dane o dodanym obrazie. Wykorzystujemy do zapytań CURL.

Jeśli używasz innych formatów obrazków niż .jpg zmień odpowiednio Content Type.

Autoryzujemy żądanie dodając odpowiedni nagłówek (tak będziemy robić także w pozostałych zapytaniach do API): 'Authorization: Basic '. base64_encode($this->username . ':' . $this->password)

Metoda addTag

Ta metoda służy do dodawania tagów do WordPressa. Oto jej kod:

function addTag(string $tag){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->domain . '/wp-json/wp/v2/tags');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Basic '. base64_encode($this->username . ':' . $this->password),
      'Content-Type: application/json; charset=utf-8',
    ]);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      'name' => trim($tag)
    ]));
    $response = curl_exec($ch);
    curl_close($ch);
    if ($response) {
      $new_tag = json_decode($response, true);
      if(!empty($new_tag['id'])){
        return $new_tag;
      }else{
        throw new \Exception('Error creating tag');
      }
    } else {
      throw new \Exception('Error creating tag');
    }
  }

Metoda ta jako parametr przyjmuje nazwę tagu. Wysyła żądanie POST do endpointa WordPress API odpowiedzialnego za dodawanie tagów. Następnie zwraca dane o dodanym tagu.

Metoda replaceImageLinks

To metoda prywatna, która jest używana do zamiany linków do obrazków w treści posta. Każdy obrazek w treści jest dodawany jako media do Wodpressa. Nie jest to niezbędne do działania skryptu ale może być bardzo przydatne jeśli w treści wstawisz linki do obrazków. Oto jej kod:

 private function replaceImageLinks(array $matches) {
  $imageData = $this->addMedia($matches[1]);
  return str_replace($matches[1], $imageData['guid']['rendered'], $matches[0]);
 }

Metoda addArticle

To główna metoda w naszej klasie. Tworzy ona nowy artykuł na podstawie parametrów które przyjmuje: tytuł artykułu, treść (w HTML), wprowadzenie, tablica tagów i ID miniaturki.

Wywołuje wcześniej opisaną metodę replaceImageLinks do zamiany linków do obrazków w treści posta.

Poniżej kod tej metody:

function addArticle(string $title, string $body = '', string $lid = '', array $tags = [], string $thumbnail_id = null){

    $pattern = '/<img[^>]+src=[\'"]([^\'"]+)[\'"][^>]*>/';
    $body = preg_replace_callback($pattern, [$this, 'replaceImageLinks'], $body);

    $postfields = json_encode([
      'status' => 'publish',
      'tags' => $tags,
      'title' => $title,
      'content' => $body,
      'excerpt' => $lid,
      'featured_media' => $thumbnail_id
      ]);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->domain . '/wp-json/wp/v2/posts');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Basic '. base64_encode($this->username . ':' . $this->password),
      'Content-Type: application/json; charset=utf-8',
    ]);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
    $response = curl_exec($ch);
    curl_close($ch);
    if ($response) {
      $post = json_decode($response, true);
      if (!empty($post['id'])) {
        return $post;
      } else {
        throw new \Exception($post['message']);
      }
    }else{
      throw new \Exception('Error communicating with WordPress API.');
    }
  }

Funkcja ta wysyła żądanie POST do endpointa WordPress API odpowiedzialnego za dodawanie postów. Pola są wysyłane w JSON. Ustawiamy status posta na publish (opublikowany), ale możesz to zmienić na draft (szkic).

Te metody wspólnie tworzą funkcjonalność klasy WordPressApi, umożliwiając dodawanie treści, mediów i tagów do WordPressa za pomocą API. Spójrzmy teraz jak je wywoływać.

Formularz wysyłki artykułu

Szkielet strony

Tworzymy szkielet strony www z formularzem wysyłki artykułu. Oto przykładowy kod w pliku index.php:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Add post to WordPress</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>

<body>
  <div class="container mt-5">  
    <h1 class="mb-4">Add post to WordPress</h1>
    <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
      <div class="mb-3">
        <label for="title" class="form-label">Title:</label>
        <input type="text" name="title" required class="form-control" id="title">
      </div>

      <div class="mb-3">
        <label for="lid" class="form-label">LID:</label>
        <textarea name="lid" rows="2" required class="form-control" id="lid"></textarea>
      </div>

      <div class="mb-3">
        <label for="content" class="form-label">Content (in HTML):</label>
        <textarea name="content" rows="4" required class="form-control" id="content"></textarea>
      </div>

      <div class="mb-3">
        <label for="tags" class="form-label">Tags (enter after comma):</label>
        <input type="text" name="tags" class="form-control" id="tags">
      </div>

      <div class="mb-3">
        <label for="thumb" class="form-label">Link to thumb:</label>
        <input type="url" name="thumb" class="form-control" id="thumb">
      </div>

      <button type="submit" class="btn btn-primary">Send</button>
    </form>
  </div>

</body>

</html>

Wykorzystujemy tutaj Bootstrap ale oczywiście nie jest to wymagane.

Wczytywanie zmiennych środowiskowych

W tym celu można użyć gotowych bibliotek. Jako że nie chciałem być od nich zależny w tym małym projekcie stworzyłem skrypt do czytania pliku .env i ustawiania zmiennych środowiskowych. Oto jego kod (dodałem go na samej górze pliku index.php):

<?php

$envFilePath = __DIR__ . '/.env';

if (!file_exists($envFilePath)) {
  die('.env file not found.');
}

$envContent = file_get_contents($envFilePath);
$lines = explode("\n", $envContent);

foreach ($lines as $line) {
  $line = trim($line);
  if (!empty($line) && strpos($line, '=') !== false) {
    list($key, $value) = explode('=', $line, 2);
    $key = trim($key);
    $value = trim($value);
    putenv("$key=$value");
    $_ENV[$key] = $value;
  }
}

require_once('wordpress-api.class.php');

$wordpressApi = new WordPressApi(getenv('WORDPRESS_DOMAIN'), getenv('WORDPRESS_USERNAME'), getenv('WORDPRESS_PASSWORD'));

?>

Załączamy w nim także naszą klasę wordpressAPI i następnie tworzymy obiekt WordPressApi na podstawie danych konfiguracyjnych z pliku .env.

Odbiór danych z formularza i tworzenie artykułu

Na koniec zostało nam sprawdzenie czy formularz został wysłany i wywołanie odpowiednich metod z klasy WordPressApi. Chcemy dodać media, tagi i na końcu sam artykuł. Oto kod (załączam go w body dokumentu nad formularzem):

<?php
    if ($_SERVER["REQUEST_METHOD"] == "POST" and !empty($_POST['title']) and !empty($_POST['lid']) and !empty($_POST['content'])) {
      $thumbnail_id = null;
      if (!empty($_POST['thumb'])) {
        try {
          $thumbnail_id = $wordpressApi->addMedia($_POST['thumb'], $_POST['title'])['id'];
        } catch (\Exception $e) {
          echo ('<p>Error sending image: ' . $e->getMessage() . '</p>');
        }
      }
      $tags = [];
      if (!empty($_POST['tags'])) {
        $new_tags = explode(',', $_POST['tags']);
        foreach ($new_tags as $tag) {
          try {
            $tags[] = $wordpressApi->addTag($tag)['id'];
            echo ('<p>Tag created successfully: ' . $new_tag_name . '</p>');
          } catch (\Exception $e) {
            echo ('<p>Error creating tag: ' . $e->getMessage() . '</p>');
          }
        }
      }

      try {
        $post = $wordpressApi->addArticle($_POST['title'], $_POST['content'], $_POST['lid'], $tags, $thumbnail_id);
        echo('<p>You have successfully added an article. Post ID: ' . $post['id'] . '</p>');
      } catch (\Exception $e) {
        echo('<p>Error: ' . $e->getMessage() . '</p>');
      }
    }
?>

Warunek if ($_SERVER["REQUEST_METHOD"] == "POST" ...) sprawdza, czy formularz został wysłany metodą POST i zawiera wymagane pola.

Jeśli użytkownik podał link do obrazu ($_POST['thumb']), próbujemy dodać to media do WordPressa za pomocą metody addMedia z klasy WordPressApi. Jeśli dodawanie obrazu zakończy się sukcesem, otrzymamy jego ID.

Jeśli użytkownik podał tagi ($_POST['tags']), oddzielone od siebie przecinkami, dzielimy je na pojedyncze tagi. Każdy tag próbujemy dodać do WordPressa za pomocą metody addTag z klasy WordPressApi.

Następnie próbujemy dodać artykuł do WordPressa, wywołując metodę addArticle z klasy WordPressApi. W przypadku sukcesu, wyświetlamy komunikat o pomyślnym dodaniu artykułu wraz z ID nowego posta.

Podsumowanie

Mam nadzieję, że ten wpis pomoże Wam w tworzeniu postów na WordPressie za pomocą swojego skryptu PHP. Gotowy kod znajduję się w repozytorium https://github.com/kamilwyremski/wordpress-create-post-by-api

Pamiętaj, żeby po skopiowaniu utworzyć własny plik .env z adresem URL, loginem i hasłem aplikacji.

Miłego kodowania!

Ta strona używa ciasteczek (cookies), dzięki którym nasz serwis może działać lepiej. Więcej informacji

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close