laravel 中 所有的模型会继承自模型基类
当调用一个模型不存在的属性时,会调用基类模型的__get方法(php中的魔术方法,读取不可访问属性的值时,__get()会被调用)model类中的方法
public function __get($key){return $this->getAttribute($key); //调用 model 类的 getAttribute 方法}.......public function getAttribute($key){if (array_key_exists($key, $this->attributes) || $this->hasGetMutator($key)) {return $this->getAttributeValue($key);}//$this->attributes是当前实例模型的属性关联数组 false//method_exists 和 function_exists 差不多 ,一个是检查是否有此 function, 一个是检查当前类是否有成员方法 method//如果都没有会当成关联模型,尝试获取关联关系return $this->getRelationValue($key);}.......public function hasGetMutator($key){//method_exists 和 function_exists 差不多 ,一个是检查是否有此 function, 一个是检查当前类是否有成员方法 method//在当前 类实例中存在 getXxxAttribute方法return method_exists($this, 'get'.Str::studly($key).'Attribute');}........public function getAttributeValue($key){$value = $this->getAttributeFromArray($key);// If the attribute has a get mutator, we will call that then return what// it returns as the value, which is useful for transforming values on// retrieval from the model to a form that is more useful for usage.//如果当前属性有修改器,调用修改器if ($this->hasGetMutator($key)) {return $this->mutateAttribute($key, $value);}// If the attribute exists within the cast array, we will convert it to// an appropriate native PHP type dependant upon the associated value// given with the key in the pair. Dayle made this comment line up.//如果有映射转换关系,数据库int 转 布尔值, json 转数组if ($this->hasCast($key)) {return $this->castAttribute($key, $value);}// If the attribute is listed as a date, we will convert it to a DateTime// instance on retrieval, which makes it quite convenient to work with// date fields without having to create a mutator for each property.//不是时间戳if (in_array($key, $this->getDates()) && ! is_null($value)) {return $this->asDateTime($value);}//返回值return $value;}
如果实例模型设置了$appends属性,并且模型没有这个属性(假设为name),laravel 会自动调用getNameAttribute方法
有个问题就是每次都会自动调用,有时候只想在某些情况下调用的话,可以取消$appends属性,获取模型时手动调用setAppends方法
$user=User::find(1)->setAppends(['wage','info']);
但是 setAppends方法对collection不生效,也就是说用get,all方法都不生效,可以在 AppServiceProvider中为collection添加宏
Collection::macro('setAppends', function ($attributes) {return $this->map(function ($item) use ($attributes) {return $item->setAppends($attributes);});});$users = User:all();$users->setAppends(['info']);
也可以利用 collection 的高阶消息传递
$users->each->setAppends(['info']);
