使用 Laravel Lift 提升 Eloquent 模型

发布日期 作者

Boost your Eloquent Models with Laravel Lift image

Lift 是一个用于提升 Laravel 中 Eloquent 模型的包。

它允许你在 Eloquent 模型 中创建与你的表模式匹配的公共属性。这使得你的模型在任何 IDE 中都更容易阅读和使用。

它提供了一种简单的方法来设置你的模型,通过使用 PHP 8 的属性,重点关注简单性和易用性。

该包依赖于 Eloquent Events 才能正常工作。这意味着该包可以轻松地集成到你的项目中,而无需任何重大更改(除非你已关闭事件触发)。

在本篇文章中,让我们深入研究 Lift 并了解它提供的所有功能。

安装 Laravel Lift

你可以通过 Composer 安装该包

composer require wendelladriel/laravel-lift

要开始使用 Lift,你需要将 Lift 特性添加到你的 Eloquent 模型 中,然后你就可以开始使用了。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
}

功能

默认情况下,当你将 Lift 特性添加到你的 Eloquent 模型 中时,你可以在模型上创建公共属性,使它们更容易理解并在任何 IDE 中使用。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
public $id;
 
public $name;
 
public $price;
}

当你开始使用该包提供的属性时,魔法就会发生。

类属性

DB 属性

Lift 提供了一个 DB 属性,你可以使用它来定义模型的连接、表和时间戳。

没有 Lift

use Illuminate\Database\Eloquent\Model;
 
final class Product extends Model
{
public $timestamps = false;
 
protected $connection = 'mysql';
 
protected $table = 'custom_products_table';
 
// ...
}

使用 Lift

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\DB;
use WendellAdriel\Lift\Lift;
 
#[DB(connection: 'mysql', table: 'custom_products_table', timestamps: false)]
final class Product extends Model
{
use Lift;
// ...
}

关系属性

Lift 提供属性来定义模型之间的关系,因此,你无需使用方法来定义它们,而是可以使用属性来定义它们。所有关系属性都接受与方法相同的参数。

没有 Lift

// Post.php
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
 
final class Post extends Model
{
public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}
// ...
}
 
// Comment.php
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
 
final class Comment extends Model
{
public function post(): BelongsTo
{
return $this->belongsTo(Post::class);
}
// ...
}

使用 Lift

// Post.php
 
use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Relations\HasMany;
use WendellAdriel\Lift\Lift;
 
#[HasMany(Comment::class)]
final class Post extends Model
{
use Lift;
// ...
}
 
// Comment.php
 
use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Relations\BelongsTo;
use WendellAdriel\Lift\Lift;
 
#[BelongsTo(Post::class)]
final class Comment extends Model
{
use Lift;
// ...
}

你可以查看 文档中 所有可用的关系属性。

这些关系的工作方式与使用方法定义它们的方式相同。

属性属性

Cast 属性

Lift 提供了一个 Cast 属性,你可以使用它来定义模型属性的类型转换。除了类型转换值之外,它还允许你为你的属性进行类型声明。

没有 Lift

use Illuminate\Database\Eloquent\Model;
 
final class Product extends Model
{
protected $casts = [
'id' => 'int',
'name' => 'string',
'price' => 'float',
'active' => 'boolean',
'expires_at' => 'immutable_datetime',
];
}

使用 Lift

use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Cast('string')]
public string $name;
 
#[Cast('float')]
public float $price;
 
#[Cast('boolean')]
public bool $active;
 
#[Cast('immutable_datetime')]
public CarbonImmutable $expires_at;
}

Column 属性

Lift 提供了一个 Column 属性,你可以使用它来定制模型属性的列名并为它们定义默认值。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Column;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Cast('string')]
#[Column('product_name')]
public string $name;
 
#[Cast('float')]
#[Column(name: 'product_price', default: 0.0]
public float $price;
}

在上面的示例中,name 属性将映射到 product_name 列,而 price 属性将映射到 product_price 列,默认值为 0.0

你甚至可以将函数名传递给默认值,该函数将在属性保存到数据库时被调用。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Column;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Cast('string')]
#[Column('product_name')]
public string $name;
 
#[Cast('float')]
#[Column(name: 'product_price', default: 0.0]
public float $price;
 
#[Cast('float')]
#[Column(default: 'generatePromotionalPrice')]
public float $promotional_price;
 
public function generatePromotionalPrice(): float
{
return $this->price * 0.8;
}
}

Fillable 属性

当使用 Lift 特性时,模型的所有属性都将被设置为 guarded。你可以使用 Fillable 属性来定义哪些属性可以进行批量赋值。

没有 Lift

use Illuminate\Database\Eloquent\Model;
 
final class Product extends Model
{
protected $fillable = [
'name',
'price',
];
 
protected $casts = [
'id' => 'int',
'name' => 'string',
'price' => 'float',
];
}

使用 Lift

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Fillable]
#[Cast('string')]
public string $name;
 
#[Fillable]
#[Cast('float')]
public float $price;
}

Hidden 属性

Lift 提供了一个 Hidden 属性,你可以使用它来隐藏模型转换为数组或 JSON 时不希望显示的属性。

没有 Lift

use Illuminate\Database\Eloquent\Model;
 
final class Product extends Model
{
protected $fillable = [
'name',
'price',
'active',
];
 
protected $casts = [
'id' => 'int',
'name' => 'string',
'price' => 'float',
'active' => 'boolean',
];
 
protected $hidden = [
'active',
];
}

使用 Lift

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Hidden;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Fillable]
#[Cast('string')]
public string $name;
 
#[Fillable]
#[Cast('float')]
public float $price;
 
#[Hidden]
#[Fillable]
#[Cast('boolean')]
public bool $active;
}

Immutable 属性

Lift 提供了一个 Immutable 属性,你可以使用它来使属性不可变。这意味着,一旦模型被创建,该属性就无法更改。如果你尝试更改它,将会抛出一个 WendellAdriel\Lift\Exceptions\ImmutablePropertyException 异常。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Immutable;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Immutable]
#[Fillable]
#[Cast('string')]
public string $name;
}
 
$product = Product::query()->create([
'name' => 'Product 1',
]);
 
$product->name = 'Product 2';
$product->save(); // Throws an WendellAdriel\Lift\Exceptions\ImmutablePropertyException

PrimaryKey 属性

Lift 提供了一个 PrimaryKey 属性,你可以使用它来定制模型的主键。

没有 Lift

use Illuminate\Database\Eloquent\Model;
 
final class Product extends Model
{
public $incrementing = false;
 
protected $primaryKey = 'uuid';
 
protected $keyType = 'string';
// ...
}

使用 Lift

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\PrimaryKey;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[PrimaryKey(type: 'string', incrementing: false)]
#[Cast('string')]
public string $uuid;
// ...
}

Rules 属性

Lift 提供了一个 Rules 属性,你可以使用它来定义模型属性的验证规则。

验证规则的设置方式与你在 Laravel Form Request 中设置的方式相同,你甚至可以为每个规则设置自定义消息。

⚠️ 仅在保存模型(创建或更新)时才会验证规则

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Rules;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Fillable]
#[Cast('string')]
#[Rules(['required', 'string', 'max:255'])]
public string $name;
 
#[Fillable]
#[Cast('float')]
#[Rules(['required', 'numeric', 'min:0.0'])]
public float $price;
 
#[Fillable]
#[Cast('boolean')]
#[Rules(rules: ['required', 'boolean'], messages: ['required' => 'You must set the active status for the product'])]
public bool $active;
}

Watch 属性

默认情况下,Eloquent 已经在创建、更新、删除等操作时触发了事件。但那是一个通用的事件,有时,你需要在属性更改时触发一个特定的事件。这就是 Watch 属性发挥作用的地方。

你可以定义一个自定义事件,当属性更改时会触发该事件。该事件将接收更新后的模型实例作为参数。

// Product.php
 
use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Watch;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Fillable]
#[Cast('string')]
public string $name;
 
#[Fillable]
#[Cast('float')]
#[Watch(PriceChangedEvent::class)]
public float $price;
 
#[Fillable]
#[Cast('boolean')]
public bool $active;
}
 
// PriceChangedEvent.php
 
final class PriceChangedEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
 
public function __construct(
public Product $product,
) {
}
}

方法

除了该包提供的所有属性之外,它还提供了一些方法,你可以使用这些方法来获取有关模型的更多信息。

customColumns()

它将返回一个包含你在模型中定义的所有自定义列的数组。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Column;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Cast('string')]
#[Column('product_name')]
public string $name;
 
#[Cast('float')]
#[Column(name: 'product_price', default: 0.0]
public float $price;
}
 
Product::customColumns();
 
// WILL RETURN
[
'name' => 'product_name',
'price' => 'product_price',
]

defaultValues()

它将返回一个包含所有定义了默认值的属性的数组。如果默认值是一个函数,则将返回函数名,而不是函数结果,因为这是一个静态调用。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Column;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Cast('string')]
#[Column('product_name')]
public string $name;
 
#[Cast('float')]
#[Column(name: 'product_price', default: 0.0]
public float $price;
 
#[Cast('float')]
#[Column(default: 'generatePromotionalPrice')]
public float $promotional_price;
 
public function generatePromotionalPrice(): float
{
return $this->price * 0.8;
}
}
 
Product::defaultValues();
 
// WILL RETURN
[
'price' => 0.0,
'promotional_price' => 'generatePromotionalPrice',
]

immutableProperties()

它将返回一个包含所有不可变属性的数组。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Immutable;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Immutable]
#[Fillable]
#[Cast('string')]
public string $name;
}
 
Product::immutableProperties();
 
// WILL RETURN
[
'name',
]

validationMessages()

它将返回一个包含你在模型中定义的所有验证消息的数组。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Rules;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Fillable]
#[Cast('string')]
#[Rules(['required', 'string', 'max:255'])]
public string $name;
 
#[Fillable]
#[Cast('float')]
#[Rules(['required', 'numeric', 'min:0.0'])]
public float $price;
 
#[Fillable]
#[Cast('boolean')]
#[Rules(rules: ['required', 'boolean'], messages: ['required' => 'You must set the active status for the product'])]
public bool $active;
}
 
Product::validationMessages();
 
// WILL RETURN
[
'name' => [],
'price' => [],
'active' => [
'required' => 'You must set the active status for the product',
],
]

validationRules()

它将返回一个数组,其中包含您在模型中定义的所有验证规则。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Rules;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Fillable]
#[Cast('string')]
#[Rules(['required', 'string', 'max:255'])]
public string $name;
 
#[Fillable]
#[Cast('float')]
#[Rules(['required', 'numeric', 'min:0.0'])]
public float $price;
 
#[Fillable]
#[Cast('boolean')]
#[Rules(rules: ['required', 'boolean'], messages: ['required' => 'You must set the active status for the product'])]
public bool $active;
}
 
Product::validationRules();
 
// WILL RETURN
[
'name' => ['required', 'string', 'max:255'],
'price' => ['required', 'numeric', 'min:0.0'],
'active' => ['required', 'boolean'],
]

watchedProperties()

它将返回一个数组,其中包含所有定义了自定义事件的属性。

use Illuminate\Database\Eloquent\Model;
use WendellAdriel\Lift\Attributes\Cast;
use WendellAdriel\Lift\Attributes\Fillable;
use WendellAdriel\Lift\Attributes\Watch;
use WendellAdriel\Lift\Lift;
 
final class Product extends Model
{
use Lift;
 
#[Cast('int')]
public int $id;
 
#[Fillable]
#[Cast('string')]
public string $name;
 
#[Fillable]
#[Cast('float')]
#[Watch(PriceChangedEvent::class)]
public float $price;
 
#[Fillable]
#[Cast('boolean')]
public bool $active;
}
 
Product::watchedProperties();
 
// WILL RETURN
[
'price' => PriceChangedEvent::class,
]

结论

Lift 是一个将DoctrineSpringEntity Framework 等工具的一些功能引入Eloquent 的软件包。

它通过利用 PHP 8 的属性,使您的模型更易于阅读和理解,并具有更简洁的外观。

Wendell Adriel photo

软件工程师 💻 开源爱好者 🔥 从 2009 年开始构建解决方案 🚀

归档于
Cube

Laravel 新闻

加入 40,000 多名其他开发人员,不要错过新的技巧、教程等等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

绝不妥协

Joel 和 Aaron,两位来自 No Compromises 播客的资深开发人员,现在可以为您的 Laravel 项目雇用。 ⬧ 固定费用 7500 美元/月。 ⬧ 没有漫长的销售流程。 ⬧ 没有合同。 ⬧ 100% 退款保证。

绝不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序取得成功。

Kirschbaum
Shift logo

Shift

运行旧版本的 Laravel?即时、自动化的 Laravel 升级和代码现代化,使您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

只需 2500 美元/月,即可使用拥有 4-6 年经验的资深 Laravel 开发人员为您的项目增效。获得 160 小时的专职专业知识和 15 天无风险试用。立即预约电话!

Bacancy
Lucky Media logo

Lucky Media

立即获得好运 - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 的电子商务。一个开源软件包,将现代无头电子商务功能的强大功能带到 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 职位平台

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS 启动工具包

SaaSykit 是一个 Laravel SaaS 启动工具包,包含运行现代 SaaS 所需的所有功能。付款、精美结账、管理面板、用户仪表板、身份验证、就绪组件、统计数据、博客、文档等等。

SaaSykit: Laravel SaaS 启动工具包
Rector logo

Rector

您无缝升级 Laravel、降低成本和加速创新的合作伙伴,助力企业成功

Rector
MongoDB logo

MongoDB

通过 MongoDB 和 Laravel 的强大集成增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。了解 MongoDB 的灵活、现代数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

在您的 Laravel 应用程序中添加 Swagger UI

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel 提示构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包向您的 Laravel 应用程序添加评论

阅读文章