$wpdb не вставляет NULL в столбец таблицы

5 мая 2014 г., 16:01:47
Просмотры: 17K
Голосов: 15

Когда я пытаюсь сделать так:

$wpdb->update(
    'table',
    ['status' => NULL],
    ['id' => 1] 
);

В столбце status оказывается пустая строка '', а не NULL, как ожидалось.

Столбец определен как NULL в структуре таблицы. Я также пробовал методы $wpdb->query и $wpdb->prepare, но результат тот же. Что я делаю не так?

0
Все ответы на вопрос 3
1
12

Обновление:

Начиная с 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###'.

5 мая 2014 г. 17:48:19
Комментарии

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

dmsnell dmsnell
12 июл. 2016 г. 01:47:19
0

wpdb->update по умолчанию обрабатывает все типы данных как строки.

format
(array|string) (необязательный) Массив форматов, которые будут применены к каждому значению в $data. Если передана строка, этот формат будет использоваться для всех значений в $data. Если параметр опущен, все значения в $data будут обрабатываться как строки, если не указано иное в wpdb::$field_types.

http://codex.wordpress.org/Class_Reference/wpdb#UPDATE_rows

Вы можете указать формат, но допустимыми спецификаторами являются:

Возможные значения формата: %s для строки; %d для целого числа и %f для числа с плавающей запятой. (Подробности см. ниже.) Если параметр опущен, все значения в $where будут обрабатываться как строки.

http://codex.wordpress.org/Class_Reference/wpdb#UPDATE_rows

Вы можете изучить исходный код и разобраться в процессе.

Если вы измените метод wpdb->prepare (на тестовом сервере, который периодически очищается :)), чтобы вывести SQL прямо перед возвратом, вы увидите, что замена происходит до вызова wpdb->prepare:

string(48) "UPDATE `table` SET `status` = %s WHERE `id` = %s"

Хотя, как отметил @birgire, это может быть ограничением метода prepare, которое привело к такой замене.

5 мая 2014 г. 17:48:54
0

Я хочу подробнее объяснить, как это сделать в 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'
            ]);
26 нояб. 2017 г. 21:23:52