Eloquent: 修改器

原作者:coding01 原文链接:https://juejin.im/post/5c309ee66fb9a04a0d570020


感觉好长时间没写东西了,一方面主要是自己的角色发生了变化,每天要面对各种各样的事情和突发事件,不能再有一个完整的长时间让自己静下来写代码,或者写文章。

另一方面现在公司技术栈不再停留在只有Laravel + VUE 了,我们还有小程序、APP 等开发,所以我关注的东西也就多了。

接下来我还是会继续持续「高产」,把写技术文章当作一个习惯,坚持下去。

好了,废话不多说,今天来说一说「Eloquent: 修改器」。

一直想好好研究下 Eloquent。但苦于 Eloquent 有太多可研究的,无法找到一个切入点。前两天看一同事好像对这个「Eloquent: 修改器」了解不多,所以今天就拿它作为入口,扒一扒其实现源代码。

首先还是拿一个 Demo 为例:

Demo

<?php

namespace App\Models;


use Illuminate\Database\Eloquent\Model;

use Carbon\Carbon;


class BabyextendsModel

{

    protected$table ='baby';

    protected$appends = ['age'];


    publicfunctiongetAgeAttribute()

    {

        $date =newCarbon($this->birthday);

        returnCarbon::now()->diffInYears($date);

    }

}

复制代码

这个代码比较简单,就是通过已有属性 birthday,计算 Baby 几岁了,得到age 属性。

前端就可以直接拿到结果:

return $baby->age;

复制代码

同样的,还有 setXxxAttribute 方法来定义一个修改器。

源代码

读代码还是从使用入手,如上通过 $baby->age 调用 age 属性,这个属性没在类中定义,所以只能通过 PHP 的魔术方法__get() 调用了。

我们看看 Model 类的 __get() 方法:

/**

 * Dynamically retrieve attributeson the model.

 *

 *@param  string  $key

 *@return mixed

 */

publicfunction__get($key)

{

    return$this->getAttribute($key);

}

复制代码

好了,我们开始解读源代码了:

/**

 * Get an attribute from the model.

 *

 *@param  string  $key

 *@return mixed

 */

publicfunctiongetAttribute($key)

{

    if(! $key) {

        return;

    }


    //

If the attribute exists in the attribute array or has a "get" mutator

we will

    //

get the attribute's value. Otherwise, we will proceed as if the developers

    //

are asking for a relationship's value. This covers both types of values.

    if(array_key_exists($key,$this->attributes) ||

        $this->hasGetMutator($key)){

        return$this->getAttributeValue($key);

    }


    ...

}

复制代码

重点自然就在第二个 if 上,主要判断 attributes 数组中是否包含该属性,如果没有,则会执行函数 $this->hasGetMutator($key):

/**

 * Determine if a get mutator existsfor an attribute.

 *

 *@param  string  $key

 *@return bool

 */

publicfunctionhasGetMutator($key)

{

    returnmethod_exists($this,'get'.Str::studly($key).'Attribute');

}

复制代码

这就对上了我们的 Demo 中自定义的函数 getAgeAttribute(),也就返回 true 了。

接下来就是执行函数 $this->getAttributeValue($key),进而执行函数:return $this->mutateAttribute($key, $value);

/**

 * Get the value of an attributeusing its mutator.

 *

 *@param  string  $key

 *@param  mixed  $value

 *@return mixed

 */

protectedfunctionmutateAttribute($key, $value)

{

    return$this->{'get'.Str::studly($key).'Attribute'}($value);

}

复制代码

好了,到此我们基本就知道了获取自定义 Attribute 的流程了。

相信解析 set

XxxAttribute 也是很简单的。

总结

好长时间没写东西了,先从最简单的入手,练练手。解析 Eloquent 需要费很多脑细胞,接下来的一段时间我会围绕着这个主题好好研究下去,尽可能的全部解读一遍::

.

|____Capsule

| |____Manager.php

|____composer.json

|____Concerns

| |____BuildsQueries.php

| |____ManagesTransactions.php

|____Connection.php

|____ConnectionInterface.php

|____ConnectionResolver.php

|____ConnectionResolverInterface.php

|____Connectors

| |____ConnectionFactory.php

| |____Connector.php

| |____ConnectorInterface.php

| |____MySqlConnector.php

| |____PostgresConnector.php

| |____SQLiteConnector.php

| |____SqlServerConnector.php

|____Console

| |____Factories

| | |____FactoryMakeCommand.php

| | |____stubs

| | | |____factory.stub

| |____Migrations

| | |____BaseCommand.php

| | |____FreshCommand.php

| | |____InstallCommand.php

| | |____MigrateCommand.php

| | |____MigrateMakeCommand.php

| | |____RefreshCommand.php

| | |____ResetCommand.php

| | |____RollbackCommand.php

| | |____StatusCommand.php

| |____Seeds

| | |____SeedCommand.php

| | |____SeederMakeCommand.php

| | |____stubs

| | | |____seeder.stub

|____DatabaseManager.php

|____DatabaseServiceProvider.php

|____DetectsDeadlocks.php

|____DetectsLostConnections.php

|____Eloquent

| |____Builder.php

| |____Collection.php

| |____Concerns

| | |____GuardsAttributes.php

| | |____HasAttributes.php

| | |____HasEvents.php

| | |____HasGlobalScopes.php

| | |____HasRelationships.php

| | |____HasTimestamps.php

| | |____HidesAttributes.php

| | |____QueriesRelationships.php

| |____Factory.php

| |____FactoryBuilder.php

| |____JsonEncodingException.php

| |____MassAssignmentException.php

| |____Model.php

| |____ModelNotFoundException.php

| |____QueueEntityResolver.php

| |____RelationNotFoundException.php

| |____Relations

| | |____BelongsTo.php

| | |____BelongsToMany.php

| | |____Concerns

| | | |____InteractsWithPivotTable.php

| | | |____SupportsDefaultModels.php

| | |____HasMany.php

| | |____HasManyThrough.php

| | |____HasOne.php

| | |____HasOneOrMany.php

| | |____MorphMany.php

| | |____MorphOne.php

| | |____MorphOneOrMany.php

| | |____MorphPivot.php

| | |____MorphTo.php

| | |____MorphToMany.php

| | |____Pivot.php

| | |____Relation.php

| |____Scope.php

| |____SoftDeletes.php

| |____SoftDeletingScope.php

|____Events

| |____ConnectionEvent.php

| |____QueryExecuted.php

| |____StatementPrepared.php

| |____TransactionBeginning.php

| |____TransactionCommitted.php

| |____TransactionRolledBack.php

|____Grammar.php

|____Migrations

| |____DatabaseMigrationRepository.php

| |____Migration.php

| |____MigrationCreator.php

| |____MigrationRepositoryInterface.php

| |____Migrator.php

| |____stubs

| | |____blank.stub

| | |____create.stub

| | |____update.stub

|____MigrationServiceProvider.php

|____MySqlConnection.php

|____PostgresConnection.php

|____Query

| |____Builder.php

| |____Expression.php

| |____Grammars

| | |____Grammar.php

| | |____MySqlGrammar.php

| | |____PostgresGrammar.php

| | |____SQLiteGrammar.php

| | |____SqlServerGrammar.php

| |____JoinClause.php

| |____JsonExpression.php

| |____Processors

| | |____MySqlProcessor.php

| | |____PostgresProcessor.php

| | |____Processor.php

| | |____SQLiteProcessor.php

| | |____SqlServerProcessor.php

|____QueryException.php

|____README.md

|____Schema

| |____Blueprint.php

| |____Builder.php

| |____Grammars

| | |____ChangeColumn.php

| | |____Grammar.php

| | |____MySqlGrammar.php

| | |____PostgresGrammar.php

| | |____RenameColumn.php

| | |____SQLiteGrammar.php

| | |____SqlServerGrammar.php

| |____MySqlBuilder.php

| |____PostgresBuilder.php

| |____SQLiteBuilder.php

| |____SqlServerBuilder.php

|____Seeder.php

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容