#php #mysql #wordpress #woocommerce
#php #mysql #wordpress #woocommerce
Вопрос:
Я новичок в запросах mysql, и у меня возникли проблемы с получением нужной структуры данных. Я надеюсь, что один из вас, ребята, сможет помочь.
У меня есть следующий запрос:
SELECT *
FROM wp_postmeta
WHERE post_id IN (SELECT id from wp_posts WHERE post_type = 'product')
Который просто захватывает все данные из таблицы 2, которые имеют тот же идентификатор, что и продукт в таблице 1. Проблема в том, что результаты возвращаются как:
{meta_id: "37230", post_id: "2549", meta_key: "total_sales", meta_value: "0"}
{meta_id: "37231", post_id: "2549", meta_key: "_virtual", meta_value: "no"}
{meta_id: "37232", post_id: "2549", meta_key: "_tax_status", meta_value: "taxable"}
{meta_id: "37233", post_id: "2549", meta_key: "_visibility", meta_value: "visible"}
{meta_id: "37234", post_id: "2549", meta_key: "_featured", meta_value: "no"}
{meta_id: "37235", post_id: "2549", meta_key: "_weight", meta_value: "0.50"}
{meta_id: "37236", post_id: "2549", meta_key: "_sku", meta_value: "HCS-DGMP"}
{meta_id: "37237", post_id: "2549", meta_key: "_product_attributes", meta_value: "a:0:{}"}
{meta_id: "37238", post_id: "2549", meta_key: "_regular_price", meta_value: "18.99"}
{meta_id: "37239", post_id: "2549", meta_key: "_sale_price", meta_value: ""}
Как вы можете видеть, все они имеют одинаковый идентификатор записи, но возвращаются в виде отдельных объектов. Как я могу изменить свой запрос выше, чтобы все это возвращалось в одном объекте? Я также удалю meta_id
, поскольку это бесполезно.
Комментарии:
1. Выполните цикл по всем массивам и создайте новый массив, ключами которого являются
meta_key
, а значениями являютсяmeta_value
2. @Barmar Хм, это правда. Нет ли способа настроить запрос для этого? Или ваше предложение было бы более эффективным?
3. Что вы имеете в виду под «отдельными объектами»? Результирующие наборы состоят из строк , а не из объектов .
4. @GordonLinoff в зависимости от настроек или режима выборки PHP может возвращать строки как объекты со столбцами в качестве атрибутов объекта. Однако — Эта часть (получение результата в PHP) отсутствует в этом ответе.
Ответ №1:
Начиная с MySQL 5.7.22, вы можете использовать JSON_OBJECTAGG(key, value)
:
SELECT post_id, JSON_OBJECTAGG(meta_key, meta_value) AS meta_data
FROM wp_postmeta
WHERE post_id IN (SELECT id from wp_posts WHERE post_type = 'product')
GROUP by post_id
Это вернет meta_data
как JSON_OBJECT с key: value
парами:
post_id | meta_data
2549 | {"_sku": "HCS-DGMP", "_weight": "0.50", "_virtual": "no", "_featured": "no", "_sale_price": null, "_tax_status": "taxable", "_visibility": "visible", "total_sales": "0", "_regular_price": "18.99", "_product_attributes": "a:0:{}"}
Если ваш сервер не поддерживает JSON_OBJECTAGG()
, я бы использовал PHP-решение:
$postIds = array_unique(array_column($dbResult, 'post_id'));
$posts = [];
foreach ($postIds as $id) {
$posts[$id] = (object)['id' => $id];
}
foreach ($dbResult as $row) {
$posts[$row->post_id]->{$row->meta_key} = $row->meta_value;
}
echo json_encode(array_values($posts), JSON_PRETTY_PRINT);
Результат:
[
{
"id": "2549",
"total_sales": "0",
"_virtual": "no",
"_tax_status": "taxable",
"_visibility": "visible",
"_featured": "no",
"_weight": "0.50",
"_sku": "HCS-DGMP",
"_product_attributes": "a:0:{}",
"_regular_price": "18.99",
"_sale_price": ""
}
]
Пока вы не обрабатываете тысячи строк, я бы не беспокоился о производительности.
Комментарии:
1. О, чувак, это довольно аккуратно, ненавижу застрять на 5.6, который
JSON_OBJECTAGG
кажется полезным2. @MiroslavGlamuzina С 5.6 вы можете эмулировать это с помощью
GROUP_CONCAT
. Но значения могут не содержать двойных кавычек или нулей. Я бы написал PHP-решение, которое не было бы таким ужасно сложным.3. Да, я знаю, но это просто выглядит намного лучше. Да, это было бы не так уж плохо, но этот IMO был бы чище. Просто нужны
json_ecode
,array_combine
и дваarray_columns
, но тогда вам пришлось бы извлекать все эти дополнительные данные D:4. @MiroslavGlamuzina Дополнительные данные — это всего лишь один INT (post_id) на пару ключ-значение — так что не так уж и много. Я мог бы даже предпочесть PHP-решение с более новыми версиями MySQL, потому что оно более гибкое.