【问题标题】:Wordpress database insert() and update() - using NULL valuesWordpress 数据库 insert() 和 update() - 使用 NULL 值
【发布时间】:2011-02-05 12:28:34
【问题描述】:

Wordpress 附带处理 CRUD 操作的 wpdb 类。我感兴趣的这个类的两个方法是insert()(CRUD 中的 C)和update()(CRUD 中的 U)。

当我想在 mysql 数据库列中插入 NULL 时出现问题 - wpdb 类将 PHP 空变量转义为空字符串。如何告诉 Wordpress 使用实际的 MySQL NULL 而不是 MySQL 字符串?

【问题讨论】:

    标签: php mysql wordpress null crud


    【解决方案1】:

    wpdb insert()update()NULL 值一起使用,它在多年前就已修补,但从未在 Codex 中提及。

    在你的情况下:

    $wpdb->update(
        'table',
        array( 
            'status' => null,
        ), 
        array( 'id' => 1 ), 
        null, 
        '%d'
    );
    

    参考:https://core.trac.wordpress.org/ticket/15158#no0

    【讨论】:

      【解决方案2】:

      我在Wordpress StackExchange 论坛上找到了这个,对我来说效果很好。

      // Add a filter to replace the 'NULL' string with NULL
      add_filter( 'query', 'wp_db_null_value' );
      
      global $wpdb;
      $wpdb->update(
          'table',
          array( 
              'status' => 'NULL',
          ), 
          array( 'id' => 1 ) 
      );
      
      // Remove the filter again:
      remove_filter( 'query', 'wp_db_null_value' );
      

      而函数 wp_db_null_value 是:

      /**
      * Replace the 'NULL' string with NULL
      * 
      * @param  string $query
      * @return string $query
      */
      
      function wp_db_null_value( $query )
      {
        return str_ireplace( "'NULL'", "NULL", $query ); 
      }
      

      因为在我的情况下我不能使用 $db->prepare() 函数...

      【讨论】:

        【解决方案3】:

        我尝试编辑此处列出的其他解决方案之一,因为它导致格式数组与数据数组未对齐,但失败了。

        这是一个从最新版本的 wordpress 修改 wpdb 的解决方案,以便允许使用 insert() 和 update() 将空值插入和更新到 SQL 表中:

        /*
         * Fix wpdb to allow inserting/updating of null values into tables
         */
        class wpdbfixed extends wpdb
        {
            function insert($table, $data, $format = null) {
                $type = 'INSERT';
                if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) )
                    return false;
                $this->insert_id = 0;
                $formats = $format = (array) $format;
                $fields = array_keys( $data );
                $formatted_fields = array();
                foreach ( $fields as $field ) {
                    if ( !empty( $format ) )
                        $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
                    elseif ( isset( $this->field_types[$field] ) )
                        $form = $this->field_types[$field];
                    else
                        $form = '%s';
        
                    //***Steve Lee edit begin here***
                    if ($data[$field]===null) {
                        unset($data[$field]); //Remove this element from array, so we don't try to insert its value into the %s/%d/%f parts during prepare().  Without this, array would become shifted.
                        $formatted_fields[] = 'NULL';
                    } else {
                        $formatted_fields[] = $form; //Original line of code
                    }
                    //***Steve Lee edit ends here***
                }
                $sql = "{$type} INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")";
                return $this->query( $this->prepare( $sql, $data ) );
            }
        
            function update($table, $data, $where, $format = null, $where_format = null)
            {
                if ( ! is_array( $data ) || ! is_array( $where ) )
                    return false;
        
                $formats = $format = (array) $format;
                $bits = $wheres = array();
                foreach ( (array) array_keys( $data ) as $field ) {
                    if ( !empty( $format ) )
                        $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
                    elseif ( isset($this->field_types[$field]) )
                        $form = $this->field_types[$field];
                    else
                        $form = '%s';
        
                    //***Steve Lee edit begin here***
                    if ($data[$field]===null)
                    {
                        unset($data[$field]); //Remove this element from array, so we don't try to insert its value into the %s/%d/%f parts during prepare().  Without this, array would become shifted.
                        $bits[] = "`$field` = NULL";
                    } else {
                        $bits[] = "`$field` = {$form}"; //Original line of code
                    }
                    //***Steve Lee edit ends here***
                }
        
                $where_formats = $where_format = (array) $where_format;
                foreach ( (array) array_keys( $where ) as $field ) {
                    if ( !empty( $where_format ) )
                        $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
                    elseif ( isset( $this->field_types[$field] ) )
                        $form = $this->field_types[$field];
                    else
                        $form = '%s';
                    $wheres[] = "`$field` = {$form}";
                }
        
                $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
                return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) );
            }
        
        }
        global $wpdb_allow_null;
        $wpdb_allow_null = new wpdbfixed(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
        

        将此代码插入到始终可以运行的位置,例如您的functions.php,然后照常使用新的全局$wpdb_allowed_null->insert() 和->update()。

        我更喜欢这种方法而不是覆盖默认的 $wpdb,以便保留其他 Wordpress 和其他插件所期望的 DB 行为。

        【讨论】:

          【解决方案4】:

          这是您的问题的解决方案。在“wp-content”文件夹中,创建一个名为“db.php”的文件并将这段代码放入其中:

          <?php
          
          // setup a dummy wpdb to prevent the default one from being instanciated
          $wpdb = new stdclass();
          
          // include the base wpdb class to inherit from
          //include ABSPATH . WPINC . "/wp-db.php";
          
          
          class wpdbfixed extends wpdb
          {
              function insert($table, $data, $format = null) {
                  $formats = $format = (array) $format;
                  $fields = array_keys($data);
                  $formatted_fields = array();
                  $real_data = array();
                  foreach ( $fields as $field ) {
                      if ($data[$field]===null)
                      {
                          $formatted_fields[] = 'NULL';
                          continue;
                      }
                      if ( !empty($format) )
                          $form = ( $form = array_shift($formats) ) ? $form : $format[0];
                      elseif ( isset($this->field_types[$field]) )
                          $form = $this->field_types[$field];
                      else
                          $form = '%s';
                      $formatted_fields[] = "'".$form."'";
                      $real_data[] = $data[$field];
                  }
                  //$sql = "INSERT INTO <code>$table</code> (<code>&quot; . implode( '</code>,<code>', $fields ) . &quot;</code>) VALUES (" . implode( ",", $formatted_fields ) . ")";
                  $sql = "INSERT INTO $table (" . implode( ',', $fields ) . ") VALUES (" . implode( ",", $formatted_fields ) . ")";
                  return $this->query( $this->prepare( $sql, $real_data) );
              }
          
              function update($table, $data, $where, $format = null, $where_format = null)
              {
                  if ( !is_array( $where ) )
                      return false;
          
                  $formats = $format = (array) $format;
                  $bits = $wheres = array();
                  $fields = (array) array_keys($data);
                  $real_data = array();
                  foreach ( $fields as $field ) {
                      if ($data[$field]===null)
                      {
                          $bits[] = "$field = NULL";
                          continue;
                      }
                      if ( !empty($format) )
                          $form = ( $form = array_shift($formats) ) ? $form : $format[0];
                      elseif ( isset($this->field_types[$field]) )
                          $form = $this->field_types[$field];
                      else
                          $form = '%s';
                      $bits[] = "$field = {$form}";
          
                      $real_data[] = $data[$field];
                  }
          
                  $where_formats = $where_format = (array) $where_format;
                  $fields = (array) array_keys($where);
                  foreach ( $fields as $field ) {
                      if ( !empty($where_format) )
                          $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
                      elseif ( isset($this->field_types[$field]) )
                          $form = $this->field_types[$field];
                      else
                          $form = '%s';
                      $wheres[] = "$field = {$form}";
                  }
          
                  $sql = "UPDATE $table SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
          
                  return $this->query( $this->prepare( $sql, array_merge($real_data, array_values($where))) );
              }
          
          }
          
          $wpdb = new wpdbfixed(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
          ?>
          

          通过这种方式,您可以将 null 值 与 wpdb 一起使用!

          【讨论】:

          • 非常感谢分享这个;多年后,我用它向 wp-db.php 添加了一小段调试代码(检测长度溢出并返回实际错误而不是忽略它)。
          【解决方案5】:

          如果您希望它兼容,您必须显示列并提前确定是否允许 NULL。如果允许,则如果值为空($v),则在查询中使用 val = NULL。

          $foo = null;
          $metakey = "Harriet's Adages";
          $metavalue = "WordPress' database interface is like Sunday Morning: Easy.";
          
          if ($foo == null) {
          $wpdb->query( $wpdb->prepare( "
              INSERT INTO $wpdb->postmeta
              ( post_id, meta_key, meta_value, field_with_null )
              VALUES ( %d, %s, %s, NULL )", 
                  10, $metakey, $metavalue ) );
          } else {
          $wpdb->query( $wpdb->prepare( "
              INSERT INTO $wpdb->postmeta
              ( post_id, meta_key, meta_value, field_with_null )
              VALUES ( %d, %s, %s, %s)", 
                  10, $metakey, $metavalue, $foo ) );
          }
          

          【讨论】:

          • 我将表创建为自定义插件的一部分 - 有问题的列确实接受 NULL 值。
          • 除了更改插件的 NULL/空语义之外,这几乎是唯一的解决方案。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-10-18
          • 1970-01-01
          • 1970-01-01
          • 2014-03-19
          • 2011-01-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多