Nieco ponad rok temu napisałem post o tym, jak używać WP_Meta_Query, gdy masz zestaw kluczy, których chcesz użyć, aby pomóc w odzyskaniu informacji z bazy danych.
A co z przypadkiem, gdy masz wiele różnych kluczy, które skutkowałyby utworzeniem naprawdę długiej tablicy dla klasy WP_Meta_Query? Na przykład, co by było, gdybyś musiał przejść przez zbiór danych przed skonfigurowaniem zapytania?
Na pewnym poziomie może się wydawać, że naturalną rzeczą do zrobienia byłoby:
- iterować przez kolekcję kluczy,
- dynamicznie budować wyniki,
- połączyć je w jeden zestaw wyników,
- następnie pracuj z tym, co otrzymasz.
Ale czy to nie brzmi trochę nieporęcznie (nie mówiąc już o powolnym)?
Jeśli chodzi o korzystanie z API WordPress, robię, co w mojej mocy, aby się go trzymać, zanim porozmawiam, powiedzmy, bezpośrednio z bazą danych, ale są też sytuacje, w których sensowne jest napisanie surowego zapytania niż napisanie jakiegoś sprytnego kodu aby uruchomić API WordPress.
Zanim przejdę do uzasadnienia, dlaczego zrobiłem to, co zrobiłem, chcę wyjaśnić problem i podejście. Prawdopodobnie uchroni to kogoś przed przedwczesnym wskakiwaniem do komentarzy.
Ten zrzut ekranu nie ma nic wspólnego z zapytaniem. Tylko ujęcie IDE dla zabawy.
Więc proszę bardzo:
- Mam standardową tablicę wartości, które są ostatecznie używane do pomocy w pobieraniu metadanych i tworzeniu z nich niestandardowego typu postu (ponieważ zostały zaimportowane z zewnętrznego źródła).
- Jestem wielkim zwolennikiem parametryzacji zapytań (a tym samym używania przygotowania ), aby upewnić się, że dane są poprawnie odpytywane w bazie danych. Niestety tak się nie stało podczas próby wykonania tego zapytania. Wyjaśnię dlaczego w dalszej części tego postu.
- Tak więc weź tablicę i przekonwertuj ją na ciąg znaków jest pomocna, ale nadal nie rozwiązuje problemu, dlaczego standardowa funkcja przygotowania nie działała.
Powiedziawszy to, wyjaśnię kilka rzeczy:
- dlaczego zdecydowałem się użyć tablicy do przechowywania wartości metadanych,
- dlaczego użyłem implode do konwersji ich na łańcuch,
- dlaczego nie używam przygotowania do obsługi zapytania.
O wartościach metadanych
Powodem przechowywania metadanych w tablicy jako właściwości klasy jest to, że ta tablica może się zmieniać w czasie.
Oznacza to, że być może będziemy musieli zaimportować dodatkowe dane osób trzecich, będziemy musieli usunąć dane osób trzecich lub możemy wprowadzić pewne modyfikacje w tym, co jest obecne.
Przechowywanie tych danych w jednym miejscu znacznie ułatwia zarządzanie przyszłymi wersjami kodu.
Implodująca tablica
Za każdym razem, gdy uruchamiasz zapytanie względem bazy danych i musisz pracować z tablicą danych, możesz użyć WP_Meta_Query i użyć każdego klucza jako części tablicy argumentów.
Ale jeśli masz stosunkowo duży zestaw danych, to najpierw musisz je wszystkie przejść w pętli, potem utworzyć zapytanie, a potem je przetworzyć.
A kiedy już to wszystko zrobisz, nie jestem przekonany, że napisany kod nie powstał kosztem wydajności. Dlatego czasami decyduję się na użycie wpdb.
Nie używam przygotowania
Teraz, gdy łączymy się bezpośrednio z bazą danych, staram się upewnić:
- mam ku temu dobry powód,
- Używam zapytań parametrycznych.
Ale od jakiegoś czasu pracuję z tym konkretnym zestawem danych, próbując wykorzystać każdą permutację rozwoju WordPressa, o której wiem (w tym rozmawiając o tym z kilkoma rówieśnikami), aby spróbować zrobić to w najlepszy możliwy sposób.
Jednak to się nie działo. I wtedy natknąłem się na następną stronę Kodeksu :
W 99% przypadków można zamiast tego użyć $wpdb->prepare() i jest to zalecana metoda. Ta funkcja jest do użytku tylko w tych rzadkich przypadkach, w których nie można łatwo użyć $wpdb->prepare(). Jednym z przykładów jest przygotowanie tablicy do użycia w klauzuli IN.
I to właśnie próbowałem zrobić: chciałem przeszukać tabelę meta postu, w której wartości klucza meta były zawarte w tablicy.
Oto jak to wszystko wypracowałem.
Najpierw utworzyłem tablicę do przechowywania różnych metakluczy, o których wiem, że w końcu będę musiał zmapować (chociaż wartość kluczy nie ma znaczenia dla celów tego postu):
<?php
// This is used to maintain a map of data should we need to add more.
$data_types = [
'data_item_one',
'data_item_two',
'...'
'data_item_ten,
];
Następnie przekonwertowałem je na ciąg znaków zgodny z MySQL. To prawda, nie jest to dane wejściowe użytkownika i jest używane w klauzuli IN, więc nie można go użyć w instrukcji przygotowania :
<?php
/**
* Converts the incoming array into a comma-delimited string with
* quotes wrapped around each key.
*
* @access private
*
* @param array $arr The array to convert to a string.
* @return string The string representation of the array delimited by quotes and commas.
*/
private function convert_to_sql_ready_string( $arr) {
return '"'. implode( $arr, '","' ). '"';
}
Na koniec utworzyłem zapytanie i pobrałem wyniki:
<?php
public function get_data_values() {
global $wpdb;
$query = "
SELECT post_id, meta_key, meta_value
FROM $wpdb->postmeta WHERE
meta_key in ($this->data_types) AND
meta_value <> '';
";
$results = $wpdb->get_results( $query );
return $results;
}
I tak skończyłem pracę z tablicami, właściwością class i konfiguracją zapytania.
Czy to najlepszy sposób na pracę z zapytaniami WordPress z klauzulami IN? Nie jestem pewien, ale biorąc pod uwagę moje doświadczenie, to, co przeczytałem i jak to działa, jestem zadowolony z efektu końcowego.