ThinkPHP:模型三大利器之三(獲取器)
定义获取器
获取器的作用是对模型对象的(原始)数据做出自动处理。一个获取器对应模型的一个特殊方法(该方法必须为public类型),方法命名规范为:
getFieldNameAttr
FieldName为数据表字段的驼峰转换或者你数据表不存在的字段(注意理解后面这句话),下面是一个典型的获取器定义:
<?php namespace app\index\model; use think\Model; class User extends Model { public function getUserTypeAttr($value, $data) { $type = [0 => '普通', 1 => 'VIP', 2 => '黄金', 3 => '白金', 4 => '钻石']; return $type[$value]; } }
你需要给每一个需要输出转换处理的数据字段定义一个对应的获取器,但获取器的字段名不一定要和数据表的字段名一致,例如我希望给user_type字段定义一个名为getTypeAttr的获取器也是允许的,但要注意这个时候传入获取器的第一个参数肯定是没有值(因为没有对应的数据表字段数据),只能通过第二个参数获取你需要的数据。
<?php namespace app\index\model; use think\Model; class User extends Model { public function getTypeAttr($value, $data) { $type = [0 => '普通', 1 => 'VIP', 2 => '黄金', 3 => '白金', 4 => '钻石']; return $type[$data['user_type']]; } }
当然更为严谨的情况下,你还需要判断下是否存在$data['user_type'],这个暂且略过。
注意第二个参数的data数据,可能本身已经经过了获取器的处理(如果你定义了相关的获取器的话)。
为什么要定义一个和数据报字段不一致的获取器呢?最明显的好处可以区分不同的字段获取原始数据和处理过的数据。事实上,有很多理由可以让你定义一些数据表不存在的字段获取器,这恰恰是获取器的魅力所在。
看的出来获取器定义本身没什么难度,关键在于方法里面的获取逻辑,这是实际应用中最需要关注的。
调用获取器
定义获取器之后会在下列情况自动触发:
·模型的数据对象取值操作(例如$model->field_name);
·模型的序列化输出操作(例如$model->toArray()或toJson());
·显式调用getAttr方法(例如$model->getAttr('field_name'));
前面两种其实最终都是调用最后一种来实现的,最关键的是要理解第一种。模型对象取值的时候一般都是通过下面的方式:
$user = User::get(1); echo $user->name; echo $user->user_type;
当我们使用上面的方式进行模型对象数据获取或者在模板输出的时候事实上都会按照下面的顺序来检测和获取数据。
·第1步——如果查询结果包含该字段数据,取回原始数据,否则并进入第2步;
·第2步——检查是否定义该字段的获取器(包括动态获取器),如果有,则调用获取器返回结果,没有则进入第3步;
·第3步——检查是否定义了字段的类型转换,有则进行转换处理并返回结果,没有则进入第4步;
·第4步——如果是系统的时间字段,则自动进行时间格式化处理并返回结果,否则进入第5步;
·第5步——如果第1步检查的时候不包含该字段数据,则检查是否存在关联属性定义,有则通过关联关系获取数据并返回结果,否则抛出属性未定义的异常。
上面的这五个步骤的详细代码,如果你有兴趣的可以直接参考think\model\concern\Attribute的getAttr方法代码。
简单来说,当你获取$user->user_type的时候都会去检查是否定义了相关的获取器,而不管user_type字段是否是一个真实的数据表字段。
但很多情况下,你不会一个个去获取模型数据,而是把整个模型数据返回给客户端或者模板。
public function index() { $user = User::get(1); return json($user); }
在这种情况下,其实就是在响应输出的时候进行了模型的toJson处理。
有一点至关重要,如果你的获取器定义了非数据表的字段,是不会自动输出的,必须通过append方法追加额外属性(并且支持追加关联模型属性)。
如果我们定义了一个type属性的获取器(假设这并不是一个真实的数据表字段),那么需要使用下的方式才能正常输出(否则你可能只有user_type数据):
public function index() { $user = User::get(1); return json($user->append(['type'])); }
如果你是使用toArray的话,处理方式相同。
如果是数据集查询的话,一样可以使用append方法统一追加额外字段。
public function index() { $users = User::all(); return json($users->append(['type'])); }
除了append方法之外,我们还支持用hidden方法临时隐藏一些数据。
获取原始数据
有些情况下,除了要获取处理过的数据外,还需要获取原始数据以便应对不同的需求。
如果你的获取器都是用的区分于实际数据表字段的额外属性字段,那么这个问题本身已经解决了。所以我们主要讨论的是当你的获取器属性和数据表字段一致的情况下,该如何获取原始数据。
一个最简单的办法是使用getData方法:
$user = User::get(1); // 获取user_type获取器数据 echo $user->user_type; // 获取原始的user_type数据 echo $user->getData('user_type'); // 获取全部原始数据 dump($user->getData());
动态获取器
前面我们提到过动态获取器的概念,动态获取器就是不需要在模型类里面定义获取器方法,而是在查询的时候使用闭包来定义一个字段的获取器对数据进行统一的处理。
User::withAttr('name', function($value, $data) { return strtolower($value); })->select();
如果你需要定义多个动态获取器,多次调用withAttr方法就行。
动态获取器的意义除了可以不用在模型里面定义获取器方法之外,还可以起到覆盖已经定义的获取器的作用,并且动态获取器可以支持Db类操作,弥补了Db操作不能使用获取器的缺憾,具体就看自己的需求来选择了。
Db::name('user')->withAttr('name', function($value, $data) { return strtolower($value); })->select();
总结
无论是获取器,还是之前提的修改器、搜索器,其作用无非是把你的模型工作细化和拆分,这样代码和逻辑也会更清晰,可维护性也大大增强,至于性能,从来不是模型首先考虑的。
PHP中文网,有大量免费的ThinkPHP入门教程,欢迎大家学习!
本文转自:https://blog.thinkphp.cn/825350
以上是ThinkPHP:模型三大利器之三(獲取器)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

想像一下,一個人工智慧模型,不僅擁有超越傳統運算的能力,還能以更低的成本實現更有效率的效能。這不是科幻,DeepSeek-V2[1],全球最強開源MoE模型來了。 DeepSeek-V2是一個強大的專家混合(MoE)語言模型,具有訓練經濟、推理高效的特點。它由236B個參數組成,其中21B個參數用於啟動每個標記。與DeepSeek67B相比,DeepSeek-V2效能更強,同時節省了42.5%的訓練成本,減少了93.3%的KV緩存,最大生成吞吐量提高到5.76倍。 DeepSeek是一家探索通用人工智

波士頓動力Atlas,正式進入電動機器人時代!昨天,液壓Atlas剛「含淚」退出歷史舞台,今天波士頓動力就宣布:電動Atlas上崗。看來,在商用人形機器人領域,波士頓動力是下定決心要跟特斯拉硬剛一把了。新影片放出後,短短十幾小時內,就已經有一百多萬觀看。舊人離去,新角色登場,這是歷史的必然。毫無疑問,今年是人形機器人的爆發年。網友銳評:機器人的進步,讓今年看起來像人類的開幕式動作、自由度遠超人類,但這真不是恐怖片?影片一開始,Atlas平靜地躺在地上,看起來應該是仰面朝天。接下來,讓人驚掉下巴

本月初,來自MIT等機構的研究者提出了一種非常有潛力的MLP替代方法—KAN。 KAN在準確性和可解釋性方面表現優於MLP。而且它能以非常少的參數量勝過以更大參數量運行的MLP。例如,作者表示,他們用KAN以更小的網路和更高的自動化程度重現了DeepMind的結果。具體來說,DeepMind的MLP有大約300,000個參數,而KAN只有約200個參數。 KAN與MLP一樣具有強大的數學基礎,MLP基於通用逼近定理,而KAN基於Kolmogorov-Arnold表示定理。如下圖所示,KAN在邊上具

ThinkPHP 擁有多個版本,針對不同 PHP 版本而設計。主要版本包括 3.2、5.0、5.1 和 6.0,而次要版本用於修復 bug 和提供新功能。目前最新穩定版本為 ThinkPHP 6.0.16。在選擇版本時,需考慮 PHP 版本、功能需求和社群支援。建議使用最新穩定版本以獲得最佳性能和支援。

特斯拉機器人Optimus最新影片出爐,已經可以在工廠裡打工了。正常速度下,它分揀電池(特斯拉的4680電池)是這樣的:官方還放出了20倍速下的樣子——在小小的「工位」上,揀啊揀啊揀:這次放出的影片亮點之一在於Optimus在廠子裡完成這項工作,是完全自主的,全程沒有人為的干預。而且在Optimus的視角之下,它還可以把放歪了的電池重新撿起來放置,主打一個自動糾錯:對於Optimus的手,英偉達科學家JimFan給出了高度的評價:Optimus的手是全球五指機器人裡最靈巧的之一。它的手不僅有觸覺

目標偵測在自動駕駛系統當中是一個比較成熟的問題,其中行人偵測是最早得以部署演算法之一。在多數論文當中已經進行了非常全面的研究。然而,利用魚眼相機進行環視的距離感知相對來說研究較少。由於徑向畸變大,標準的邊界框表示在魚眼相機當中很難實施。為了緩解上述描述,我們探索了擴展邊界框、橢圓、通用多邊形設計為極座標/角度表示,並定義一個實例分割mIOU度量來分析這些表示。所提出的具有多邊形形狀的模型fisheyeDetNet優於其他模型,並同時在用於自動駕駛的Valeo魚眼相機資料集上實現了49.5%的mAP

ThinkPHP Framework 的本機運作步驟:下載並解壓縮 ThinkPHP Framework 到本機目錄。建立虛擬主機(可選),指向 ThinkPHP 根目錄。配置資料庫連線參數。啟動 Web 伺服器。初始化 ThinkPHP 應用程式。存取 ThinkPHP 應用程式 URL 運行。

FP8和更低的浮點數量化精度,不再是H100的「專利」了!老黃想讓大家用INT8/INT4,微軟DeepSpeed團隊在沒有英偉達官方支援的條件下,硬生在A100上跑起FP6。測試結果表明,新方法TC-FPx在A100上的FP6量化,速度接近甚至偶爾超過INT4,而且比後者擁有更高的精度。在此基礎之上,還有端到端的大模型支持,目前已經開源並整合到了DeepSpeed等深度學習推理框架中。這項成果對大模型的加速效果也是立竿見影──在這種框架下用單卡跑Llama,吞吐量比雙卡還要高2.65倍。一名
