【问题标题】:CodeIgniter returns all fields as stringsCodeIgniter 将所有字段作为字符串返回
【发布时间】:2013-08-06 18:41:37
【问题描述】:

我在 CodeIgniter 中有这个查询:

$query = $this->db->query("
      SELECT u.id
           , u.first_name, u.last_name
           , u.email_address
           , g.id AS group_id
           , g.name AS group_name
           , g.human_readable_name AS human_readable_group_name
        FROM users AS u
        JOIN groups AS g
          ON u.group_id = g.id
    ORDER BY u.last_name
");

return $query->result();

当我var_dump 一行时,我得到了这个:

object(stdClass)#22 (4) {
  ["id"]=>
  string(2) "19"
  ["first_name"]=>
  string(9) "rightfold"
  // etc
}

idgroup_id 在 PostgreSQL 中都是 integers,但 $query->result() 将它们作为字符串返回。如何告诉 CodeIgniter 使用正确的数据类型返回字段(texts 作为字符串,integers 作为整数,timestamps 作为 DateTime 对象,等等...)?

我在 PHP 5.3.15 上使用 CodeIgniter 2.1.4。

【问题讨论】:

  • -1:这是预期的行为。这种形式的返回数据导致的错误是什么?
  • @tereško 这不是投反对票的正当理由,看在上帝的份上!如果有的话,那就是 PHP 再次。
  • @rightfold 你有什么解决办法吗?请更新为答案..面临同样的问题

标签: php codeigniter postgresql


【解决方案1】:

解决此问题的正确方法是在 Codeigniter 驱动程序中设置 mysqli 选项。 以下方法适用于使用mysqli作为数据库驱动程序的人。

方法一:
在您的 php 扩展中启用 mysqlnd 驱动程序。这将主要解决您的问题。如果不是,请尝试方法2

方法2(可能不适用于所有系统):

  1. 从系统 > 数据库 > 驱动程序 > mysqli_driver.php 打开 mysqli_driver.php 文件
  2. 在代码中添加下面一行

代码:

public function db_connect($persistent = FALSE)
    ...
    $this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10); // already exits
    $this->_mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE,TRUE); // add this line
    ...

代码更改后,您会得到如下响应

array (size=16)
    'auth_id' => int 1            
    'role' => string 'admin' (length=5)
    'permissions' => string 'all' (length=3)       
    'login_attempt' => int 0
    'active' => int 1        
    'mobile_verified' => int 1

【讨论】:

  • 谢谢!。这个可行,即使编辑框架代码有点风险。
  • 这是更好的答案,维护一些运行 CI 的遗留代码,这真的很有帮助。不明白为什么其他答案被赞成。
  • Postgresql 怎么样?
【解决方案2】:

这可以使用 PDO 驱动程序来实现。然后将 PDO::ATTR_EMULATE_PREPARES 设置为 false。这可以在 database.php 中完成。我相信使用选项数组是未记录的功能。

更改 application/config/database.php 以使用 PDO 并将 PDO::ATTR_EMULATE_PREPARES 添加到选项:

    $db['default'] = array(
        'dsn'   => 'mysql:host=localhost;dbname={{my_db}};charset=utf8;',
        'username' => 'my_db_user',
        'password' => '123',
        'database' => 'my_db',
        'dbdriver' => 'pdo',
        'options' => [
            PDO::ATTR_EMULATE_PREPARES => false,
        ],
        ...
    );

现在您应该拥有从数据库返回的所有正确类型的数据。

【讨论】:

    【解决方案3】:

    如果您不想更改系统驱动程序,您可以更改您的 application/Core/MY_Controller.php。

    混合使用 KalaivananFirze 答案,但使用 mysqli,而不是 PDO。

    注意:小数在 pdo 和 mysqli 中仍会转换为字符串,因此请改用 Double。

    如下创建/更改application/Core/MY_Controller.php:

    class MY_Controller extends CI_Controller
    { 
        public function __construct()
        {
            parent::__construct();        
            $this->db->conn_id->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
        }
    }
    

    警告:如果您使用 BIT 列,它们将不起作用,它们将始终返回零。因为驱动程序的一个错误。见:mysqlnd with MYSQLI_OPT_INT_AND_FLOAT_NATIVE fails to interpret bit columns.

    【讨论】:

    • $this->db->conn_id->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true); 不适用于生产。
    • @yeshansachithak,检查php和mysql服务器版本是否与您的开发环境相同或更高。
    • Production Env = Server version: 5.6.49-cll-lve - MySQL Community Server (GPL), Development Env = Server version: 5.7.26 - MySQL Community Server (GPL), Both Env has PHP5.6.40
    • 它应该可以工作,php 5.6... 已经有选项 (php.net/manual/pt_BR/mysqli.options.php)。检查您的 /config/database.php 是否在服务器上使用正确的驱动程序: ... 'dbdriver' => 'mysqli' ... 我不知道如何为您提供更多帮助。这可能是您服务器上的 php 或 mysql 中的配置/环境问题。
    【解决方案4】:

    这对我有用。如果您想要任意转换,您需要遍历您的数据集以转换数组的变量。将此函数添加到您的控制器:

    <?php 
    /**
     * Runs a query and returns an array of array, with correct types (as Code
     * Igniter returns everything as string) 
     * @param string $sql
     * @return array Array of array, 1st index is the row number, 2nd is column name
     */
    public function queryWithProperTypes($sql) {
    
      $query = $this->db->query($sql);
      $fields = $query->field_data();
      $result = $query->result_array();
    
      foreach ($result as $r => $row) {
        $c = 0;
        foreach ($row as $header => $value) {
    
          // fix variables types according to what is expected from
          // the database, as CodeIgniter get all as string.
    
          // $c = column index (starting from 0)
          // $r = row index (starting from 0)
          // $header = column name
          // $result[$r][$header] = that's the value to fix. Must
          //                        reference like this because settype
          //                        uses a pointer as param
    
          $field = $fields[$c];
    
          switch ($field->type) {
    
            case MYSQLI_TYPE_LONGLONG: // 8 = bigint
            case MYSQLI_TYPE_LONG: // 3 = int
            case MYSQLI_TYPE_TINY: // 1 = tinyint
            case MYSQLI_TYPE_SHORT: // 2 = smallint
            case MYSQLI_TYPE_INT24: // 9 = mediumint
            case MYSQLI_TYPE_YEAR: // 13 = year
              settype($result[$r][$header], 'integer');
              break;
    
            case MYSQLI_TYPE_DECIMAL: // 0 = decimal
            case MYSQLI_TYPE_NEWDECIMAL: // 246 = decimal
            case MYSQLI_TYPE_FLOAT: // 4 = float
            case MYSQLI_TYPE_DOUBLE: // 5 = double
              settype($result[$r][$header], 'float');
              break;
    
            case MYSQLI_TYPE_BIT: // 16 = bit
              settype($result[$r][$header], 'boolean');
              break;
    
          }
    
          $c = $c + 1;
        }
      }
    
      return $result;
    }
    

    像这样使用它:

    $sql = "SELECT * FROM whatever_table";
    $result = $this->queryWithProperTypes($sql);
    var_dump($result); // check that all types are correctly cast
    

    您可能希望对其进行调整以支持参数,但基本上就是这样:$query-&gt;field_data() 为您提供数据集字段的元数据。这样您就可以使用settype 函数“修复”$query-&gt;result_array() 返回的值。

    请记住,根据数据集的大小,这可能会产生相当大的开销,并且您应该只在返回任意时才这样做。如果您事先知道类型,最好相应地转换它们。

    我尝试过 PDO,它也将所有值作为字符串返回。

    另见:

    【讨论】:

      【解决方案5】:

      PDO 返回具有正确数据类型的值。使用它来代替 CodeIgniter 的数据库。

      【讨论】:

        【解决方案6】:

        不,您无法通过数据类型获得它。

        这与 codeignter 无关。

        MySQL 以字符串形式返回所有内容,NULL 除外。

        1 : PHP mysql_fetch_object, all properties are string?

        2 : Get MySQL Query Results as Their Native Data Type?

        【讨论】:

        • 我没有使用 MySQL,正如您在我的问题中看到的那样。
        【解决方案7】:

        我对 CodeIgnitor 文档(参见 http://ellislab.com/codeigniter/user-guide/database/fields.html)的阅读是,您希望遍历字段数据,然后自行决定如何处理数据。

        我的猜测是,要无缝地做到这一点,您可能希望继承他们的数据库和/或查询类,以便您可以让他们做您想做的事情。

        这并没有让我觉得工作量很小,尽管开始可能还不错。

        【讨论】:

          【解决方案8】:
          This is return sql object 
          
          $query = $this->db->query("
                SELECT u.id
                     , u.first_name, u.last_name
                     , u.email_address
                     , g.id AS group_id
                     , g.name AS group_name
                     , g.human_readable_name AS human_readable_group_name
                  FROM users AS u
                  JOIN groups AS g
                    ON u.group_id = g.id
              ORDER BY u.last_name
          ");
          return $query->result();
          
          This query return multidimensional array as result
          $query = $this->db->query("
                SELECT u.id
                     , u.first_name, u.last_name
                     , u.email_address
                     , g.id AS group_id
                     , g.name AS group_name
                     , g.human_readable_name AS human_readable_group_name
                  FROM users AS u
                  JOIN groups AS g
                    ON u.group_id = g.id
              ORDER BY u.last_name
          ");
          return $query->result_array();
          
          This query return single row as result
          $query = $this->db->query("
                SELECT u.id
                     , u.first_name, u.last_name
                     , u.email_address
                     , g.id AS group_id
                     , g.name AS group_name
                     , g.human_readable_name AS human_readable_group_name
                  FROM users AS u
                  JOIN groups AS g
                    ON u.group_id = g.id
              ORDER BY u.last_name
          ");
          return $query->row_array();
          

          【讨论】:

            【解决方案9】:

            如果您想将此查询作为对象,

            $query->row();
            return $query;
            

            在您的视图文件中

            foreach($row as $query)
            print $row->object_name;
            

            PS:PHP 总是给你输出为“字符串”。如果要将其转换为任何数据类型,例如 string 为 integer ,请使用 (int) $value

            【讨论】:

            • 返回的 fields 在 PHP 中仍然是字符串。
            • 你的意思是它作为字符串返回? php 中的所有 sql 输出都将是输出字符串,它将从 db 中获取并将结果作为字符串提供给您。如果你想做一个数学。计算,或者你可以使用 (int)$row->object_name 的其他东西,但在 php 中数据绑定不是必需的。
            • PostgreSQL 返回不总是字符串的类型化结果。此外,其他数据库接口(例如 Haskell 中的 HDBC 和 Python 中的 psycopg2)返回具有正确类型的字段。
            • 我认为这与数据库无关,因为 mySQL 也保留整数字符串和枚举数据类型,如果您将它与其他编程语言一起使用 MySQL,您还需要分配数据绑定而不是避免捕获异常.
            • 1) 我没有使用 MySQL。 2) PostgreSQL返回字符串。
            【解决方案10】:

            试试这个,它对我很有帮助。

            $query = $this->db->query("
              SELECT u.id
                   , u.first_name, u.last_name
                   , u.email_address
                   , g.id AS group_id
                   , g.name AS group_name
                   , g.human_readable_name AS human_readable_group_name
                FROM users AS u
                JOIN groups AS g
                  ON u.group_id = g.id
            ORDER BY u.last_name ");
            
             // use return $query->result_array();
             // use like this
            
              $data = $query->result_array();
              foreach ($data as $key => $value) {
                  $data['group_id'] = intval($value['group_id']);
                  $data['dateField'] = date_create($value['dateField']);
                }
            
               var_dump($data);
               //or return $data
            

            【讨论】:

              猜你喜欢
              • 2017-10-22
              • 2019-12-15
              • 1970-01-01
              • 2022-01-03
              • 1970-01-01
              • 1970-01-01
              • 2019-12-17
              • 2014-10-14
              • 1970-01-01
              相关资源
              最近更新 更多