Я работаю над проектом, в котором я создаю собственный тип записи и пользовательские данные, вводимые через мета-блоки, связанные с моим собственным типом записи. По какой-то причине я решил закодировать метаблоки таким образом, чтобы входные данные в каждом метабоксе были частью массива. Например, я храню долготу и широту:
<p>
<label for="latitude">Latitude:</label><br />
<input type="text" id="latitude" name="coordinates[latitude]" class="full-width" value="" />
</p>
<p>
<label for="longitude">Longitude:</label><br />
<input type="text" id="longitude" name="coordinates[longitude]" class="full-width" value="" />
</p>
По какой-то причине мне понравилась идея иметь отдельную запись постмета для каждого метабокса. На save_post
крючке я сохраняю данные примерно так:
update_post_meta($post_id, '_coordinates', $_POST['coordinates']);
Я сделал это, потому что у меня есть три метабокса, и мне нравится просто иметь 3 значения postmeta для каждого поста; однако теперь я понял потенциальную проблему с этим. Я могу захотеть использовать WP_Query только для извлечения определенных сообщений на основе этих мета значений. Например, я могу захотеть получить все сообщения, значения широты которых превышают 50. Если бы у меня были эти данные в базе данных по отдельности, возможно, с использованием ключа latitude
, я бы сделал что-то вроде:
$args = array(
'post_type' => 'my-post-type',
'meta_query' => array(
array(
'key' => 'latitude',
'value' => '50',
'compare' => '>'
)
)
);
$query = new WP_Query( $args );
Поскольку у меня есть широта как часть _coordinates
постмета, это не сработает.
Итак, мой вопрос, есть ли способ использовать meta_query
для запроса сериализованного массива, как у меня в этом сценарии?
источник
Я тоже столкнулся с этой ситуацией. Вот что я сделал:
Надеюсь это поможет
источник
$value
также является идентификатором. В этом случае я предлагаю создать функции для добавления символа в каждый элемент массива перед сохранением данных и другую функцию для удаления символа перед использованием данных. При этом сериализованныйi:2
индекс не следует путать сi:D2
«реальными» данными. Параметр мета-запроса должен стать таким,'value' => sprintf(':"D%s";', $value),
и вы сохраните правильную функциональность этого замечательного ответа!LIKE
- это отличный и быстрый способ выключить ваш сервер (не говоря уже о ложных срабатываниях), вам лучше иметь очень хорошее кэширование.Вы действительно потеряете возможность запрашивать ваши данные любым эффективным способом при сериализации записей в базе данных WP.
Общее снижение производительности и выигрыш, который, по вашему мнению, вы достигаете благодаря сериализации, не будут заметны в какой-то степени. Вы можете получить немного меньший размер базы данных, но стоимость транзакций SQL будет большой, если вы когда-нибудь запросите эти поля и попытаетесь сравнить их любым полезным и осмысленным способом.
Вместо этого сохраните сериализацию для данных, которые вы не собираетесь запрашивать таким образом, но вместо этого будете обращаться к ним только пассивным способом посредством прямого вызова API WP
get_post_meta()
- из этой функции вы можете распаковать сериализованную запись, чтобы получить доступ к ее свойствам массива.На самом деле присваивается значение true, как в;
$meta = get_post_meta( $post->ID, 'key', true );
Возвращает данные в виде массива, доступного для повторения в обычном порядке.
Вы можете сосредоточиться на других оптимизациях баз данных / сайтов, таких как кэширование, минимизация CSS и JS и использование таких сервисов, как CDN, если вам нужно. Назовем лишь некоторые .... Кодекс WordPress является хорошей отправной точкой, чтобы узнать больше по этой теме: ЗДЕСЬ
источник
Я только что имел дело с сериализованными полями и мог запросить их. Не используя meta_query, но используя SQL-запрос.
Сначала запрос ищет запись с совпадающим типом post_type, поэтому количество записей wp_postmeta будет меньше для фильтрации. Затем я добавил оператор where для дальнейшего уменьшения строк путем фильтрации
meta_key
Идентификаторы заканчиваются в массиве по мере необходимости для get_posts.
PS. MySQL v5.6 или выше необходим для хорошей производительности подзапроса
источник
Этот пример действительно помог мне. Это специально для плагина S2Members (который сериализует метаданные пользователя). Но это позволяет вам запрашивать часть сериализованного массива в meta_key.
Это работает с использованием функции MySQL REGEXP.
Вот источник
Вот код, который запрашивает всех пользователей, живущих в США. Я легко изменил его, чтобы запросить одно из моих пользовательских полей регистрации, и он заработал в кратчайшие сроки.
источник
Я думаю, что есть 2 решения, которые могут попытаться решить проблему хранения результатов в виде как String, так и Integer. Однако, как отмечали другие, важно сказать, что невозможно гарантировать целостность результатов, хранящихся в виде целых чисел, поскольку, поскольку эти значения хранятся в виде сериализованных массивов, индекс и значения сохраняются точно по одному и тому же шаблону. Пример:
хранится в виде сериализованного массива, как это
Обратите внимание
i:0
как первая позиция массива иi:37
как первое значение. Картина такая же. Но давайте перейдем к решениям1) РЕГЭКСП РЕШЕНИЕ
Это решение работает для меня независимо от мета-значения, сохраняемого в виде строки или числа / идентификатора. Однако он использует
REGEXP
, что не так быстро, как использованиеLIKE
2) как решение
Я не уверен в разнице в производительности, но это решение, которое использует
LIKE
и работает как для числа, так и для строкиисточник
REGEXP
Это хорошо в определенных ситуациях, но если вы можете использоватьLIKE
, я думаю, что это предпочтительный метод. Старая ссылка, но все еще довольно полезная, по моему мнению: thingsilearn.wordpress.com/2008/02/28/… :-)LIKE
быстрее. Но это решение, которое работает как для строк, так и для чиселLIKE
но работает как для чисел, так и для строк. Я не уверен насчет производительности, потому что нужно сравнивать результаты с помощьюOR
После прочтения нескольких советов по выполнению
WP_Query
фильтрации по сериализованным массивам, вот как я, наконец, сделал это: создав массив значений, разделенных запятыми, используя implode в сочетании с$wpdb
пользовательским запросом SQL, который используетсяFIND_IN_SET
для поиска запрошенного списка с разделителями-запятыми.(это похоже на ответ Томаса, но его производительность немного ниже для SQL-запроса)
1. В functions.php:
В вашем файле functions.php (или где бы вы ни настраивали мета-поле) в
yourname_save_post()
функции используйтесоздать массив, содержащий значения, разделенные запятыми.
Вы также захотите изменить свою выходную переменную в
yourname_post_meta()
функции построения мета-окна администратора на2. В шаблоне PHP-файла:
Тест: если вы запустите a,
get_post_meta( $id );
вы должны увидетьcheckboxArray
массив, содержащий значения, разделенные запятыми, а не сериализованный массив.Теперь мы создаем наш собственный запрос SQL с помощью
$wpdb
.Обратите внимание
FIND_IN_SET
, вот где происходит волшебство.Теперь ... так как я использую
SELECT *
это, возвращает все данные поста, и в немforeach
вы можете получить то, что вы хотите от этого (сделайте,print_r($posts);
если вы не знаете, что включено. Это не устанавливает "цикл" для вы (я предпочитаю это так), но его можно легко изменить, чтобы настроить цикл, если вы предпочитаете (взгляните наsetup_postdata($post);
кодекс, вам, вероятно, придется изменить,SELECT *
чтобы выбрать только идентификаторы постов и$wpdb->get_results
правильный$wpdb
тип - - см. также кодекс для$wpdb
получения информации по этому вопросу).Понятно, что это заняло немного усилий, но так
wp_query
как не поддерживает'compare' => 'IN'
сериализацию или разделение запятыми, эта прокладка - ваш лучший вариант!Надеюсь, это кому-нибудь поможет.
источник
Если вы используете
like
оператор сравнения в своем мета-запросе, он должен нормально работать внутри сериализованного массива.результаты в:
источник
Если мои метаданные имеют тип массива, я использую этот метод для запроса по мета:
источник
Мне стало любопытно, что ответы выше, где
meta_query
нацелены на ключ,latitude
а не_coordinates
. Пришлось пойти и проверить, действительно ли было возможно в мета-запросах нацеливаться на определенный ключ внутри сериализованного массива. :)Это явно не тот случай.
Итак, обратите внимание, что правильный ключ для цели
_coordinates
вместоlatitude
.ЗАМЕТКИ:
Такой подход делает возможным нацеливание только на точные совпадения. Поэтому такие вещи, как все широты больше 50 , невозможны.
Чтобы включить совпадения подстроки, можно использовать
'value' => sprintf(':"%%%s%%";', $value),
. (не проверял)источник
У меня такой же вопрос. Может быть, вам нужен параметр 'type'? Проверьте этот связанный вопрос: запрос пользовательского поля - мета-значение - массив
Возможно, попробуйте:
источник
Я столкнулся с чем-то похожим, когда использовал плагин Magic Fields. Это может сделать трюк
источник
serialize()
в этом случае не требуется ...