Laravel 是一个开源、易用的 PHP 框架。它最强大的功能之一是 Eloquent,这是一种对象关系映射器(ORM),可简化数据库记录处理。
Eloquent 可加快应用程序对数据库进行创建、读取、更新和删除操作的速度。使用 Eloquent 时,您可以创建映射数据库表的模型,并使用这些模型创建查询。
本文探讨了 Eloquent 最强大功能的六个要素:查询作用域、关系、突变器和访问器、集合、模型删除和工厂。文章通过实际示例介绍了每个功能的作用。希望你能通过这些示例快速掌握 Laravel Eloquent。
1. Eloquent 查询范围
在构建应用程序时,有时会遇到多次使用条件的情况。每次重写代码都会增加出错的几率,并使代码变得不整齐。Laravel 解决了这个问题,它将这些条件封装在称为作用域的可重用语句中。
查询作用域是将数据库逻辑添加到模型中并重复使用查询逻辑的方法。
下面是一个查询作用域的示例。假设您想为团队创建一个软件开发平台,跟踪已完成和正在进行的功能。您可以使用此条件只检索正在进行的功能:
$onGoing = Project::where('ongoing', 1)->get();
您可能需要在其他应用程序页面(如统计页面)中使用此条件。查询作用域允许页面重复使用上述条件,从而简化查询并使代码更简洁。
下面介绍如何在这种情况下使用查询作用域:
class Features extends Model { public function scopeOngoing($query) { return $query->where('ongoing', 0); } }
然后使用下面的代码执行该作用域:
$onGoing = Feature::ongoing()->get();
有两种作用域:全局作用域和局部作用域。
全局作用域
全局作用域允许在模型内的所有查询中添加限制条件。例如,您可以在模型内的所有查询中添加一个条件,根据组长的姓名过滤特征。
本地作用域
本地作用域允许定义通用约束,以实现可重用性。例如,您可能希望应用程序返回存在错误的功能。您的代码可能会这样实现一个局部作用域:
namespace AppModels; use IlluminateDatabaseEloquentModel; class User extends Model { public function scopeBugged($query) { return $query->where('bugged', '>', 1); } }
上面的代码会返回所有存在未修复错误的功能。
2. Eloquent 关系
Eloquent 中的关系允许您轻松地将不同的表联系起来。例如,电子商务网站上的产品可能列出了库存、价格、视图和评论。有了 Eloquent,即使记录在不同的表中,您也可以轻松管理这些关系。
您可以将关系定义为模型类上的方法,就像定义 Eloquent 模型一样。一些常用的 Eloquent 关系包括一对一关系、逆关系和多态关系。
一对一
下面是一个将产品模型与库存关联起来的基本一对一关系示例。
public function Inventory() { return $this->hasOne('AppInventory'); }
在上面的代码中, Inventory()
方法调用了产品模型上的 hasOne()
方法。这将检查产品当前是否可用。
反向关系
Eloquent 还允许您创建反向关系。例如,当您想根据查看次数来获取产品时。反向关系可以为您提供网站访客最感兴趣的产品。您可以使用 belongsTo()
方法,它是 hasOne()
的逆向方法。下面的代码说明了这一点。
public function product() { return $this->belongsTo('AppProduct'); }
在上面的代码中,Eloquent 会将 product_id
与所传递的视图数量相匹配。然后,product_id
可以帮助获取其他参数,如价格和库存。
多态性
在应用程序开发中,关系并不总是那么简单。有时,一个模型属于多个模型类型。例如,产品和库存模型都可以与图像模型建立多态关系。
多态关系允许您在库存和产品中使用相同的图像列表。下面是实现多态关系的代码片段。
class Image extends Model { /** * Getting the shared image. */ public function myimage() { return $this->morphTo(); } } class Product extends Model { /** * Get the image to use on the product's page. */ public function image() { return $this->morphOne(Image::class, 'myimage'); } } class Inventory extends Model { /** * Get the image to use on the inventory page. */ public function image() { return $this->morphOne(Image::class, 'myimage'); } }
上面的代码使用 morphTo()
方法来检索多态模型的父模型。
这只是这个主题的冰山一角。更多详情,请参阅我们的 Laravel Eloquent 关系高级指南。
3. Eloquent 突变器和访问器
突变器和访问器允许你在存储和检索数据时修改数据。突变器在保存数据前修改数据,而访问器在检索数据时修改数据。
如果想在数据库中以小写存储姓名,可以创建一个突变器来执行这种转换。如果想在应用程序页面上将用户的名和姓显示为一个名字,可以创建一个访问器来实现这一目的。
下面是一个突变器的示例,该突变器可在保存名称之前将其大写。
class User extends Model { /** * Mutators capitalizing first and last name. */ public function setFirstNameAttribute($value) { $this->attributes['first_name'] = ucfirst($value); } public function setLastNameAttribute($value) { $this->attributes['last_name'] = ucfirst($value); } }
下面是一个访问器的示例,该访问器结合了用户的名和姓。
class User extends Model { /** * Accessor combining both names. */ public function getFullNameAttribute() { return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name); } }
4. Eloquent 集合
Eloquent 集合用于处理返回多个模型结果的方法。该类可在 IlluminateDatabaseEloquentCollection
中找到。
与数组一样,可以对集合进行迭代。下面是一个简单的迭代过程。
use AppModelsProduct; $products = Product::where('availability', 1)->get(); foreach ($products as $product) { echo $product->name; }
集合比数组更强大,因为您可以对它们执行更复杂的操作。例如,您可以显示所有可用产品的列表,并跳过所有未 “激活” 的产品。
$names = Product::all()->reject(function ($product) { return $product->active === false; })->map(function ($product) { return $product->name; });
以下是集合类提供的一些方法。
Contains
contains()
方法会检查代码是否包含指定模式,如下代码所示:
$products->contains(1); $products->contains(Product::find(1));
All
all()
方法会返回集合中包含的模型,如下所示:
$collection = Product::all();
集合类还支持许多其他方法。
5. 删除 Eloquent 模型
在 Eloquent 中,您可以创建模型来帮助构建查询。不过,有时您需要删除模型,以使应用程序更有效率。为此,请在模型实例上调用 delete
。
use AppModelsStock; $stock = Stock::find(1); $stock->delete();
上面的代码会从应用程序中删除模型 Stock
。这是永久删除,无法撤销。
软删除
Eloquent 的另一项功能是模型软删除功能。软删除模型时,不会将其从数据库中删除。
您可以使用 deleted_at
标记它,以指示软删除的时间和日期。当您想排除数据库中的部分记录(如不完整的记录),而又不想永久删除它们时,这一点非常重要。它有助于在不添加额外条件的情况下清理 Eloquent 的查询结果。
您可以通过在模型中添加 softDeletes
特性,并在相关数据库表中添加 deleted_at
列来启用软删除功能。
在模型中添加软删除
如下所示,通过添加 IlluminateDatabaseEloquentSoftDeletes
特性来启用模型软删除功能。
namespace AppModels; use IlluminateDatabaseEloquentModel; use IlluminateDatabaseEloquentSoftDeletes; class Flight extends Model { use SoftDeletes; }
如何添加 delete_at 列
在开始使用软删除之前,你的数据库应该有一个 delete_at
列。添加这一列需要使用 Laravel Schema
生成器的辅助方法,如下所示:
use IlluminateDatabaseSchemaBlueprint; use IlluminateSupportFacadesSchema; Schema::table('users', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('users', function (Blueprint $table) { $table->dropSoftDeletes(); });
这将添加一个 delete_at
列,在软删除操作成功的情况下,该列将用日期和时间更新。
如何包含软删除的模型
如果希望查询结果包括软删除的模型,可以在查询中添加 withTrashed()
方法。下面是一个示例:
$stocks = Stock::withTrashed()->where('stock_id', 20)->get();
上述查询还将包括带有 deleted_at
属性的模型。
如何只检索软删除的模型
Eloquent 还允许您只检索软删除的模型。例如,您可以通过调用 onlyTrashed()
方法来做到这一点:
$Stock = Stock::onlyTrashed()->where('stock_id', 1)->get();
如何恢复软删除的模型
您也可以通过调用 restore()
方法来恢复软删除的模型。
$stocks = Stock::withTrashed()->where('stock_id', 20)->restore();
这会将软删除模型的 delete_at
字段改为空。如果模型未被软删除,则该字段保持不变。
6. Eloquent 工厂
Laravel 中的模型工厂可以创建虚拟数据,用于测试应用程序或为数据库提供种子数据。为此,你需要在工厂类中创建一个模型,如下图所示。代码片段创建了一个模型工厂,它可以生成产品及其价格的虚假供应商。
namespace DatabaseFactories; use IlluminateDatabaseEloquentFactoriesFactory; use IlluminateSupportStr; class StockFactory extends Factory { public function definition() { return [ 'supplier_name' => fake()->name(), 'price' => fake()->numberBetween($min = 1500, $max = 6000), ]; } }
上例中的 definition()
方法会返回一组属性值,供 Laravel 在构建模型时使用。伪助手帮助工厂访问 PHP 库 Faker。
小结
Eloquent 简化了在 Laravel 中开发应用程序的任务。借助关系等实现方式,它在构建简单或复杂查询时同样有效。使用工厂生成功能性虚拟数据的简便性,使其成为希望为应用程序创建强大测试的开发人员的完美选择。此外,Eloquent 的作用域还有助于简化复杂的查询,使代码更加整洁。
本文仅介绍了 Eloquent 的六项主要功能,但 Eloquent 还有其他强大的功能。可共享和可重用模型的使用使 Eloquent 成为开发人员最喜爱的功能,而 Eloquent 查询的简洁性则使 Laravel 成为对开发人员友好的框架–即使对初学者来说也是如此。
评论留言