前面讲过数据,通过load方式导入数据对象的原理。
下面主要分析下:
$this->fields();
追踪源码,在yii2/base/model:
/* * @return array the list of field names or field definitions.
* @see toArray()
*/
public function fields()
{
$fields = $this->attributes();
return array_combine($fields, $fields);
}
继续:
/**
* Returns the list of attribute names.
* By default, this method returns all public non-static properties of the class.
* You may override this method to change the default behavior.
* @return array list of attribute names.
*/
public function attributes()
{
$class = new ReflectionClass($this);
$names = [];
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
if (!$property->isStatic()) {
$names[] = $property->getName();
}
}
return $names;
}
其实这两步就是返回,model中所有的public属性数组(key和value一致)。
$fields = $this->fields();返回结果:
array(39) {
["_params"]=>
string(7) "_params"
["debug"]=>
string(5) "debug"
["accessToken"]=>
string(11) "accessToken"
["adminId"]=>
string(7) "adminId"
["period"]=>
string(6) "period"
["dimen"]=>
string(5) "dimen"
["unionGameId"]=>
string(11) "unionGameId"
["unionGameName"]=>
string(13) "unionGameName"
["gameId"]=>
string(6) "gameId"
["gameName"]=>
string(8) "gameName"
["folderId"]=>
string(8) "folderId"
["folderName"]=>
string(10) "folderName"
["groupId"]=>
string(7) "groupId"
["groupType"]=>
string(9) "groupType"
["groupName"]=>
string(9) "groupName"
["sDay"]=>
string(4) "sDay"
["eDay"]=>
string(4) "eDay"
["sHour"]=>
string(5) "sHour"
["eHour"]=>
string(5) "eHour"
["sMonth"]=>
string(6) "sMonth"
["eMonth"]=>
string(6) "eMonth"
["sTime"]=>
string(5) "sTime"
["eTime"]=>
string(5) "eTime"
["aggr"]=>
string(4) "aggr"
["channel"]=>
string(7) "channel"
["threshold"]=>
string(9) "threshold"
["isNatural"]=>
string(9) "isNatural"
["userId"]=>
string(6) "userId"
["company"]=>
string(7) "company"
["supplier"]=>
string(8) "supplier"
["advertising_admin_id"]=>
string(20) "advertising_admin_id"
["serverId"]=>
string(8) "serverId"
["costAndNoReg"]=>
string(12) "costAndNoReg"
["fackFilter"]=>
string(10) "fackFilter"
["advertiserId"]=>
string(12) "advertiserId"
["gid"]=>
string(3) "gid"
["fid"]=>
string(3) "fid"
["types"]=>
string(5) "types"
["reportConfig"]=>
string(12) "reportConfig"
}
继续,看一下 $this->isAttributeActive() 方法:
/**
* Returns a value indicating whether the attribute is active in the current scenario.
* @param string $attribute attribute name
* @return bool whether the attribute is active in the current scenario
* @see activeAttributes()
*/
public function isAttributeActive($attribute)
{
return in_array($attribute, $this->activeAttributes(), true);
}
/**
* Returns the attribute names that are subject to validation in the current scenario.
* @return string[] safe attribute names
*/
public function activeAttributes()
{
$scenario = $this->getScenario();
$scenarios = $this->scenarios();
if (!isset($scenarios[$scenario])) {
return [];
}
$attributes = array_keys(array_flip($scenarios[$scenario]));
foreach ($attributes as $i => $attribute) {
if ($attribute[0] === '!') {
$attributes[$i] = substr($attribute, 1);
}
}
return $attributes;
}
上面,两步,其实就是返回,定义的场景下,定义的类属性。如果$this->load()方法,对相关属性赋值,则有值,反之,则为null:
定义场景如下:
/**
* 场景
* @return array
*/
public function scenarios()
{
$basicFields = [
'debug', 'sDay', 'eDay', 'aggr', 'dimen', 'period', 'unionGameId', 'gameId', 'folderId', 'groupId',
'unionGameName', 'folderName', 'gameName', 'groupName', 'groupType', 'channel', 'company', 'supplier',
'serverId','threshold','fackFilter'
];
}
相关操作判断如下,过滤null数值后,返回结果如下:
$where = [];
$fields = $this->fields();
foreach($fields as $f) {
if($this->isAttributeActive($f)) {
if ($this->$f != '') {
$where[$f] = $this->$f;
}
}
}
var_dump($where);die;
array(4) {
["period"]=>
string(1) "1"
["sDay"]=>
string(10) "2020-05-23"
["eDay"]=>
string(10) "2020-05-29"
["aggr"]=>
string(1) "0"
}
通过上篇文章可以知道AR模式的 $this->attributes()方法,是跟数据库字段相关;
而通过yii/base/model中的 $this->attributes()方法,是跟Model类中自定义的公有public属性相关。
注意两者之间差异。
对应方法定义再看一下吧:
AR模式,yii2/db/ActiveRecord中:
/**
* Returns the list of all attribute names of the model.
* The default implementation will return all column names of the table associated with this AR class.
* @return array list of attribute names.
*/
public function attributes()
{
return array_keys(static::getTableSchema()->columns);
}
Model类中,yii2/base/Model中:
/**
* Returns the list of attribute names.
* By default, this method returns all public non-static properties of the class.
* You may override this method to change the default behavior.
* @return array list of attribute names.
*/
public function attributes()
{
$class = new ReflectionClass($this);
$names = [];
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
if (!$property->isStatic()) {
$names[] = $property->getName();
}
}
return $names;
}