thepublicgood/is-presentable

简单的 Laravel 模型展示器特质

v2.0.1 2022-01-26 18:53 UTC

This package is auto-updated.

Last update: 2024-09-15 10:37:06 UTC


README

Tests

IsPresentable 是一个简单的包,可以帮助您格式化 Laravel 模型的数据,以便在视图中展示。例如,如果您需要在 Blade 视图中打印模型的创建日期,并且您这样写:

<p>{{ $model->created_at }}</p>

您将得到如下 HTML 输出

<p>2021-12-09 03:04:22</p>

这没问题,但不是很好。如果您想格式化它怎么办?好吧,您可以这样操作

<p>{{ $model->created_at->format('d F Y H:i a') }}</p>

Laravel 会自动将 created_at 时间戳传递给 Carbon,因此这实际上工作得很好。但如果有很多地方需要使用相同的格式,现在就有点令人沮丧了。您可以创建一个模型访问器,这也可以正常工作,但它会让模型看起来像是被展示数据充斥。您是否要在所有模型中添加相同的访问器?这就是 IsPresentable 的用武之地。

安装

始终使用 Composer 将其安装到您的 Laravel 应用中

composer require thepublicgood/is-presentable=^2.0

用法

版本 2 带来了一种全新的方法来向您的模型添加展示器。旧版本 1 的使用 presentable 方法的方式仍然可行,并且向后兼容。

使用 presentable

首先将 IsPresentable 特质添加到您的模型类中

namespace App\Models\Models;

use Illuminate\Database\Eloquent\Model;
use TPG\IsPresentable\Traits\IsPresentable;

class User extends Model {
    use IsPresentable;
    
    // ...
}

现在为要展示的属性创建一个新的展示器类。请确保扩展 Presentable 抽象类。您要展示的模型将被注入为 $model 类属性,因此您可以使用 $this->model 来引用它。这里有一个简单的 CreatedAtPresentable

<?php

namespace App\Http\Presenters;

use App\Models\User;
use TPG\IsPresentable\Presentable;

class CreatedAtPresentable extends Presentable
{
    public function render(): string
    {
        return $this->model->created_at->format('d F Y H:i a');
    }
}

现在您可以将这个展示器类分配给模型中的 $presentables 数组中的属性名

use App\Http\Presenters\CreatedAtPresentable;

class User extends Model {
    use IsPresentable;
    
    protected $presentables = [
        'created_at' => CreatedAtPresentable::class,
    ];
    
    // ...
}

所以现在,在您的 Blade 视图文件中,您可以这样做

<p>{{ $user->presentable()->created_at }}</p>

在视图中不再需要调用 format

创建这样的展示器类作为类非常实用,因为它们是可重用的。例如,created_at 列在 Laravel 模型中相当标准化,因此您可以使用相同的类在任何模型上格式化这些数据。不需要为每个模型编写另一个展示器。只需将它添加到您需要它的 $presentables 数组中即可。

使用 presentable 方法

如果您不想/不需要创建展示器类,或者您只向模型添加一个将不会在其他地方使用的展示器,您可以直接在模型类上创建简单的 "访问器" 方法,方法名前缀为 "presentable"。例如,一个 User 可能需要一个即时计算的 username。我们可以在模型类上编写一个 "展示器" 方法,如下所示

public function presentableUsername(): ?string
{
    return Str::slug($this->name);  
}

为了使其更整洁,您可以为您的展示器方法创建特质,并在您的自己特质中包含 IsPresentable 特质

trait UserPresenter
{
    use IsPresentable;
    
    public function presentableUsername(): ?string
    {
        // ...
    }
}

然后在您的 User 模型类中,只使用 UserPresenter 特质

class User extends Authenticatable
{
    use UserPresenter;
    // ...
}

这允许有一点可重用性,因为这些特质也可以由多个模型使用。

使用 JavaScript

IsPresentable 特质将扩展 toArray() 方法并向结果添加渲染数据。如果您需要在 JavaScript 前端访问展示器,这很有用。将包含所有格式化数据的 presentable 子数组添加到结果数组中。例如,$user->toArray() 将导致类似以下结果

{
    "id": 1,
    "name": "Marquardt Morissette",
    "email": "user@example.com",
    "password": "password",
    "created_at": "2021-03-08T20:49:43.000000Z",
    "updated_at": "2021-03-08T20:49:43.000000Z",
    "presentable": {
        "created_at": "08 March 2021 08:49 pm"
    }
}

如果您正在使用Vue等前端框架,并且数组被转换为JSON对象,则可以通过以下方式访问到相同的格式化created_at属性

{{ user.presentable.created_at }}

高级用法

隐藏演示者

如果您出于任何原因不希望在模型转换为数组时包含演示数据,您可以在您的演示类中实现IsHidden接口来隐藏该数据

class UsernamePresentable extends Presenter implements IsHidden
{
    // ..
}

您仍然可以通过Laravel应用程序中的presentable()方法访问演示者,但它在模型转换为数组时将不再显示。

访问属性名称

演示器类可以访问您在$presentables数组中设置的键的属性名称。例如,您可以在您的User模型类上设置以下演示者

class User extends Model
{
    protected $presentables = [
        'created_at' => DatePresentable::class,
        'updated_at' => DatePresentable::class,
    ];

我们不必为每个属性创建两个单独的演示器类,我们可以在演示器类中通过$this->attribute访问我们正在展示的属性的名称

class DatePresenter extends Presentable
{
    public function render(): string|null
    {
        return $this->model->{$this->attribute};
    }
}

如果需要以一致的方式显示所有日期和时间,这非常有用。

向演示器传递数据

使用演示器类,可以传递任意数据,这可以用来改变演示器的反应方式。您可以通过对模型类中的$presentables属性进行小修改来实现这一点。您不需要传递字符串类路径,而是可以传递一个数组,其中第一个元素是类路径,第二个元素是要传递的数据

class User extends Model
{
    use IsPresentable;
    
    $presentables = [
        'created_at' => [            
            DatePresenter::class,
            'd F Y'
        ],
    ];
}

在您的演示器类中,可以通过$this->option访问第二个元素

class DatePresenter extends Presentable
{
    public function render(): string|null
    {
        return $this->model->{$this->attribute}->format($this->option);
    }
}

选项不一定是字符串,您也可以传递一个选项数组

class User extends Model
{
    use IsPresentable;
    
    protected $presentables = [
        'created_at' => [
            DatePresentable::class,
            [
                'Africa/Johannesburg',
                'd F Y',
            ],
        ],
    ];

这使您能够对模型属性的表现方式有相当大的控制权。

如果您不希望使用$presentables数组,也可以将整个配置移动到getPresentables方法中

class User extends Model
{
    use IsPresentable;
    
    public function getPresentables(): array
    {
        return [
            'created_at' => DatePresentable::class,
        ];
    }

默认演示器

有时指定一组默认的演示器类,这些类将自动用于所有使用IsPresentable特质的模型类,这可能非常有用。您可以在presentable.php配置文件中添加默认值。首先,使用Artisan发布配置文件

php artisan vendor:publish --provider=TPG\IsPresentable\IsPresentableServiceProvider

现在您可以将您的默认演示器类添加到default数组中。您可以使用与直接添加到模型类相同的功能

return [
    'defaults' => [
        'created_at' => [
            DatePresentable::class,
            [
                'Africa/Johannesburg',
                'd F Y',
            ],
        ],
    ],
],

您不需要向您的$presentables数组中添加任何内容。只需包含IsPresentable特质,默认情况下就会包含created_at演示器属性。

测试

可以使用PHPUnit运行测试

vendor/bin/phpunit

致谢

变更日志

所有API更改都在CHANGELOG.md文件中进行了记录。查看变更日志

许可证

IsPresentable采用MIT许可证。有关更多详细信息,请参阅LICENSE