Обновление нескольких строк в $wpdb с помощью IN, как в обычном SQL
Мне интересно, возможно ли использовать $wpdb->update
для обновления значений в нескольких строках с помощью условия IN
, как в "обычном" SQL.
Я хочу реализовать что-то вроде этого примера:
UPDATE [table]
SET [column_1] = [updated_value]
WHERE [column_2] IN ([comma_separated_ids])
Я искал информацию о том, как это можно сделать, но пока не нашел ни одного вопроса или статьи, объясняющей, возможно ли это.
Пока я использую обычный запрос, но было бы удобнее иметь простое однострочное решение.

Как видно в исходном коде, знак =
жестко прописан в методе wpdb::update()
, поэтому по умолчанию нельзя использовать оператор IN
в методе обновления.
Самый простой способ обойти это ограничение — использовать wpdb::query()
с вашим SQL-запросом, но обязательно правильно экранируйте все значения.
Пример:
function wpdb_update_in( $table, $data, $where, $format = NULL, $where_format = NULL ) {
global $wpdb;
$table = esc_sql( $table );
if( ! is_string( $table ) || ! isset( $wpdb->$table ) ) {
return FALSE;
}
$i = 0;
$q = "UPDATE " . $wpdb->$table . " SET ";
$format = array_values( (array) $format );
$escaped = array();
foreach( (array) $data as $key => $value ) {
$f = isset( $format[$i] ) && in_array( $format[$i], array( '%s', '%d' ), TRUE ) ? $format[$i] : '%s';
$escaped[] = esc_sql( $key ) . " = " . $wpdb->prepare( $f, $value );
$i++;
}
$q .= implode( $escaped, ', ' );
$where = (array) $where;
$where_keys = array_keys( $where );
$where_val = (array) array_shift( $where );
$q .= " WHERE " . esc_sql( array_shift( $where_keys ) ) . ' IN (';
if( ! in_array( $where_format, array('%s', '%d'), TRUE ) ) {
$where_format = '%s';
}
$escaped = array();
foreach( $where_val as $val ) {
$escaped[] = $wpdb->prepare( $where_format, $val );
}
$q .= implode( $escaped, ', ' ) . ')';
return $wpdb->query( $q );
}
Затем используйте функцию следующим образом:
wpdb_update_in(
'posts', // таблица
array( 'post_author' => '1', 'post_status' => 'draft' ), // данные
array( 'post_author' => array( '2', '3', '4', '5' ) ), // условие
array( '%d', '%s' ), // формат
'%d' // формат условия
);
Выполненный SQL-запрос будет выглядеть так:
UPDATE wp_posts
SET post_author = 1, post_status = 'draft'
WHERE post_author IN (2, 3, 4, 5)

Я не так много работал с WordPress, поэтому не был знаком с исходным кодом. Обязательно добавлю это в закладки для будущих ссылок. Мне нравится ваше решение, и я отмечу его как ответ.

Жестко закодировано в WordPress и сложно в использовании...

Я нашел это полезным, но похоже, что некоторые вещи изменились с момента написания этого ответа. Во-первых, сигнатура функции implode()
поменяла порядок параметров начиная с PHP 7.4. Также я не смог понять, что такое $wpdb->$table
? В итоге убрал это.

За 10 лет многое изменилось, да :)
$wpdb->$table
— это способ получить полное имя таблицы. Вам не следует использовать, например, "wp_content"
, а лучше $wpdb->content
, потому что префикс может измениться, а в мультисайте он обязательно изменится.
Это не изменилось. Но теперь у нас есть заполнитель %i
для экранирования имён таблиц.
Что касается %f
, да, он был добавлен относительно недавно вместе с упомянутым выше %i
.
