Как создать новые колонки таблицы в базе данных? Или использовать массив в метаданных поста
Создаю плагин WordPress, который после активации должен к стандартной таблице wp_posts добавить две колонки positive_users_reaction и negative_users_reaction. В ячейках этих колонок хочу складывать id пользователей которые положительно/негативно оценили каждый пост. Вот код.
function create_rows() { global $wpdb; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $table_name = $wpdb->get_blog_prefix() . 'posts'; $charset_collate = $wpdb->get_charset_collate(); $sql = "ALTER TABLE {$table_name} (ADD COLUMN positive_users_reaction TEXT NOT NULL AFTER comment_count, negative_users_reaction TEXT NOT NULL AFTER positive_users_reaction); {$charset_collate}"; dbDelta($sql); $wpdb->insert( $table_name, array( 'positive_users_reaction' => [], 'negative_users_reaction' => [], ) ); } create_rows();
Подскажите, почему оно ничего не создает и не назначает скобки объекта по умолчанию (Ведь это же правильный стартовый шаблон если надо получать array? Как это поправить что б создавало две колонки?
dbDelta() не работает с ALTER TABLE. Используй $wpdb->query(). Ну и как в комментах ниже написали, лучше метаполя юзать. Не надо родные таблицы ВП использовать для этого, кроме случаев когда вы 100% знаете и понимаете зачем вам именно так нужно.
Вместо {$table_name} должно быть ${table_name}.
Со второй переменной аналогично.
Это не помогло. Да и в документациях оно так пишется
Вам надо делать без затрагивания таблицы, на самом дела это странный подход.
Вместо колонок, вам надо смотреть в сторону метаполей.
https://wp-kama.ru/function/update_post_meta
Это PHP, не JS
Оказывается можно и так и так...
Не помню чтобы видел, что где-то в PHP так писали
${table_name}
.Странно, но я наоборот запомнил именно такой вид написания как в шаблонизации JS.
Мало того, оно даже в редакторах правильно подсвчивается.
Спасибо за совет. Так
Код работает. Можете ещё помочь с второй частью вопроса - Хочу что б изначально в ячейках колонок хранился как-бы шаблон, который указывал что это массивы из значений. Но вот такой код
Не создает некое представление для ячеек. Не могу найти пример где б в mySQL говорилось про хранение массивов в ячейках таблицы базы.
В mySQL нет массивов - есть строки, который могут содержать JSON. Чтобы по умолчанию они там хранились надо в описании колонки указать DEFAULT, как-то так.
Далее в коде всегда обрабатываешь эти значения строк через json_encode() (для записи значения) json_decode() (для получения).
$wpdb->insert() тут вообще не подходит!
ПС: Ну и как писалось выше и учитывая что у вас такие вопросы. Все же лучше хранить это в метаполях...
Спасибо, большое. Не очень понимаю, как в метаполях держать массивы и ещё и работать с ними. С документации понял, что там работают с обычными переменными. Ещё, был бы благодарен если бы объяснили почему так сильно все рекомендуют не трогать стандартные таблицы WP? Кроме вопросов безопасности там есть какие-то опасности?
Потому что в этих таблицах храняться данные меню, других плагинов, типов записей, которые могут не оносится к вашей users_reaction логике. Потому что у этих таблиц есть задокументировання структура, с которой работают и другие плагини и черт знает кто и как может их использовать. Добавление новых полей туда может где-то чтото сломать или может быть какой-то конфликт который сломает работат вашего кода или кода другого плагина. В будущем ВП теоретически может запретить добавлять в эту таблицу свои колонки. Вообще может быть что угодно.
С другой стороны, для любых дополнительных данных записей в WP предусмотрены метаполя, которые также задокументированы и имеют своюлогику, кэшируются и т.д. По сути у вас нет ни одной причины хранить данные массива в основной таблице, а не в таблице метаполей. Вам в любом случае придется с ними работать и писать какой-то кастом под них, и делать это все равно где - в метаполях или для основной таблицы. Так зачем совать данные не туда где для них специально приготовлено место?
Чтобы менять привычную структуру движка, вам нужна веская причина, какая она у вас? просто так хочется? Это не причина - это просто ваше желание не подкрепленное никакой логикой.
В БД вообще нельзя хранить массивы. Там есть только строки и массивы храняться там в виде сериализоыванной, JSON, какой-то вашей кастомной строки, которая при получении парсится и превращается в массив.
Прочитай как работают функции update_post_meta() и get_post_meta(). В значения можно указывать массив и он будет храниться в серриализованном виде в БД. Как вариант можно вручную сохранять туда JSON и работать с ним.
Тут главный вопрос как вообще тебе придется работать с данными, просто сохранять их и потом считывать где нужно - 100% метаполя. Если нужна будет сортировка или выборка по отдельным полям из этого массива, то эти поля нужно сохранять как отдельные метаполя и потом делать сотировку по отедльным метаполям.
Спасибо, за объяснения. С update_post_meta() как-то понятнее не стало. Это получается Надо будет каждый раз получать данные $str=get_post_meta(), потом превращать их в массив str_split($str) добавлять/отнимать значения из этого массива, а потом снова превращать в строку и возвращать в это метополе? Или есть какое-то решение попроще ?
Этот код чего-то не отрабатывает. Отдает 500
Как то так, и в PHP не принято писать верблюжьей нотацией.
Спасибо, буду знать. Как-то не так скрипт обновляет.
При нажатии кнопки новым пользователем идет перезапись параметров, а необходимо дополнение массива данных. Тут явно должно задействоваться значение $prev_value из update_post_meta. Не очень понимаю, как он работает ваша строка
if (!in_array($currentUserId, $data)) $data[] = $currentUserId;
думал, что в meta_value будут храниться значения по типу {1,5,2}
Не понимаю, что тут сложного-то? Ну, потыкай чуть посмотри как работает, я вообще уже молчу что в описании функций есть примеры все которые тебе могут пригодится.
Есть две функции get_post_meta() и update_post_meta(). Одна получает, другая сохраняет что ей дали. Все!
Остальное - твоя логика - как напишешь так и будет работать. Нужно дополнять данные? Так получи то что есть сперва, добавь туда что надо и сохрани что получилось.
Обе функции понимаю если в значении массив (он сериализуется/десереализуется при сохранении/получении). Если нужно не сериализовать, а хранить как JSON, например, то пиши конвертацию туда и обратно отдельно (из коробки эти функции сереализуют массивы, а не в JSON строку первращают их).
Такое впечатление, что не понимаете задачу. Ваш пример не чувствительн к тому, что уже было записано в ячейке (То что я ищу)... Аналогичен тому, что написал el-lable
При вызове вы каждый раз перезаписываете новыми данными, не обращая внимания на то, что там хранилось... Параметр $prev_value из документации не фигурирует. Пример. Вот в 'meta_key' ячейке хранилось значение (ID пользователя поставившего лайк), дальше мы вешаем срабатывания приведенного скрипта на какую-то кнопку. И в вашем случаи в ячейке базы будет храниться значение ID последнего пользователя поставившего лайк. А не всех
PS там что-то с приведением типов не так.
это так не сработает.
если вам нужно знать кто последний совершил некое действо(лайк или дизлайк)
поменяйте эту строку в моем примере с
на
При таком варианте $currentUserId у вас будет всегда последним в масиве, и это всегда позволит получать вам последнего пользователя, если он был конечно, из него(массива)
нет, это не то что необходимо. el-lable скрипт который вы описали работает так -> заходит пользователь (id=1) на страницу читает пост, жмет кнопку Понравилось в базу в ячейку пишется вот такое a:1:{i:0;i:1;} Приходит следующий пользователь (id=2) на ту же страницу, читает пост, нажимает кнопку Понравилось теперь в ячейке базы находиться a:1:{i:0;i:2;} так оно отображает... Так понятно ? А по хорошему после второго пользователя там должно было быть [1,2] (ну или ассоциативный массив, не важно) после третьего [1,2,3] где цифры - id пользователей которые нажали кнопку Понравиться.
Какая вам хрен разница что по факту хранится в ячейке таблицы БД?
Вы получаете данные get_post_meta() - в виде массива, и записываете их с помощью update_post_meta() тоже массивом, ничего с данными при передачи-получении конвертировать или как-то преобразовывать не нужно, эти матоды это делают сами.
И в каком формате хранятся данные в ячейке таблицы, сериализованные или в виде json, да хоть в XML-е - на кой ляд вам это нужно?
Конечно чувствителен, еще раз тот же пример с комментариями в которых видно где и как он чувствителен:
Спасибо за объяснение строчек кода. Вопросы всё же остались. После первого захода, в ячейку массива записало
a:1:{i:0;i:1;} после второго пользователя с другим ID в ячейке уже было - a:2:{i:0;i:1;i:1;i:4;} после третьего пользователя a:3:{i:0;i:1;i:1;i:4;i:2;i:3;} Может чего не понимаю, но это не очень похоже на стандартные объект php... ключ-значения по разным элементам. Это такая особенность WordPress? Не понимаю как это отфильтровывать. Допустим, что б один и тот же пользователь не имел возможность добавить ID в массив больше одного раза.
Ага, всё дошло сериализованый массив. Уникальные значения через $data = array_unique( $data ); Ещё раз всем спасибо.