$wpdb не вставляет NULL в столбец таблицы
Когда я пытаюсь сделать так:
$wpdb->update(
'table',
['status' => NULL],
['id' => 1]
);
В столбце status
оказывается пустая строка ''
, а не NULL, как ожидалось.
Столбец определен как NULL в структуре таблицы. Я также пробовал методы $wpdb->query
и $wpdb->prepare
, но результат тот же. Что я делаю не так?

Обновление:
Начиная с WordPress 4.4, это теперь поддерживается методами insert
, update
, replace
и delete
класса wpdb
, а тикет #15158 был закрыт с пометкой исправлено.
Спасибо @dmsnell за комментарий об этом обновлении.
С другой стороны, поддержка null
в wpdb::prepare()
в настоящее время закрыта с пометкой не будет исправлено в тикете #12819.
Предыдущий ответ:
NULL
не поддерживается:
Похоже, вам придется написать собственный SQL-запрос для обновления значения на NULL
.
В настоящее время NULL
не поддерживается в $wpdb->prepare()
, который обрабатывает входные данные через функцию форматирования vsprintf.
Ознакомьтесь с этими открытыми тикетами в Trac:
Этим тикетам уже около 4 лет, так что вряд ли стоит ожидать скорой реализации этой функции в ядре ;-)
Как предложил @s_ha_dum, вам следует изучить исходный код.
Возможное решение:
Если вы готовы к экспериментам, можете попробовать следующий подход с фильтром query
:
// Добавляем фильтр для замены строки 'NULL' на NULL
add_filter( 'query', 'wpse_143405_query' );
global $wpdb;
$wpdb->update(
'table',
array(
'status' => 'NULL',
),
array( 'id' => 1 )
);
// Удаляем фильтр:
remove_filter( 'query', 'wpse_143405_query' );
где
/**
* Заменяет строку 'NULL' на NULL
*
* @param string $query
* @return string $query
*/
function wpse_143405_query( $query )
{
return str_ireplace( "'NULL'", "NULL", $query );
}
Возможно, стоит использовать более уникальную строку вместо 'NULL'
, например '###NULL###'
.

поддержка установки NULL
была добавлена в r34737, поэтому больше нет необходимости в обходных решениях

wpdb->update
по умолчанию обрабатывает все типы данных как строки.
format
(array|string) (необязательный) Массив форматов, которые будут применены к каждому значению в $data. Если передана строка, этот формат будет использоваться для всех значений в $data. Если параметр опущен, все значения в $data будут обрабатываться как строки, если не указано иное вwpdb::$field_types
.
Вы можете указать формат, но допустимыми спецификаторами являются:
Возможные значения формата: %s для строки; %d для целого числа и %f для числа с плавающей запятой. (Подробности см. ниже.) Если параметр опущен, все значения в $where будут обрабатываться как строки.
Вы можете изучить исходный код и разобраться в процессе.
Если вы измените метод wpdb->prepare
(на тестовом сервере, который периодически очищается :)), чтобы вывести SQL прямо перед возвратом, вы увидите, что замена происходит до вызова wpdb->prepare
:
string(48) "UPDATE `table` SET `status` = %s WHERE `id` = %s"
Хотя, как отметил @birgire, это может быть ограничением метода prepare
, которое привело к такой замене.

Я хочу подробнее объяснить, как это сделать в WordPress 4.4 и более поздних версиях. Вам нужно установить для элемента данных и формата, который вы хотите сделать нулевым, значение PHP 'null'.
Пример из тикета #15158 выглядит следующим образом:
$wpdb->update($ttable,
[
'user_id' => NULL,
'status' => 'available',
'update_time' => $now->format('Y-m-d H:i:s')
], [
'therapist_id' => $therapist_id,
'user_id' => $user_id,
'start_time' => $ub['start_time']
], [
NULL,
'%s',
'%s'
], [
'%d',
'%d',
'%s'
]);
