gearbox-solutions/eloquent-filemaker

一个将FileMaker记录作为Laravel模型获取的包


README

Total Downloads Latest Stable Version License

Eloquent-FileMaker是一个用于Laravel的PHP包,通过FileMaker数据API使使用FileMaker数据库变得更容易。此项目的目标是提供与通过数据API使用MySQL在原生Laravel中工作相似的接口。

此包允许您通过数据API轻松连接到您的FileMaker数据库,并以Laravel模型的形式获取记录数据,尽可能支持许多原生功能。

支持

此包由Gearbox Solutions构建和维护。我们使用Laravel、Vue、React和Node等技术构建出色的Web应用程序。如果您想获得帮助构建自己的Web应用程序,无论是使用此包还是其他项目,请联系我们进行免费咨询,讨论您的项目。

特性

  • 使用FileMaker数据API访问您的FileMaker数据
  • 支持访问多个文件或使用多个凭据集
  • FMModel类
    • 扩展基础模型类,允许与许多标准模型功能兼容
    • 关系支持
    • 容器数据读写
    • 自动名称/布局/表解析
    • 门户数据读写
    • FileMaker到Laravel字段名重映射
  • 自动身份验证和会话管理
  • Eloquent查询构建器和基础查询构建器
  • 原始连接服务,易于访问数据API
  • FileMaker数据库连接驱动程序
  • 运行脚本
  • 等等!

支持的Laravel版本

我们支持目前支持的Laravel版本。Laravel的早期版本可能兼容,但如果需要不兼容的更改,则可能在将来被删除。

2.0版本中的新功能

  • 增加了对Laravel 11的支持
  • 默认情况下,FileMaker中的空字段返回null而不是空字符串
  • FileMaker会话仅持续单个Laravel请求的持续时间,而不是默认情况下重复使用15分钟 - 这可以在配置中更改
  • 改进了whereNot逻辑和实现,使其更接近应有的行为

从1.x升级到2.x

运行composer require gearbox-solutions/eloquent-filemaker:^2.0以升级到包的最新版本。

代码中可能出现的更改

包的使用通常保持不变。但是,有一些更改可能会影响您的代码。阅读下面的更改,以了解在升级时可能需要哪些重构。

主要 - 空字段的更改

在版本1.0中,FileMaker中的空字段返回空字符串。在版本2.0中,空字段返回null。此更改使处理FileMaker数据更接近Laravel开发者对数据库的期望。

如果您想继续使用旧的行为,可以将 empty_strings_to_null 配置值更改为 false 以保留空字符串。否则,如果您有任何依赖空字段返回空字符串的代码,您可能需要重构您的代码以适应新的行为。

小改 - 改进 whereNot 逻辑

在某些情况下,whereNot 可能返回不正确或未预期的结果。这已在 2.0 版本中修复。如果您有任何依赖旧的不正确 whereNot 行为的代码,您可能需要重构您的代码以适应新的修正行为。

安装

使用 Composer 在您的项目中安装 gearbox-solutions/eloquent-filemaker

composer require gearbox-solutions/eloquent-filemaker

使用方法

安装该包后,您现在可以访问该包的所有功能。有几个不同的配置区域。

数据库配置

首先要做的是在您的 database.php 配置文件中添加一个新的数据连接。您在此处指定的连接将用于您的 FMModel 类中,以配置每个模型将连接到哪个数据库。

以下代码块可以作为模板,其中包含一些良好的默认设置。

'filemaker' => [
    'driver' => 'filemaker',
    'host' => env('DB_HOST', 'fms.mycompany.com'),
    'database' => env('DB_DATABASE', 'MyFileName'),
    'username' => env('DB_USERNAME', 'myusername'),
    'password' => env('DB_PASSWORD', ''),
    'prefix' => env('DB_PREFIX', ''),
    'version' => env('DB_VERSION', 'vLatest'),
    'protocol' => env('DB_PROTOCOL', 'https'),
    'cache_session_token' => env('DB_CACHE_SESSION_TOKEN', true), // set to false to log out after each reqeust. This can be slower than re-using a session token, but allows for globals to be set for individual user values.
    'empty_strings_to_null' => env('DB_EMPTY_STRINGS_TO_NULL', true), // set to false to return empty strings instead of null values when fields are empty in FileMaker
]

您应该为每个您要连接的 FileMaker 数据库添加一个数据库连接配置。每个文件可以具有完全不同的配置,甚至可以位于不同的服务器上。

如果 cache_session_token 为 true,登录会话将根据每个连接进行维护,并且令牌将自动使用您为您的 Laravel 应用程序设置的任何缓存配置进行缓存。这可以防止在每个请求中重新登录到数据 API,这可以提高性能。如果您为您的 Laravel 应用程序配置了缓存,通常应将其设置为 true。

前缀

前缀配置选项将前缀添加到您指定的每个布局/表名称中。您不需要指定前缀,但这样做可能非常方便。

创建专门用于数据 API 的布局是良好的实践,而不是使用您常规的 GUI 或开发者布局,这些布局可能很慢,并且包含不必要的字段。为您的网络应用程序创建专门布局可以允许您优化数据 API 的使用,并最大限度地提高网络应用程序的性能。考虑到这一点,管理这些布局的一种简单方法是将它们组织在一个文件夹中,并给它们一个前缀,这样您就可以知道它们用于什么。

例如,假设您有三个表 - 组织、联系人和发票。您可能希望为您的网络应用程序创建布局,例如 "dapi-organizations"、"dapi-contacts" 和 "dapi-invoices"。如果您使用相同的文本为它们添加前缀,您可以设置前缀值,这样您就可以在 Laravel 中将它们称为 "organizations"、"contacts" 和 "invoices"。如果您正确命名模型类,根据 Laravel 的命名指南,您甚至可以自动解析布局,而无需手动输入它们!

Laravel 缓存配置

Eloquent FileMaker 将使用您的应用程序的缓存来在请求之间缓存 FileMaker 数据 API 会话令牌。为了使其正常工作,您需要确保您没有将 FileMaker 连接作为缓存驱动程序使用。

Laravel 的默认设置是使用 database 缓存驱动程序。如果您的 FileMaker 数据库连接也是您的默认驱动程序,您需要更改您的缓存配置为其他内容,例如 fileredis。您可以在 .env 中更改您的缓存驱动程序。

Laravel 11

cache_store=file

Laravel 10 及更早版本

cache_driver=file

模型类

创建模型类是访问FileMaker数据的最容易方法,也是最符合Laravel风格的做法。创建一个新的模型类,并将扩展类从Model更改为FMModel。这种类更改使您能够使用此包的功能来处理您的模型。

可行的事物

FMModel类扩展了Laravel基础模型类,可以非常相似地使用。它支持许多标准Eloquent查询构建器功能,用于处理数据,如where()、find()、id()、orderBy()、delete()、save()等!

支持模型功能,如访问器和修改器,以及自动表/布局名称解析、事件触发、观察者、belongsTo、hasOne和hasMany关系、序列化(包括受保护属性等),以及尽可能保证兼容的其他事物。

我们的目标是能够使用所有有意义的Eloquent功能,因此此包将尽可能支持更多。提交一个更新或让我们知道如果您认为有什么不工作但应该支持的功能。

请务必阅读Laravel的Eloquent文档,以查看Eloquent模型类可以执行的所有操作。

不可行的事物

由于此类扩展了Model,所以所有常规eloquent方法可能都会显示为在您的IDE中可用,但其中一些在FileMaker数据API的上下文中没有意义,因此不执行任何操作。一些此类示例包括批量更新或原始SQL查询。

设置布局

您针对FileMaker数据库的查询需要从特定的布局获取数据。Eloquent-FileMaker支持Laravel的表名称猜测,但在您的布局名称不匹配的情况下,您可以通过在模型类上设置$layout属性来指定与模型一起使用的布局名称。

protected $layout = 'MyLayout';

空值和空字符串

在处理数据库时,空值是开发人员期望的重要可能值。不幸的是,作为平台的FileMaker没有空值的概念。未写入值的字段将包含一个空字符串。为了使此行为更适合Web开发者,Eloquent FileMaker在从数据API读取数据时自动将FileMaker字段的''值转换为null

如果您希望将空的FileMaker字段返回为空字符串,可以在您的连接配置中将empty_strings_to_null配置值设置为false。

Eloquent FileMaker将始终自动将null值转换为'',以防止将数据写回到您的FileMaker数据库时出现错误。

只读字段

您的FileMaker数据库中的许多字段将是只读的,例如摘要和计算字段,尽管您仍然希望在从数据库检索数据时获取它们。FMModels将尝试将所有已修改的属性写回到您的FileMaker数据库。如果您写入只读字段,例如计算字段,则在尝试将该字段写回到FileMaker数据库时将收到错误。

容器字段

此包支持读取和写入容器字段数据。容器字段作为包含可以用来检索文件URL的属性的模型属性从FileMaker检索。

请注意:FileMaker数据API不允许您在相关记录中写入容器字段。

FileMaker数据API容器字段文档

容器字段必须是指定布局的表实例中的字段。它不能是相关表中的容器字段。

写入容器字段

设置容器字段时,应将值设置为Illuminate/HTTP/FileIlluminate/HTTP/UploadedFile对象。这些属性将在调用模型对象的save()方法时,与任何其他模型更新一起写回到容器字段。

$file = new File(storage_path('app/public/gator.jpg'));
$newPet->photo = $file;
$newPet->save();

在容器中插入文件时自定义文件名

默认情况下,文件使用您要插入的文件的文件名插入到容器中。如果您希望在文件插入容器时设置新的文件名,可以在设置容器时通过数组将文件和文件名一起传递来实现。

$file = new File(storage_path('app/public/gator.jpg'));
$newPet->photo = [$file, 'fluffy.jpg'];
$newPet->save();

重命名和映射FileMaker字段

有时您可能会处理具有不便的字段名的FileMaker数据库。可以通过设置$fieldMapping属性将这些字段重映射到模型属性。这应该是一个字符串数组,将FileMaker字段名映射到新属性名。然后,您可以使用这些名称作为常规Eloquent属性,并且它们将与FileMaker中的正确字段一起工作。

protected $fieldMapping = [
  'My Inconveniently Named Field' => 'a_much_better_name'
];

然后您可以通过以下方式获取/设置属性...

$myModel->a_much_better_name = 'my new value';

相关记录的字段

如果您通过数据API布局中的关系包括了相关记录的字段,您需要添加一个$fieldMapping属性才能访问您的相关数据。

例如,如果您有一个与第一个拥有汽车记录的一对一关系的Person表

protected $fieldMapping = [
  'person_CARfirst::color' => 'first_car_color',
  'person_CARfirst::make' => 'first_car_make',
  'person_CARfirst::model' => 'first_car_model'
];

相关数据可以像模型的其他任何属性一样获取/设置。数据将从第一个相关记录读取并写回。

$personFirstCarColor = $person->first_car_color;

门户数据

您可以根据FileMaker布局中门户的对象名称作为属性访问门户数据。可以使用字段名称的数组键访问字段。

例如,如果您在布局上有一个名为"person_pet_portal"的门户,其对象名称基于"person_PET"关系,您可以通过该属性的数组来访问您的门户数据

// Get the name of the first related Pet
$firstPetName = $person->person_pet_portal[0]['person_PET::name'];

您可以通过相同的方式将数据写回门户

// Set the 'type' of the second related pet in the portal
$person->person_pet_portal[1]['person_PET::type'] = 'cat';

转换FileMaker时间戳和日期字段

此包为您提供了特殊处理,将FileMaker时间戳和日期字段转换为Carbon实例。为了利用这一点,您必须像使用本地Laravel模型类一样映射字段。您可以使用通常用于这些属性的$casts属性。

protected $casts = [
    'nextAppointment' => 'datetime',
    'birthday' => 'date',
];

写入FileMaker的日期和时间戳字段的格式可以通过模型中$dateFormat属性的值进行更改。此值必须与FileMaker数据API输出的时间戳值格式兼容,并将是写入数据库的格式。一个重要要求是这必须是一个完整的日期时间格式,而不仅仅是日期格式。

以下是一些示例格式

protected $dateFormat = 'n/j/Y g:i:s A'; // 7/1/1920 4:01:01 PM
protected $dateFormat = 'n/j/Y G:i:s'; // 7/1/1920 16:01:01

示例FMModel类

// Person.php

class Person extends FMModel
{

    protected $layout = "person";

    protected $fieldMapping = [
        'first name' => 'nameFirst',
        'last name' => 'nameLast'
    ];

    protected $casts = [
        'birthday' => 'date',
    ];


    public function pets(){
        return $this->hasMany(Pet::class);
    }

}

基本查询构建器和FM外观

类似于本地的DB外观,您可以使用FM外观生成和执行查询,而无需通过模型。这对于使用非表相关的数据API功能非常有用,例如设置全局变量或执行脚本,尽管您也可以用它来检索记录。虽然FMModel和它使用的Eloquent查询构建器将返回组织良好的FMModel集合,但基本查询构建器将返回来自FileMaker数据API的直接响应。

FM外观提供了对FMBaseQueryBuilder类的访问,该类也被FMModel对象使用的Eloquent构建器利用。FMBaseQueryBuilder的方法也对FMModel Eloquent构建器可用。

在此包设置完成后,DB外观仍适用于对FileMaker数据库进行基本记录查询,例如DB::table('pets')>where('name', 'Cosmo')>first(),但FM外观将允许您访问更多FileMaker特定的功能,并且通常应使用它而不是DB来访问您的FileMaker数据。

与FMModel类和Eloquent构建器一样,目标是支持与DB外观相同的特性集,因此请查看Laravel查询构建器文档,以了解基本查询构建器特性。

FileMaker查询构建器和FM外观中的FileMaker特定功能

除了基本的查询构建器功能之外,通过FM外观或FMModel eloquent构建器访问的FMBaseQueryBuilder类还提供了许多新的FileMaker特定方法。

FileMaker数据API支持在请求中支持许多参数,用于执行脚本和在不同时间传递参数。请查看FileMaker数据API指南以及更具体的数据API参考文档,以了解每个特定调用支持哪些选项。

数据API参考文档可以通过遵循API指南中的说明在运行的FileMaker服务器上查看。

一般来说

“要查看远程FileMaker服务器上的参考,请打开浏览器并输入URL https://host/fmi/data/apidoc/,其中host是运行FileMaker Server的主机的IP地址或主机名。”

以下是一些允许您为数据API特性设置参数的方法列表。请注意,这些方法中的大多数都可以像标准查询构建器一样链式调用。

从以下开始

FM::table()
FM::connection()
FM::layout() // alias for table()
FM::setGlobalFields() // not chainable

链式可调用

// standard query-builder stuff like where, orderBy, etc.
->limit( $value )
->offset( $value )
->script( $scriptName, $param)
->scriptParam( $param )
->scriptPresort( $scriptName, $param
->scriptPresortParam( $param )
->scriptPrerequest( $scriptName, $param )
->scriptPrerequestParam( $param )
->layoutResponse( $layoutName )
->portal( $portalName )
->portalLimit( $portalName, $limit )
->portalOffset( $portalName, $startingRecord  )
->sort() // alias for the native orderBy()
->omit()
->fieldData( $array )
->portalData( $array )

最终链式链接方法

// standard query-builder stuff like get, first, etc.
->findByRecordId()
->performScript()
->setContainer()
->duplicate()
->createRecord()
->getLayoutMetadata()

示例

为名为Jaina的人执行查找

$person = FM::table('person')->where('nameFirst', 'Jaina')->first();

查找客户的10个最新发票

$invoices = FM::layout('invoice')->where('customer_id', $customer->id)->orderByDesc('date')->limit(10)->get();

获取布局元数据,包括字段、端口和值列表信息

$layoutMetadata = FM::getLayoutMetadata('MyLayoutName');

获取特定记录的布局元数据

$layoutMetadata = FM::layout('MyLayoutName')->recordId(879)->getLayoutMetadata();

运行脚本

$result = FM::layout('MyLayoutName')->performScript('MyScriptName');

带有JSON数据的参数运行脚本

$json = json_encode ([
    'name' => 'Joe Smith',
    'birthday' => '1/1/1970'
    'favorite_color' => 'blue'
]);

$result = FM::layout('globals')->performScript('New Contact Request'; $json);

在默认数据库连接之外运行脚本

$result = FM::connection('MyOtherDatabaseConnectionName')->layout('MyLayoutName')->performScript('MyScriptName');

使用字段数据数组创建记录,然后在同一请求中创建记录后执行脚本

FM::layout('MyLayoutName')->script('ScriptName')->fieldData($data)->createRecord();

设置全局字段。全局字段需要使用完整的table_name::field_name语法。

        $globalFields = [
            'GLOB::my_global_field' => 'New global value',
            'GLOB::other_global_field' => 'New global value',

        ];
        FM::setGlobalFields($globalFields);

注销、断开连接并结束您的数据API会话

Eloquent-FileMaker试图通过在请求之间缓存会话令牌来自动重用会话令牌。这意味着您将在FileMaker服务器管理控制台中看到会话保持打开状态。它将根据您的服务器或数据库的断开设置自动断开。

如果您想手动注销并结束会话,您可以通过FM外观或通过模型来完成。

FM::connection()->disconnect();

MyModel::getConnectionResolver()->connection()->disconnect();

将原生Laravel模型与FMModels关联

可能将来自MySQL数据库的原生Laravel Model对象与来自FileMaker数据库的FMModel对象之间的关系。为此,您需要在您的database.config文件中设置这两个连接,然后确保您的模型通过在Model和FMModel类中设置$connection属性指向正确的连接。

protected $connection = 'theConnectionName';

一旦连接设置正确,FMModel对象到基于SQL的Model对象的关联应该可以自动正确解析。对于版本>2.3.0的普通Model对象到FMModel对象的关联,需要添加一个新的特质到您的模型类以启用创建关系。对于版本小于2.3.0或需要更多控制关系的用户,可以使用以下示例手动添加关系连接。

您可以通过手动创建一个新的eloquent-filemaker belongsTo对象或导入一个新的特质并设置适当的键来创建关系,例如belongsTo。

使用特质创建关系(2.3.0+)

HasHybridRelationships 特性允许模型自动从 Model 解析到 FMModel 的关系。以下是一个示例,使用该特性在 SQL 数据库中创建一个本地的 Laravel User Model,使其属于基于 FileMaker 的 Company FMModel 类。

// User.php

use GearboxSolutions\EloquentFileMaker\Database\Eloquent\Concerns\HasHybridRelationships;

class User extends Model
{
    use HasHybridRelationships;
    
    public function company()
    {
        // The Company class is an FMModel and is stored in FileMaker
        // The correct relationship will be resolved automatically thanks to the HasHybridRelationships trait
        return $this->belongsTo(Company::class, 'company_id', 'id');
    }
}

创建此关系后,我们现在可以像在单个数据库中的正常关系一样获取用户所属的 Company FMModel。

// set $company to a FMModel of the User's Company
$company = $user->company;

手动创建关系

使用 HasHybridRelationships 特性是创建本地 Laravel 模型和 FMModel 之间关系的最简单方法。然而,如果您正在使用较旧的 Eloquent FileMaker 版本或想手动管理关系,您可以通过使用 Eloquent FileMaker 的关系类型版本来建立关系。每个有效的关联类型都将可在 \GearboxSolutions\EloquentFileMaker\Database\Eloquent\Relations\ 命名空间下找到。

以下是将本地 Laravel User 模型设置为属于基于 FileMaker 的 Company FMModel 类的示例。

// User.php

class User extends Model
{
    public function company()
    {
        // The Company class is an FMModel and is stored in FileMaker
        return new \GearboxSolutions\EloquentFileMaker\Database\Eloquent\Relations\BelongsTo(Company::query(), $this, 'company_id', 'id', '');
    }
}

许可证

Eloquent-FileMaker 是在 MIT 许可下许可的开源软件。