Przejdź do treści
🛠 Jak dodać jedno pole niestandardowe do wielu postów w WordPress

🛠 Jak dodać jedno pole niestandardowe do wielu postów w WordPress

Strona na WordPress rozrosła się do setek postów i w każdym trzeba dodać nowe pole niestandardowe. Ręczne otwieranie każdego posta i klikanie „Aktualizuj" to zajęcie na pół dnia, co najmniej.

Szczególnie jeśli dopracowują Państwo motyw lub podłączają wtyczkę SEO, która do działania potrzebuje jednakowego klucza meta_key dla całej listy postów. Panel administracyjny WordPress nie ma przycisku „zastosuj do wszystkich", ale daje dwie ścieżki rozwiązania tego problemu za pomocą kodu.

Poniżej oba sposoby z gotowymi fragmentami kodu: szybki (jedno zapytanie SQL na całą partię) i prosty (pętla po ID z natywną funkcją add_post_meta). Proszę wybrać odpowiedni do zadania.

Dwa monitory wyświetlają różne bloki kodu źródłowego i pliki deweloperskie na stanowisku pracy programisty

💡 Szybki przegląd:

  • Masowe dodanie tego samego pola niestandardowego do wszystkich postów można wykonać przez add_post_meta w pętli, 4 linijki kodu.
  • Jeśli postów są setki i ważna jest szybkość, jedno bezpośrednie INSERT do tabeli wp_postmeta przez niestandardową funkcję.
  • Oba sposoby działają przez functions.php motywu lub wtyczkę Code Snippets. Proszę zrobić kopię zapasową bazy przed uruchomieniem jakiegokolwiek SQL.

Po co dodawać jedno pole do wielu postów naraz

Pola niestandardowe (custom fields, czyli post meta) przechowują dodatkowe informacje o wpisie: liczbę wyświetleń, tagi do wewnętrznej filtracji, flagę „w ulubionych", ID powiązanego produktu. Wszystko, co nie mieści się w standardowych polach post_title i post_content.

Zazwyczaj pole dodaje się punktowo: otwierają Państwo post, znajdują blok „Pola niestandardowe" w edytorze, wpisują klucz i wartość. Ale kiedy pole ma się pojawić we wszystkich 200 postach naraz, ręczna metoda odpada.

Typowe scenariusze, w których potrzebna jest masowość:

  • Podłączyli Państwo motyw potomny, a on wykorzystuje get_post_meta($post_id, 'featured_post', true) do oznaczania popularnych wpisów. Bez masowego wypełnienia stare posty nie trafią do wyników.
  • Audyt SEO wymagał ustawienia noindex dla określonego typu treści przez metapole, a nie przez robots.txt.
  • Migracja z innego silnika: dane ze starego CMS trafiły do CSV i trzeba je załadować do wp_postmeta dla tysięcy wpisów.

WordPress nie ma standardowej funkcji add_multiple_posts_meta. Ale są dwie sprawdzone ścieżki, proszę wybrać w zależności od sytuacji.

Sposób 1. Jedno zapytanie SQL dla wszystkich postów

Najszybszy sposób, bezpośredni INSERT do tabeli wp_postmeta w jednej transakcji. Zamiast 200 osobnych zapytań do bazy wykonują Państwo jedno i działa ono w milisekundy.

Poniżej funkcja add_multiple_posts_meta, która przyjmuje tablicę ID postów i powtarza sygnaturę natywnej add_post_meta: te same parametry, ta sama kolejność.

Proszę dodać kod do functions.php motywu potomnego lub przez wtyczkę Code Snippets. Funkcja sama sprawdza, czy takie pole już istnieje w poście (jeśli przekazano $unique = true) i odfiltrowuje nieprawidłowe ID.

1if( !function_exists( 'add_multiple_posts_meta' ) ){
2 function add_multiple_posts_meta( $post_ids, $meta_key, $meta_value, $unique = false ){
3
4 // Якщо ключ або ID не задані — виходимо
5 if( !$meta_key || empty( $post_ids ) ){
6 return false;
7 }
8
9 // Один пост — віддаємо нативній add_post_meta
10 if( is_numeric( $post_ids ) || ( is_array( $post_ids ) && count( $post_ids ) === 1 ) ){
11 return add_post_meta(
12 is_array( $post_ids ) ? $post_ids[0] : $post_ids,
13 $meta_key,
14 $meta_value,
15 $unique
16 );
17 }
18
19 global $wpdb;
20
21 // Відсіюємо невалідні ID та дублікати
22 $valid_post_ids = array_unique(
23 array_filter( $post_ids, function( $post_id ) use ( $wpdb, $meta_key, $unique ){
24 return $post_id
25 && is_numeric( $post_id )
26 && get_post_status( $post_id )
27 && (
28 ! $unique
29 || ! $wpdb->get_var( $wpdb->prepare(
30 "SELECT COUNT(*) FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s",
31 $post_id,
32 $meta_key
33 ) )
34 );
35 } )
36 );
37
38 if( ! count( $valid_post_ids ) ){
39 return false;
40 }
41
42 // Санітизація
43 $meta_key = wp_unslash( $meta_key );
44 $meta_value = sanitize_meta( $meta_key, wp_unslash( $meta_value ), 'post' );
45
46 // Збираємо дані та форматні рядки для одного INSERT
47 $insert_data = [];
48 $insert_formats = [];
49
50 foreach( $valid_post_ids as $post_id ){
51 array_push( $insert_data, $post_id, $meta_key, $meta_value );
52 $insert_formats[] = '(%d, %s, %s)';
53 }
54
55 $sql_string = "INSERT INTO $wpdb->postmeta (`post_id`, `meta_key`, `meta_value`) VALUES "
56 . implode( ', ', $insert_formats );
57
58 // ... розпаковує масив в окремі аргументи для prepare
59 $sql_query = $wpdb->prepare( $sql_string, ...$insert_data );
60
61 return $wpdb->query( $sql_query );
62 }
63}

Co tu się dzieje linijka po linijce. Sprawdzenie !function_exists, zabezpieczenie przed konfliktem: jeśli inna wtyczka już zadeklarowała funkcję o tej nazwie, nie będzie błędu krytycznego. Blok is_numeric($post_ids) przekazuje pojedyncze ID do natywnej add_post_meta, dzięki czemu ta sama funkcja działa i z jednym postem, i z tablicą. Filtr array_filter odrzuca ID szkiców, usuniętych wpisów i te, dla których unikalne pole już istnieje. Sanityzacja przez wp_unslash i sanitize_meta jest obowiązkowa: bez niej zserializowane dane i znaki specjalne popsują zapytanie.

*Ważna kwestia z ...$insert_data.* Operator ... (splat) rozwija tablicę w płaską listę argumentów. Bez niego $wpdb->prepare otrzyma jeden argument-tablicę zamiast zestawu (%d, %s, %s) i zapytanie zakończy się błędem liczby placeholderów. PHP 5.6+ (WordPress wymaga co najmniej 7.0, więc śmiało).

Jak używać

Proszę przekazać tablicę ID postów, klucz i wartość zwykłym wywołaniem. Czwarty parametr, flaga unikalności: true nie doda pola, jeśli już istnieje w poście.

1$post_ids = [ 1, 2, 3, 42, 108 ];
2$meta_key = 'featured_priority';
3$meta_value = 'high';
4$unique = false; // проставить усім, навіть якщо поле вже було
5
6add_multiple_posts_meta( $post_ids, $meta_key, $meta_value, $unique );

Uruchamianie takiego wywołania jest wygodne przez hook init (raz, potem usunąć) lub przez WP-CLI komendą wp eval-file. Po wykonaniu koniecznie proszę usunąć kod z functions.php, w przeciwnym razie funkcja będzie się uruchamiać przy każdym ładowaniu strony.

Sposób 2. Pętla po ID z add_post_meta

Jeśli nie chcą Państwo dotykać SQL bezpośrednio, proszę użyć natywnego add_post_meta w pętli. Kod jest czterokrotnie krótszy i całkowicie opiera się na jądrze WordPress.

1$post_ids = [ 1, 2, 3, 42, 108 ];
2$meta_key = 'featured_priority';
3$meta_value = 'high';
4$unique = false;
5
6foreach( $post_ids as $post_id ){
7 add_post_meta( $post_id, $meta_key, $meta_value, $unique );
8}

Pętla przechodzi po tablicy i dla każdego ID wywołuje add_post_meta. Funkcja sama sprawdza istnienie wpisu, unikalność klucza (jeśli ustawiono $unique = true) i poprawność danych, żadna dodatkowa walidacja nie jest potrzebna.

Wydajność. Na setkach postów różnica w porównaniu z zapytaniem SQL jest niezauważalna. Ale jeśli mają Państwo 5 000 wpisów, każde wywołanie add_post_meta generuje osobny INSERT, plus wewnętrzne hooki (added_post_meta, update_post_meta_cache). Przy takich wolumenach pierwszy sposób z jednym zapytaniem zadziała 10-20 razy szybciej.

Do jednorazowych operacji na kilkudziesięciu postach proszę brać pętlę, nie komplikować.

Porównanie podejść

Kryterium

Sposób 1 (jeden SQL)

Sposób 2 (pętla add_post_meta)

Szybkość na 5 000 postów

~0,2 s (1 zapytanie)

~3-6 s (5 000 zapytań)

Złożoność kodu

~50 linii z walidacją

4 linie

Bezpieczeństwo

Potrzebna ręczna sanityzacja

add_post_meta robi wszystko sam

Hooki WordPress

Nie są wywoływane

added_post_meta, update_post_meta_cache

Kiedy wybierać

Masowa migracja, import z CSV

Jednorazowe poprawki, do stu postów

Uniwersalna zasada: jeśli postów jest mniej niż sto i operacja jest jednorazowa, pętla. Jeśli chodzi o regularną synchronizację lub migrację tysięcy wpisów, tylko bezpośrednie zapytanie z przygotowaną funkcją.

⁉️🤔 Często zadawane pytania

Czy można dodać pole wybiórczo, tylko do postów z określonej kategorii?

Tak. Proszę pobrać ID postów przez get_posts z parametrem 'category' => ID_рубрики, a następnie przekazać tablicę do dowolnego z dwóch powyższych sposobów. Dla tysięcy postów proszę dodać 'numberposts' => -1 i 'fields' => 'ids', zapytanie zwróci tylko tablicę ID, bez ładowania obiektów.

Oto gotowy przykład: $post_ids = get_posts( [ 'category' => 5, 'numberposts' => -1, 'fields' => 'ids', 'post_type' => 'post' ] );. Następnie wywołanie add_multiple_posts_meta($post_ids, ...) lub pętla z add_post_meta.

Co zrobić, jeśli potrzebna jest różna wartość pola dla różnych postów?

Masowe wstawianie tutaj nie zadziała. Proszę utworzyć tablicę asocjacyjną [ ID_поста => значение ] i przejść po niej w pętli z add_post_meta lub update_post_meta. Jedna wartość dla wszystkich, SQL, różne dla różnych, tylko pętla.

Dla 50+ postów z unikalnymi wartościami proszę użyć update_post_meta zamiast add_post_meta: nie tworzy duplikatów, jeśli pole już istnieje.

Czy bezpiecznie jest pisać zapytania SQL bezpośrednio do wp_postmeta?

Bezpiecznie przy dwóch warunkach. Po pierwsze: zawsze proszę przepuszczać dane przez $wpdb->prepare, który escapuje znaki specjalne i blokuje SQL injection. Po drugie: proszę zrobić pełną kopię zapasową bazy przed uruchomieniem. Jeden błędny UPDATE bez WHERE i wp_postmeta jest wyczyszczona dla wszystkich wpisów.

Komenda do backupu przez WP-CLI: wp db export backup-before-meta.sql. Przywrócić: wp db import backup-before-meta.sql.

Czym add_post_meta różni się od update_post_meta?

add_post_meta dodaje nowy wiersz w wp_postmeta, nawet jeśli klucz już istnieje w poście, powstanie duplikat. update_post_meta sprawdza istnienie klucza: jeśli jest, aktualizuje wartość, jeśli nie ma, tworzy. Do masowego wypełniania, gdzie klucz jest jeden na post, add_post_meta z $unique = true daje ten sam efekt.

W praktyce: add_post_meta($id, 'views', 0, true) raz utworzy pole i więcej go nie ruszy. update_post_meta($id, 'views', $count) nadpisze wartość przy każdym wywołaniu.

Gdzie umieścić kod, w motywie czy wtyczce?

Do jednorazowych operacji, w functions.php motywu potomnego, z natychmiastowym usunięciem po wykonaniu. Do powtarzalnych zadań proszę przygotować jako wtyczkę Must-Use (folder wp-content/mu-plugins/) lub dodać w Code Snippets z oznaczeniem „Run once". Kod w aktywnym motywie bez usunięcia będzie odpytywał bazę przy każdym ładowaniu strony, to zbędne obciążenie.

Co wybrać do Państwa zadania

Praktyka pokazuje: 9 na 10 przypadków załatwia pętla z add_post_meta. To cztery linijki kodu, natywna funkcja i żadnych niespodzianek.

Bezpośrednie zapytanie SQL jest uzasadnione w dwóch sytuacjach: masowa migracja (tysiące postów, czas jest cenny) i okresowa synchronizacja, gdzie kontrolują Państwo sanityzację na wejściu. W pozostałych przypadkach proszę nie komplikować.

Co zrobić teraz:

  • Jeśli trzeba dodać pole do ≤100 postów, proszę skopiować pętlę z drugiego sposobu, podstawić swoje ID i uruchomić.
  • Jeśli postów jest kilka tysięcy, proszę wziąć funkcję z pierwszego sposobu, ale najpierw przetestować na kopii strony.
  • W każdym wariancie, kopia zapasowa bazy przed uruchomieniem. To nie przestroga, a zasada.

A jakim sposobem zazwyczaj dodają Państwo pola niestandardowe: przez panel administracyjny, kod czy wtyczkę typu ACF? Proszę napisać w komentarzach, ciekawie porównać podejścia.