在使用 tinker CLI 时,Laravel 如何在 Eloquent 模型上查找和显示动态属性?
Posted
技术标签:
【中文标题】在使用 tinker CLI 时,Laravel 如何在 Eloquent 模型上查找和显示动态属性?【英文标题】:How does Laravel find and display the dynamic attributes on Eloquent models when using the tinker CLI? 【发布时间】:2020-11-19 18:13:25 【问题描述】:当我们使用 artisan tinker
并引用 Eloquent 模型对象时,REPL 会自动打印模型的属性,就像它打印我们引用的任何标准对象的公共属性一样:
>>> (object) ['hello' => 'world']
=>
+"hello": "world",
>>> App\User::first()
=> App\User
id: 1,
name: "...",
对我来说不太明显的是如何这些虚拟属性可以出现在这里,就好像它们已经被定义为类的公共属性一样。我知道模型的大部分属性分配是由HasAttributes
trait 在内部处理的,但是即使看那里,我仍然看不到 Laravel 的作者是如何实现这种行为的。
我尝试过构建这样的类:
class Bunch implements Arrayable, ArrayAccess, Jsonable, JsonSerializable ...
但即使使用有效的数组访问和toArray
方法,当我直接从artisan tinker
引用它时:
>>> $b = new Bunch()
=> Bunch
>>> $b->one = 1
=> 1
>>> $b['one']
=> 1
>>> $b
=> Bunch
我们如何改变 REPL 在打印这样的对象时使用的表示形式?
【问题讨论】:
【参考方案1】:确定如何在 Tinker 中显示模型属性的代码在 Tinker 代码中,而不是在模型中:
https://github.com/laravel/tinker/blob/2.x/src/TinkerCaster.php脚轮是Symfony VarDumper component 的一部分,PsySH 使用它来显示类。 Tinker 建立在 PsySH 之上。
Tinker 将施法者映射到其控制台命令类中的类:
https://github.com/laravel/tinker/blob/2.x/src/Console/TinkerCommand.php这会返回类到它们的施法者的映射:
/**
* Get an array of Laravel tailored casters.
*
* @return array
*/
protected function getCasters()
$casters = [
'Illuminate\Support\Collection' => 'Laravel\Tinker\TinkerCaster::castCollection',
'Illuminate\Support\htmlString' => 'Laravel\Tinker\TinkerCaster::castHtmlString',
'Illuminate\Support\Stringable' => 'Laravel\Tinker\TinkerCaster::castStringable',
];
if (class_exists('Illuminate\Database\Eloquent\Model'))
$casters['Illuminate\Database\Eloquent\Model'] = 'Laravel\Tinker\TinkerCaster::castModel';
if (class_exists('Illuminate\Foundation\Application'))
$casters['Illuminate\Foundation\Application'] = 'Laravel\Tinker\TinkerCaster::castApplication';
return $casters;
这会设置 VarDumper 上的脚轮:
$config->getPresenter()->addCasters(
$this->getCasters()
);
如果您想从模型中添加其他属性以在 Tinker 中显示,您可以在模型上使用 $appends 属性:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = ['is_admin'];
【讨论】:
是的!这完全是我想要的。添加$casters['App\Bunch'] = 'App\Bunch::castBunch';
允许我定义一个自定义方法来处理我的自定义类的REPL 表示。非常感谢!【参考方案2】:
Eloquent 使用数据库连接设置自动填充模型属性。
【讨论】:
以上是关于在使用 tinker CLI 时,Laravel 如何在 Eloquent 模型上查找和显示动态属性?的主要内容,如果未能解决你的问题,请参考以下文章
laravel 5.5:php artisan tinker:ErrorException:目录不为空[重复]