在这里我想总结一下我学习YII框架的过程中,踩过的那些坑。希望能给YII框架的初学者一些帮助,使大家能更快地熟悉YII框架。
1.显式地指明表名。
在使用ActiveRecord类时,你一般会去继承yii\db\ActiveRecord这个基类,在models文件夹中去创建一个自己的类,如下:
1 2 3 4 5 6 7
| namespace app\models; use yii\db\ActiveRecord; class Customer extends ActiveRecord { }
|
一般在文档里会说,yii会根据类名自动去猜测表名(如以上代码,yii便会自动去关联customer表)。但是这个并不是一直都有效,所以最稳妥的办法还是指明表名,像下面这样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| namespace app\models; use yii\db\ActiveRecord; class Customer extends ActiveRecord { /** * @return string 返回该AR类关联的数据表名 */ public static function tableName() { return 'customer'; } }
|
2.在你继承自yii\db\ActiveRecord的类里面不要去声明和相对应表里面的字段同名的公有属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php namespace app\models; use yii\db\ActiveRecord; class Country extends ActiveRecord { public $name; public $population; public function rules(){ return [ [['name', 'population'], 'required'], ]; } public static function tableName() { return 'country'; } }
|
在上面的代码中,我在Country类里面申明了2个公有属性name和population,我的country表里有3个字段,分别是自增主键id,name和population。
- 当你通过
$country->load(Yii::$app->request->post())
的方式接受数据,然后调用$country->save()
的时候,你会发现保存成功了,但是name和population字段都没有插入成功。然后我便尝试着在load数据之后打印了下$country
对象。如下:
1 2 3 4 5 6 7 8 9 10 11 12
| object(app\models\Country)#55 (10) { ["name"]=> string(3) "France" ["population"]=> string(4) "18886000" ["_attributes":"yii\db\BaseActiveRecord":private]=> array(1) { ["id"]=> int(47) } ...//多余的省略 }
|
可以看到其公有属性被成功赋值了,而其私有属性_attributes是一个数组,里面有一个元素id,值为47,查询数据库发现正是刚插入的那一行数据的id,而name和population字段都未插入成功。
- 之后我将Country类里的两个公有属性删除后,继续执行上述操作,便插入成功了,我也将
$country
对象打印了出来,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php namespace app\models; use yii\db\ActiveRecord; class Country extends ActiveRecord { public function rules(){ return [ [['name', 'population'], 'required'], ]; } public static function tableName() { return 'country'; } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| object(app\models\Country)#55 (10) { ["_attributes":"yii\db\BaseActiveRecord":private]=> array(3) { ["name"]=> string(3) "France" ["population"]=> string(4) "18886000" ["id"]=> int(48) } ...//多余的省略 }
|
可以看到这回name和population的值被填充进了私有属性_attributes中。所以由此我推断,当调用$country->save()
方法时,会从_attributes数组中取出key-value对存入数据库对应字段。取数据时也是同理,取出来的字段也是自动填充进_attributes数组。
3.当使用model->load(Yii::$app->request->post())时,如何传递post数据
我用postman(模拟http请求的chrome扩展)模拟传递数据,下面是接受数据的方式。
1 2 3
| $country = new Country(); $country->load(Yii::$app->request->post()); var_dump($country);
|
我在Country类里声明了如下rules:
1 2 3 4 5 6
| public function rules() { return [ [['name', 'population'], 'required'], ]; }
|
当我用postman模拟post方式在form data里面传递了name和population2个参数时,将$country对象打印出来:
1 2 3 4 5 6
| object(app\models\Country)#65 (8) { ["_attributes":"yii\db\BaseActiveRecord":private]=> array(0) { } ...//多余的省略 }
|
可以看到其私有变量_attributes并没有被填充进数据。
阅读Model->load()的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public function load($data, $formName = null) { $scope = $formName === null ? $this->formName() : $formName; if ($scope === '' && !empty($data)) { $this->setAttributes($data); return true; } elseif (isset($data[$scope])) { $this->setAttributes($data[$scope]); return true; } else { return false; } }
|
发现$scope变量为相对应的表名,然后isset($data[$scope])
查看的是以对应表名为key的数组,$this->setAttributes($data[$scope])
是将对应表名的数组里的key-value对填充进私有属性_attributes。
所以当你模拟post传参时,要传递Country[name]和Country[population],这样才能被load()方法正确接收。修改传参后再次打印$country对象:
1 2 3 4 5 6 7 8 9 10
| object(app\models\Country)#65 (8) { ["_attributes":"yii\db\BaseActiveRecord":private]=> array(2) { ["name"]=> string(3) "aaa" ["population"]=> string(5) "34343" } ...//多余的省略 }
|
当然你也可以不用load()方式接受数据,你也可以通过以下2种方式进行赋值。
(1)通过批量赋值的方式:
$country->attributes = Yii::$app->request->post();
。
(2)逐个赋值的方式:
$name = Yii::$app->request->post('name');
$country->name = $name;
。
上一篇:PHP的基础知识