项目使用yii1.1版本，遇到莫名的异常结束，200状态，内容为空
今天遇到一个神奇的现象项目使用yii1.1版本，遇到莫名的异常结束，200状态，内容为空报表页面，ajax请求数据，时而正常返回数据，时而异常无任何报错信息，php-fpm也无报错，PHP 7.0版本，PHP报错级别已设置为E_ALL，各种方法都尝试了，找不到原因本地同请求测试一切正常，生产环境异常一天时间已经过去，无解第2天，决定在代码中打断点试的，一步一步排查最终确定原因：在报表数据查询后处理过程中，使用了4层循环，加上数据查了4个月的日报表，数据量并不高循环中，把PHP设置的内存用尽，导致异常结束配置为128M，代码中没有修改内存大小解决方法：在代码前使用 ini_set('memory_limit', '256M'); 设置内存解决；难排查的原因在于，找不到任何报错信息。。。。。对了，报错信息是用Yii::log()方法输出到文件中，tail -f 查看文件的内容来找，可能是这个原因，由于PHP内存已经用尽，后面代码执行不了，所以没有输出内容到文件？（还有个疑点，就是控制器都没执行？这不应该啊）记录一下
yii 1.1 要使用 insert ignore into 语句批量写入数据的方法
注意这里使用的是yii 1.1版本有时候我们要批量写入数据，同时还要去重复，如下的方法可能有用（数据库设置了唯一索引）$this->db = new CDbConnection('mysql:host=dev.database.local;port=3306;dbname=xxx', 'xxx', 'xxx'); $data = [ ['areaId'=>1, 'title'=>'text1'], ['areaId'=>2, 'title'=>'text2'], ['areaId'=>3, 'title'=>'text3'], ]; $builder = $this->db->schema->getCommandBuilder(); $command = $builder->createMultipleInsertCommand("{{ztags}}", $data); $sql = $command->getText(); $sql = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $sql); $params = []; foreach ($data as $i=>$d) { foreach ($d as $k=>$v) { $params[":{$k}_{$i}"] = $v; } } $this->db->createCommand($sql)->execute($params); 文档参考：https://www.yiiframework.com/doc/api/1.1/CDbCommandBuilder#createMultipleInsertCommand-detailhttps://www.yiiframework.com/doc/api/1.1/CDbCommand#getText-detail
$builder = Yii::app()->db->schema->commandBuilder; // 创建builder对象 $command = $builder->createMultipleInsertCommand('{{umeng_message}}', array( // umeng_message为数据库表 array(// 格式为：'字段' => '值', 不包括主键ID，一个array为一条记录 'msg_id' => $android['data']['task_id'], 'detail' => $android['data']['json'], 'msg_detail_id_fk' => $detailId ), array( 'msg_id' => $android['data']['task_id'], 'detail' => $android['data']['json'], 'msg_detail_id_fk' => $detailId ), )); $command->execute(); // 执行成功返回true
Yii 1.1实现批量插入数据的扩展 整理于网络文章
扩展文件名： CDbBICommand.php ，将文件放于 \protected\components 目录下，确定项目会自动引入这个目录的文件，然后用法：StatVisitor 是 CActiveRecord 类的数据表模型$bi = new CDbBICommand(new StatVisitor());$bi->batchInsert([['name'=>123],['name'=>234]]);扩展文件代码如下：<?php /** * class for sql batch insert * eg: * $bi = new CDbBICommand(new StatVisitor()); * $bi->batchInsert([['name'=>123],['name'=>234]]); */ class CDbBICommand { /** * CDbBICommand constructor. * @param CActiveRecord $acModel */ public function __construct($acModel) { $this->ac = $acModel; $this->tablename = $this->ac->tableName(); $this->db = $this->ac->getDbConnection(); $this->command = $this->db->createCommand(); } public function batchInsert($array_columns) { $sql = ''; $params = array(); $i = 0; foreach ($array_columns as $columns) { $names = array(); $placeholders = array(); foreach ($columns as $name => $value) { if (!$i) { $names[] = $this->db->quoteColumnName($name); } if ($value instanceof CDbExpression) { $placeholders[] = $value->expression; foreach ($value->params as $n => $v) { $params[$n] = $v; } } else { $placeholders[] = ':' . $name . $i; $params[':' . $name . $i] = $value; } } if (!$i) { $sql = 'INSERT INTO ' . $this->db->quoteTableName($this->tablename) . ' (' . implode(', ', $names) . ') VALUES (' . implode(', ', $placeholders) . ')'; } else { $sql .= ',(' . implode(', ', $placeholders) . ')'; } $i++; } return $this->command->setText($sql)->execute($params); } }框架自带的批量插入方法，很少有网络资料：$builder = Yii::app()->db->schema->commandBuilder; // 创建builder对象 $command = $builder->createMultipleInsertCommand('{{umeng_message}}', array( // umeng_message为数据库表 array(// 格式为：'字段' => '值', 不包括主键ID，一个array为一条记录 'msg_id' => $android['data']['task_id'], 'detail' => $android['data']['json'], 'msg_detail_id_fk' => $detailId ), array( 'msg_id' => $android['data']['task_id'], 'detail' => $android['data']['json'], 'msg_detail_id_fk' => $detailId ), )); $command->execute(); // 执行成功返回true
下载框架：https://github.com/yiichina/yii创建一个新的空白应用(cmd 命令)：framework/yiic [appname] [path/to]入口配置：protected/config/main.php'components'=>[ //伪静态配置 'urlManager'=>array( 'urlFormat'=>'path', 'rules'=>array( '<controller:\w+>/<id:\d+>'=>'<controller>/view', '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>', '<controller:\w+>/<action:\w+>'=>'<controller>/<action>', ), ), ]伪静态：.htaccess RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} !^/(.*)\.(css|jpg|js|gif|png|bmp)/ RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L] 应用配置文档：https://www.yiiframework.com/doc/guide/1.1/zh-cn/basics.applicationYii::app()//获取配置文件main中的配置值和应用组件 Yii::app()->basePath; Yii::app()->name; Yii::app()->params->adminEmail; //组件配置在main中的components键中 Yii::app()->db; Yii::app()->cache; Yii::app()->user;可以在controller 目录创建 actions (可自定义)目录用于存放action类，达到action复用的目的：//protected/controllers/post/UpdateAction.php class UpdateAction extends CAction { public function run() { // place the action logic here } } //protected/controllers/ArticleController.php class ArticleController extends Controller { public function actions() { return [ 'edit'=>'application.controllers.post.UpdateAction' ]; } }可以在action方法中加入参数，可直接获取到get来的参数：public function actionView($id, $act, $name='joyber') { // main中的路由配置中的$id动态参数 echo $id; // $_GET['act'] echo $act; // $_GET['name'] 不存在name参数时默认值：joyber echo $name; // post xxy $xxy = Yii::app()->request->getPost('xxy'); }widget 自定义组件 可以放在components 目录 视图中应用：<?php $this->widget('MyWidget', ['data'=>123]) ?>//components/MyWidget.php class MyWidget extends CWidget { public $btn; public function init() { // 此方法会被 CController::beginWidget() 调用 } public function run() { // 此方法会被 CController::endWidget() 调用 parent::run(); // TODO: Change the autogenerated stub $this->render('my', ['btn'=>$this->btn, 'name'=>'my test widget']); } } //view file: components/views/my.php <input type="text" value="<?=$name?>"> <?=$btn?>