<rmcreative>

RSS

Yii: читаем пустые значения как null

7 мая 2011

Для того, чтобы Yii читал пустые значения как null, а не как пустую строку достаточно добавить один параметр в конфигурацию компонента db:

'db'=>array(
  'connectionString' => 'mysql:host=localhost;dbname=test',
  'username' => 'root',
  'password' => '',
  'charset' => 'utf8',
 
  'nullConversion' => PDO::NULL_EMPTY_STRING,
),

Комментарии RSS

  1. №4559
    Тормоз
    Тормоз 07 мая 2011 г., 23:04:34

    А зачем?

  2. №4560
    Миша
    Миша 08 мая 2011 г., 0:55:22

    Вероятно потому что null и "" это совсем разные значения... Согласись. Это может казаться не очевидным но ситуация вносящая ясность рано или поздно подвернется.

  3. №4561
    Тормоз
    Тормоз 08 мая 2011 г., 1:41:42

    Ну так для пустого значения мне как раз более логичным кажется пустота, а не null :) А с неочевидностью беда, всё равно она останется в голове.

  4. №4563
    Creo
    Creo 08 мая 2011 г., 3:16:38

    Невероятно важная штука. Раньше использовал для этого поведение. Берем на вооружение. Самое интересное, что эта возможность была всегда в CDbConnection. Не доглядел :(

  5. №4572
    Tokolist
    Tokolist 09 мая 2011 г., 1:52:03

    Преимущество EEnsureNullBehavior в том что он работает не только для строк, но и для других типов, плюс работает не глобально а только в тех моделях, где он подключен.

  6. №4575
    Sam
    Sam 09 мая 2011 г., 14:12:07

    Тормоз, тогда так:

    'nullConversion' => PDO::NULL_TO_STRING,
  7. №4587
    mrix
    mrix 10 мая 2011 г., 14:32:00

    У меня не работает (Windows + PHP 5.2)

  8. №4588
    Sam
    Sam 10 мая 2011 г., 15:48:48

    mrix, что именно?

  9. №4602
    mrix
    mrix 10 мая 2011 г., 20:54:25

    Как были пустые строки, так и остаются. В БД записывается "", а не NULL.

  10. №4612
    Sam
    Sam 10 мая 2011 г., 22:29:35

    mrix, а поле в базе случаем не как NOT NULL объявлено?

  11. №4622
    mrix
    mrix 11 мая 2011 г., 8:11:43

    mrix, а поле в базе случаем не как NOT NULL объявлено?

    Нет, DEFAULT NULL. Проверял и на VARCHAR, и на TEXT:

    CREATE TABLE posts
    (
    ...
        `source` VARCHAR(200) DEFAULT NULL COMMENT 'источник',
    ...
    );
    

    Вот сохраняю модель с пустым полем "source" - записывается пустая строка:

    F2w7xR10.png

    Руками в БД могу выставить NULL:

    5PXUbemV.png

  12. №4629
    Sam
    Sam 11 мая 2011 г., 16:48:19

    mrix, хм, надо будет посмотреть в чём тут дело.

  13. №4632
    mrix
    mrix 11 мая 2011 г., 19:18:43

    Оно в БД записывает, как указывается. А вот обратно в PHP возвращает NULL вместо пустых строк. Я думал, что и в БД пишется NULL. Так было бы лучше. Например, COUNT считал бы по-другому.

    Вот код:

    $db->execute('INSERT INTO t (val) VALUES (:v)', array('v' => ''));
    $db->execute('INSERT INTO t (val) VALUES (:v)', array('v' => null));
    $db->execute('INSERT INTO t (val) VALUES (:v)', array('v' => 'a'));
    $db->execute('INSERT INTO t (val) VALUES (:v)', array('v' => '2'));
    $db->execute('INSERT INTO t (val) VALUES (:v)', array('v' => '0'));
    $db->execute('INSERT INTO t (val) VALUES (:v)', array('v' => "\x00"));
    $db->execute('INSERT INTO t (val) VALUES (:v)', array('v' => ""));
     
    $rows = $db->query('SELECT val FROM t');
    echo '<pre>' . var_export($rows, true) . '</pre>';

    Возвращает:

    array (
      0 => 
      array (
        'val' => NULL,
      ),
      1 => 
      array (
        'val' => NULL,
      ),
      2 => 
      array (
        'val' => 'a',
      ),
      3 => 
      array (
        'val' => '2',
      ),
      4 => 
      array (
        'val' => '0',
      ),
      5 => 
      array (
        'val' => '' . "\0" . '',
      ),
      6 => 
      array (
        'val' => NULL,
      ),
    )

    А в БД лежит:

    vssvi693.png

  14. №4633
    mrix
    mrix 11 мая 2011 г., 19:25:14

    Забыл указать, что сделал этот пример не Yii. Простейшая "обёртка" PDO:

    /**
     * DB
     * 
     * @package pdonulls
     * @author mrixx
     * @copyright 2011
     * @version $Id$
     * @access public
     */
    class DB
    {
        /**
         * @var PDO
         */
        private $_pdo;
     
        /**
         * DB::__construct()
         * 
         * @return void
         */
        public function __construct($host = 'localhost', $db = 'test', $user = 'root', $password = '')
        {
            $this->_pdo = new PDO
            (
                "mysql:host=$host;dbname=$db", $user, $password,
                array
                (
                    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
                )
            );
     
            $this->_pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING);
        }
     
        /**
         * DB::__destruct()
         * 
         * @return void
         */
        public function __destruct()
        {
            $this->_pdo = null;
        }
     
        /**
         * DB::execute()
         * 
         * @param string $query
         * @param array $params
         * @return boolean
         */
        public function execute($query, $params = array())
        {
            $command = $this->_pdo->prepare($query);
            return $command->execute($params);
        }
     
        /**
         * DB::query()
         * 
         * @param string $query
         * @param array $params
         * @return array
         */
        public function query($query, $params = array())
        {
            $command = $this->_pdo->prepare($query);
            $command->execute($params);
            return $command->fetchAll(PDO::FETCH_ASSOC);
        }
    }
     
     
    $db = new DB();
  15. №4767
    Sam
    Sam 29 мая 2011 г., 22:38:26

    mrix, поправил.

  16. №4770
    vladdis
    vladdis 30 мая 2011 г., 8:51:57

    есть же в модели такое array('note', 'default', 'setOnEmpty' => true, 'value' => null), работает стопудово

  17. №8359
    Мигалыч
    Мигалыч 12 сент. 2013 г., 11:51:05

    Sam, спустя 2 года после твоего ответа столкнулся с такой же проблемой. Но не работает. Т.е. при сохранении пустой строки сохраняется пустая строка, но не NULL. Может быть тут - github.com/yiisoft/yii/blob/1.1.14/framework/db/schema/CDbColumnSchema.php#L138 - стоит делать проверку настроек соединения, и если стоит PDO::NULL_EMPTY_STRING, то возвращать для строки не пустую строку, но NULL ?

  18. №9357
    Wolf Forest
    Wolf Forest 03 нояб. 2014 г., 13:15:50

    Всё работает, добавляешь в правило array('note', 'default', 'setOnEmpty' => true, 'value' => null) и всё работает!

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.