yii数据类型跟数据库类型不一致,怎么解决?

by pxz


发布于: 2018-04-25 所属分类: php 标签: yii 数据类型  618


<p>最近在开发的过程中, 遇到了一个问题, 我的数据库字段明明设置的是整型, 但是把yii的模型对象打印出来, 如下所示</p> <blockquote> <p><img src="http://www.sgzhang.com/upload/2018/04/201804240930279468600.png" alt=""><br>parent_id在数据库是整型, 这里打印出来是一个字符串类型, 为什么?</p> </blockquote> <p>首先, 我的环境是: </p> <blockquote> <p> wampserver3.0.6 64位集成开发环境<br> php版本: 5.6.25<br> apache版本: 2.4.23<br> mysql版本: 5.7.14</p> </blockquote> <p>为了找到原因, 我做了以下尝试</p> <blockquote> <p><strong>1.切换系统</strong></p> <blockquote> <p>当我切换到linux系统下运行, 类型对应关系正常, 由此得出结论, 可能跟系统有关, 但是, 系统哪里出了问题呢?</p> </blockquote> <p><strong>2.切换php版本</strong></p> <blockquote> <p>当我在wamp里面把php切换到7.0版本后, 类型对应关系正常, 由此得出结论, 可能跟php版本有关, 但是, 在linux下同样版本的php, 却可以正常对应, 由此得出结论, 可能跟php版本和系统有关. 但是具体该怎么解决呢, 继续寻找解决方法… </p> </blockquote> <p><strong>3.改数据库字段类型</strong></p> <blockquote> <p>当我把字段类型由 int(11) unsigned 改成 int(11) 去掉了无符号unsigned,对应关系正常, 难道yii只能对不是无符号的整型才映射成整型? 如果是这样, 那应该不同的系统下, 不同的php版本下, 映射关系应该一样才对.</p> </blockquote> <p><strong>4.网上搜索解决方案1</strong></p> <blockquote> <p>db连接配置, 添加 <code>'emulatePrepare'=>false,</code>, 添加后无效果</p> </blockquote> <p><strong>5.网上搜索解决方案2</strong></p> <blockquote> <p>db连接配置添加</p> <pre><code>'attributes' => [ PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_EMULATE_PREPARES => false, ] </code></pre><p>添加后效果实际上跟上面的一样</p> </blockquote> <p> <strong>6. 抛弃框架, 直接用PDO连接数据库</strong></p> <blockquote> <pre><code><?php $pdo = new PDO('mysql:host=localhost;port=3306;dbname=testdb', 'root', '123456', array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8") ); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); echo '<pre>'; foreach ($pdo->query('select * from f_category') as $row) { var_dump($row); break; } ?> </code></pre><p>打印的结果是<br><img src="http://www.sgzhang.com/upload/2018/04/201804241916479259377.png" alt=""><br>映射关系正常</p> </blockquote> <p><strong>7.跟踪yii代码</strong></p> <blockquote> <p>最后只能跟踪查看yii源码, 看yii底层使用pdo读出数据之后做了什么处理, 经过几个小时的代码跟踪, 最后找到了问题的根源, 如下所示<br><img src="http://www.sgzhang.com/upload/2018/04/201804241924071259244.png" alt=""><br>关键代码 vendor/yiisoft/yii2/db/Schema.php 文件的565行<br><code>return PHP_INT_SIZE === 4 && $column->unsigned ? 'string' : 'integer';</code><br>上图的代码可以完美的解释以上遇到的种种疑问</p> </blockquote> </blockquote> <p>原来在yii底层, 通过<code>show columns from f_category;</code>查询出数据库的字段类型, 例如parent_id的字段类型是 int(11) unsigned, 第一次通过Schema类的typeMap属性转换后的变成 integer, typeMap属性如图所示<br><img src="http://www.sgzhang.com/upload/2018/04/201804252128425119114.png" alt=""><br>然后使用上面的getColumnPhpType方法对 integer 类型作了第二次转换, 如果满足三个条件, 一个是 整型, 一个是 unsigned, 还有一个是 PHP_INT_SIZE 等于 4, 这三个条件同是满足情况下, yii 会把整型当作字符串类型处理. </p> <h4 id="h4--n-"><a name="再来解释上面n种尝试出现的原因" class="reference-link"></a><span class="header-link octicon octicon-link"></span>再来解释上面n种尝试出现的原因</h4><p><strong>1. 为什么切换为linux系统下正常了? </strong><br><code>因为切换后 PHP_INT_SIZE 变成了 8</code><br><strong>2. 为什么切换到7.0正常了?</strong><br><code>根据网上的资料,PHP_INT_SIZE跟编译时使用的系统版本有关, 如果是64位系统 PHP_INT_SIZE等于8, 如果是 32位,PHP_INT_SIZE等于4, 而且php7源码对PHP_INT_SIZE作了特殊处理, 所以php不会出现这个问题,低版本的php, 如果是32位的编译器,就会出现这个问题</code><br>**3. 为什么改字段类型后变正常了<br><code>因为把字段类型unsigned去掉了, 也就不满足上面的第三个条件了</code></p> <h4 id="h4-u6700u540Eu7684u89E3u51B3u65B9u6CD5"><a name="最后的解决方法" class="reference-link"></a><span class="header-link octicon octicon-link"></span>最后的解决方法</h4><p>最后, 问题原因查清楚了, 解决方法也就很清晰了, 换个64位的php就ok了</p>

发表评论

暂无评论

搜索
用户登陆