Чуть больше года назад я написал статью о том, как использовать WP_Meta_Query всякий раз, когда у вас есть набор ключей, которые вы хотите использовать для извлечения информации из базы данных.
А как насчет случая, когда у вас есть несколько разных ключей, которые приведут к созданию очень длинного массива для класса WP_Meta_Query? Например, что, если бы вам пришлось перебрать набор данных еще до того, как был задан запрос?
На каком-то уровне может показаться, что естественным было бы сделать следующее:
- перебрать коллекцию ключей,
- динамически наращивать результаты,
- объединить их в единый набор результатов,
- затем работайте с тем, что вам дали.
Но не звучит ли это немного громоздко (не говоря уже о медленности)?
Когда дело доходит до использования WordPress API, я делаю все возможное, чтобы придерживаться его, прежде чем обращаться, скажем, непосредственно к базе данных, но бывают случаи, когда имеет смысл написать необработанный запрос, а не просто написать какой-то умный код. чтобы заставить WordPress API работать.
Прежде чем перейти к обоснованию того, почему я сделал то, что я сделал, я хочу объяснить проблему и подход. Это, вероятно, убережет кого-то от преждевременного перехода к комментариям.
Этот снимок экрана не имеет ничего общего с запросом. Просто снимок IDE для развлечения.
Так вот:
- У меня есть стандартный массив значений, которые в конечном итоге используются, чтобы помочь взять метаданные и создать из них собственный тип записи (поскольку они были импортированы из стороннего источника).
- Я большой сторонник параметризации запросов (и, следовательно, использования prepare ), чтобы убедиться, что данные правильно запрашиваются в базе данных. К сожалению, этого не происходило при попытке выполнить этот запрос. Я объясню, почему позже в этом посте.
- Таким образом, взять массив и преобразовать его в строку полезно, но это все еще не решает проблему, почему не работает стандартная функция подготовки .
С учетом сказанного, я собираюсь объяснить несколько вещей:
- почему я решил использовать массив для хранения значений метаданных,
- почему я использовал implode для преобразования их в строку,
- почему я не использую подготовку для обработки запроса.
О значениях метаданных
Причина сохранения метаданных в массиве в качестве свойства класса заключается в том, что этот массив может меняться со временем.
То есть нам может потребоваться импортировать дополнительные сторонние данные, нам может потребоваться удалить сторонние данные или нам может потребоваться внести некоторые изменения во все, что есть.
Когда эти данные хранятся в одном месте, управление будущими версиями кода становится намного проще.
Взрыв массива
Всякий раз, когда вы выполняете запрос к базе данных и вам нужно работать с массивом данных, вы можете использовать WP_Meta_Query и использовать каждый ключ как часть массива аргументов.
Но если у вас есть относительно большой набор данных, то вам сначала нужно пройтись по ним всем, затем вы должны создать запрос, затем вы должны его обработать.
И после того, как вы все это сделали, я не уверен, что написанный код не был получен за счет производительности. Вот почему иногда я предпочитаю использовать wpdb.
Без использования подготовки
Теперь, при взаимодействии непосредственно с базой данных, я стараюсь убедиться:
- У меня есть на это веская причина,
- Я использую параметризованные запросы.
Но я некоторое время работал с этим конкретным набором данных, пытаясь использовать все варианты разработки WordPress, о которых я знаю (включая разговоры об этом с несколькими коллегами), чтобы попытаться сделать эту работу наилучшим образом.
Однако этого не происходило. И вот тогда я наткнулся на следующую страницу Кодекса :
В 99% случаев вместо этого вы можете использовать $wpdb->prepare(), и это рекомендуемый метод. Эта функция предназначена для использования только в тех редких случаях, когда вы не можете легко использовать $wpdb->prepare(). Одним из примеров является подготовка массива для использования в предложении IN.
И это именно то, что я пытался сделать: я искал мета-таблицу сообщений, где значения мета-ключей содержались в массиве.
Итак, вот как я все это проработал.
Во- первых, я создал массив для хранения различных мета-ключей, которые, как я знаю, мне в конечном итоге понадобятся (хотя значение ключей не имеет значения для целей этого поста):
<?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,
];
Затем я преобразовал их в строку, готовую для MySQL. Конечно, это не пользовательский ввод, и он используется в предложении IN, поэтому его нельзя использовать в операторе подготовки :
<?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, '","' ). '"';
}
Наконец, я создал запрос и получил результаты:
<?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;
}
И вот как я закончил работу с массивами, свойством класса и настройкой моего запроса.
Это лучший способ работать с запросами WordPress с предложениями IN? Я не уверен, но, учитывая мой опыт, то, что я прочитал, и то, как это работает, я доволен конечным результатом.