CodeIgniter将所有字段作为字符串返回


CodeIgniter returns all fields as strings

我在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使用正确的数据类型(text s作为字符串,integer s作为整数,timestamp s作为DateTime对象,等等)返回字段?

我在PHP 5.3.15上使用CodeIgniter 2.1.4。

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

方法1:
在php扩展中启用mysqlnd驱动程序。这将主要解决你的问题。如果没有,则尝试方法2

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

  1. 从系统>数据库>驱动程序>mysqli_driver.php打开mysqli_driven.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

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

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

    $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,
        ],
        ...
    );

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

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

混合Kalaivanan和Firze的答案,但使用的是mysqli,而不是PDO。

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

创建/更改应用程序/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列,它们将不起作用,它们将始终返回零。因为驱动程序上有个错误。请参阅:带有MYSQLI_OPT_INT_AND_FLOAT_NATIVE的mysqlnd无法解释位列。

这对我很有效。如果你想要任意类型转换,你需要在数据集中迭代转换数组的变量。将此功能添加到您的控制器:

<?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->field_data()为您提供了数据集字段的元数据。这样,您就可以使用settype函数"修复"$query->result_array()返回的值。

请记住,根据数据集的大小,这可能是一个相当大的开销,并且只有当返回是任意的时才应该这样做。如果你事先知道类型,那么最好对它们进行相应的强制转换。

我尝试了PDO,它也以字符串的形式返回所有值。

另请参阅:

  • https://gist.github.com/paulera/370fb995988d983909e4a19769ee2f5d
  • http://php.net/manual/en/function.settype.php
  • https://www.codeigniter.com/user_guide/database/metadata.html#retrieve-字段元数据
  • http://php.net/manual/en/mysqli.constants.php

PDO返回具有正确数据类型的值。使用它而不是CodeIgniter的数据库库。

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

这与codeignter无关。

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

1:PHP mysql_fetch_object,所有属性都是字符串

2:是否将MySQL查询结果作为其本地数据类型

我对CodeIgnitor文档的阅读(请参阅http://ellislab.com/codeigniter/user-guide/database/fields.html)就是你想循环浏览字段数据,然后自己决定如何处理这些数据。

我的猜测是,要无缝地做到这一点,你可能需要对他们的数据库和/或查询类进行子类化,这样你就可以让他们做你想做的事情。

在我看来,这并不是一项小工作量的工作,尽管开始可能还不算太糟。

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();

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

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

在您的视图文件中

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

PS:PHP总是以"字符串"的形式输出。如果您想将其强制转换为任何数据类型,例如字符串为整数,请使用(int)$value

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

$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