16

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

我在 PHP 5.3.15 上使用 CodeIgniter 2.1.4。

4

10 回答 10

13

解决此问题的正确方法是在 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
于 2018-06-16T07:32:06.267 回答
7

这可以使用 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,
        ],
        ...
    );

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

于 2017-11-09T08:05:20.913 回答
5

如果您不想更改系统驱动程序,您可以更改您的 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 列,它们将不起作用,它们将始终返回零。因为驱动程序的一个错误。请参阅:带有 MYSQLI_OPT_INT_AND_FLOAT_NATIVE 的 mysqlnd 无法解释位列。

于 2020-01-02T14:08:46.743 回答
2

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

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

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

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

也可以看看:

于 2017-02-24T17:30:10.167 回答
1

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

于 2014-07-17T07:24:40.753 回答
0
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();
于 2014-07-29T13:31:25.587 回答
0

我对 CodeIgnitor 文档的阅读(请参阅http://ellislab.com/codeigniter/user-guide/database/fields.html)是您想要遍历字段数据,然后自己决定要做什么处理数据。

我的猜测是,要无缝地执行此操作,您可能希望对他们的数据库和/或查询类进行子类化,以便您可以让他们做您想做的事。

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

于 2013-11-04T04:11:38.197 回答
0

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

这与codeignter无关。

MySQL 将所有内容都作为字符串返回,但 NULL 除外。

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

2:获取 MySQL 查询结果作为其原生数据类型?

于 2013-08-06T09:42:11.700 回答
-2

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

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

在您的视图文件中

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

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

于 2013-08-05T22:14:37.250 回答
-3

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

$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
于 2015-06-04T07:04:29.607 回答