Skip to content
This repository has been archived by the owner on Apr 27, 2022. It is now read-only.

php7.2中count函数出现Parameter must be an array or an object that implements Countable #9

Open
sdscbr opened this issue Jun 27, 2019 · 1 comment

Comments

@sdscbr
Copy link

sdscbr commented Jun 27, 2019

1.运行环境
centos7 Linux 3.10.0-957.el7.x86_64
php7.2.19
swoole4.3.5
yii2-basic 2.0.20
2.在开启日志功能,将日志信息写入到数据库表中时,会报下面的错误:

2019-06-26 19:44:49 [192.168.134.1][-][-][warning][yii\log\Dispatcher::dispatch] Unable to send log via yii\log\DbTarget: Exception (Database Exception) 'yii\db\Exception' with message 'count(): Parameter must be an array or an object that implements Countable
The SQL being executed was: INSERT INTO `log` (`level`, `category`, `log_time`, `prefix`, `message`)
                VALUES (8, 'tsingsun\swoole\web\Application::runComponentBootstrap', 1561635889.3354, '[192.168.134.1][-][-]', 'Bootstrap with yii\gii\Module::bootstrap()')' 

in /usr/local/nginx/html/yii2-basic-swoole/vendor/yiisoft/yii2/db/Schema.php:664

Stack trace:
#0 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/db/Command.php(325): yii\db\Schema->convertException(Object(yii\base\ErrorException), 'INSERT INTO `lo...')#1 /usr/local/nginx/html/yii2-basic-swoole/vendor/yiisoft/yii2/log/DbTarget.php(93): tsingsun\swoole\db\Command->execute()
#2 /usr/local/nginx/html/yii2-basic-swoole/vendor/yiisoft/yii2/log/Target.php(158): yii\log\DbTarget->export()
#3 /usr/local/nginx/html/yii2-basic-swoole/vendor/yiisoft/yii2/log/Dispatcher.php(189): yii\log\Target->collect(Array, false)
#4 /usr/local/nginx/html/yii2-basic-swoole/vendor/yiisoft/yii2/log/Logger.php(177): yii\log\Dispatcher->dispatch(Array, false)
#5 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/log/Logger.php(54): yii\log\Logger->flush(false)
#6 /usr/local/nginx/html/yii2-basic-swoole/vendor/yiisoft/yii2/BaseYii.php(395): tsingsun\swoole\log\Logger->log('Bootstrap with ...', 8, 'tsingsun\\swoole...')
#7 /usr/local/nginx/html/yii2-basic-swoole/vendor/yiisoft/yii2/BaseYii.php(408): yii\BaseYii::debug('Bootstrap with ...', 'tsingsun\\swoole...')
#8 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/web/Application.php(126): yii\BaseYii::trace('Bootstrap with ...', 'tsingsun\\swoole...')
#9 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/web/Application.php(68): tsingsun\swoole\web\Application->runComponentBootstrap()
#10 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/web/Application.php(56): tsingsun\swoole\web\Application->bootstrap()
#11 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/bootstrap/WebApp.php(39): tsingsun\swoole\web\Application->beforeRun()
#12 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/bootstrap/BaseBootstrap.php(124): tsingsun\swoole\bootstrap\WebApp->handleRequest(Object(Swoole\Http\Request), Object(Swoole\Http\Response))#13 /usr/local/nginx/html/yii2-basic-swoole/vendor/tsingsun/yii2-swoole/src/server/HttpServer.php(40): tsingsun\swoole\bootstrap\BaseBootstrap->onRequest(Object(Swoole\Http\Request), Object(Swoole\Http\Response))#14 {main}

不过,日志信息是可以正常插到数据库里,经过跟踪代码,问题出在这个文件:

tsingsun/yii2-swoole/src/db/mysql/PDOStatement.php

下面这个函数:

    public function rowCount()
    {   
       return count($this->data);         
    }

$this->data的值可能是数字或者数组,当是数字时在PHP7.2上会有警告,参考官方文档:
https://www.php.net/manual/en/function.count.php
下面是一种解决办法:

    public function rowCount()
    {   
        if (is_array($this->data) || (($this->data) instanceof \Countable)) {
            return count($this->data);
        } else {
            return $this->data;
        }   
    }

这应该是个兼容问题,还有没有其他更好的解决方法,可以一起交流一下,谢谢~~

@tsingsun
Copy link
Owner

tsingsun commented Jul 2, 2019

@sdscbr 这是一个bug,而swoole本身对select的影响行数并不支持,会增加一个字段来记录影响行数

    /**
     * @var int
     * @see rowCount
     */
    private $affected_rows;

    /**
     * swoole并不支持select返回影响数据行
     * Returns the number of rows affected by the last SQL statement
     * @link https://php.net/manual/en/pdostatement.rowcount.php
     * @return int the number of rows.
     */
    public function rowCount()
    {
        if (is_array($this->data)){
            return count($this->data);
        }
        return $this->affected_rows;
    }

affected_rows会在query执行时,被影响

    public function execute($input_parameters = null)
    {
        try {
            $client = $this->pdo->getClient();
            $this->data = $client->query($this->getRawSql());
            $this->affected_rows = $client->affected_rows;
            if ($this->data === false && $client->error != null) {
                throw new \PDOException($client->error,$client->errno);
            }
        } finally {
            if (!$this->pdo->inTransaction()) {
                $this->pdo->releaseConnect();
            }
        }
        return is_array($this->data);
    }

@tsingsun tsingsun reopened this Jul 2, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants