Site icon Kamil Wyremski

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!

Exit mobile version