minionfactory / model-mapper
Laravel 扩展。用于封装模型和原始 DB::select 结果,将一个或多个属性映射到其他模型。
Requires
- php: ^8.1
- ext-json: *
- laravel/framework: ^8.0|^9.0|^10.0
README
简介
Model Mapper 是对模型使用方式的小幅修改。我的许多真实世界示例都包含多个复杂联接和复杂的 WHERE 子句。在这些场景下使用真正的 Eloquent 对象并不有利。与原始的 SQL 查询相比,维护性和可读性都会下降。
有时联接非常简单,但是除了正在实例化的主要类之外,缺少属性方法。
最后,由于我大部分工作都使用 sqlsrv(Microsoft SQL Server),它对日期有问题。
这个包是为我自己使用的,但对其他人免费。
日期和 SQLSRV(Microsoft SQL Server)
当属性被列为日期属性时,它将使用内部 fromDateTime 方法。当字段来自 sqlsrv 时,这会导致问题。这个覆盖方法从日期字段中删除尾随毫秒,以防止错误。这需要在后续更新 Laravel 核心时进行审查,以防他们修复了这个问题。
模型映射:AdvancedModel
使用模型进行简单的更新/插入等操作非常好。当查询涉及多个联接、多个条件和子查询时,模型请求开始变得混乱。我创建了两个类来处理这个问题。
第一个是 AdvancedModel。它覆盖了默认的 __get 方法,并添加了 modelMapper($array)。
用法
$reminderText = CommonData::join('Events', 'CommonData.CommonDataID', '=', 'Events.EventsCommonID') ->whereIn('EventsId', $ids) ->select('CommonData.reminderemailText', 'Events.EventDate', 'Events.PriceCount') ->get(); $reminderText->map(function($reminder) { $reminder->modelMapper([ 'EventDate' => Events::class, 'PriceCount' => 'integer' ]); });
当引用 $reminderText[ $index ]→EventDate 时,现在将使用 Events 类来确定如何处理属性,而不是访问 CommonData。
对于每个返回的字段,如果它是另一个模型的一部分,只需将其作为键→值对添加到 modelMapper 映射调用中。
如果属性不需要进行任何额外修改,只需将其转换为所需类型,可以使用以下简单值代替模型类
- integer, int
- boolean, bool
- float
- double
- string, text
模型映射:AdvancedResult
第二个类是 AdvancedResult。用于原始查询,因为 DB::select(...) 返回一个集合。每个属性都可以映射到模型。如果第三个参数提供为 true,则返回单个结果。这是一个对象,而不是集合。
$asdf = DB::select("SELECT TOP 3 * FROM Events INNER JOIN CommonData ON ..."); // The first argument is passed by reference so there's no need to set the variable to be returned. // The second argument is optional, if you want to set it later. AdvancedResult::make($asdf, [ 'EventDate' => Events::class, 'reminderemailText' => CommonData::class, 'PriceCount' => 'integer' ]); // This is how you would call the argument later. $asdf->map(function($record){ $record->modelMapper([ 'EventDate' => Events::class, 'PriceCount' => 'integer' ]); return $record; });