ahmedwaleed / soquel
用于 Salesforce 对象查询语言 (SOQL) 的 ORM 解决方案
Requires
- php: ^7.4|^8.0
- omniphx/forrest: ^2.11
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.17
- laravel/framework: ^8.21
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.3
README
Laravel SOQL 查询构建器提供了一个便捷的流畅接口来创建、更新、SOQL 查询,并从 Salesforce 中检索记录。
要求
- PHP >= 7.4
- Laravel >= 8
- omniphx/forrest >= 2.*
此包使用 omniphx/forrest 包作为 Salesforce 客户端从 Salesforce 检索记录,请参阅包的 GitHub 页面获取安装和配置指南。
安装
您可以通过 composer 安装此包。
composer require ahmedwaleed/soquel
可选地,您可以发布包的配置文件。
php artisan vendor:publish --provider="Omniphx\Forrest\Providers\Laravel\ForrestServiceProvider::class"
使用您的 Salesforce 凭证设置以下配置。
'credentials' => [ // Required: 'consumerKey' => env('SF_CONSUMER_KEY'), 'consumerSecret' => env('SF_CONSUMER_SECRET'), 'callbackURI' => env('SF_CALLBACK_URI'), 'loginURL' => env('SF_LOGIN_URL'), // Only required for UserPassword authentication: 'username' => env('SF_USERNAME'), // Security token might need to be ammended to password unless IP Address is whitelisted 'password' => env('SF_PASSWORD'), ]
将存储类型更新为 Session
或 Cache
,目前只支持这些存储类型。
'storage' => [ 'type' => 'cache', // Options include: 'session', 'cache', 'object' 'path' => 'forrest_', // unique storage path to avoid collisions 'expire_in' => 60, // number of minutes to expire cache/session 'store_forever' => false, // never expire cache/session ]
基本用法
配置文件的内容将发布到 config/soquel.php
- 从对象检索所有行
use AhmadWaleed\Soquel\SOQL; echo SOQL::object('Account')->select('Id', 'Name')->toSOQL(); // Output: SELECT Id, Name FROM Account
- WHERE 子句
SOQL::object('Account')->select('Id', 'Name')->where('Id', '=', 's3dty')->toSOQL(); SOQL::object('Account')->select('Id', 'Name')->where('Name', 'Like', '%john%')->toSOQL();
- 附加 WHERE 子句
SOQL::object('Account')->select('Id', 'Name')->where('Id', '=', 's3dty')->orWhere('Id', '=', '2abc')->toSOQL(); SOQL::object('Account')->select('Id', 'Name')->whereIn('Id', ['s3dty', 'ty4ii'])->toSOQL(); SOQL::object('Account')->select('Id', 'Name')->whereNull('Name')->toSOQL(); SOQL::object('Account')->select('Id', 'Name')->whereNotNull('Name')->toSOQL(); SOQL::object('Account')->select('Id', 'Name')->whereRaw("DISTANCE(Contact__r.Geolocation__c, GEOLOCATION(15.623,35.949), 'km') < 1000")->toSOQL();
- 选择子查询
SOQL::object('Account')->select('Id', 'Name')->selectSub(SOQL::object('Contact')->select('Id', 'Name'))->toSOQL();
- 子查询 WHERE 子句
SOQL::object('Account')->select('Id')->whereIn('Id', SOQL::object('Contact')->select('Account.Id'))->toSOQL();
- 排序 & 限制
SOQL::object('Account')->select('Id')->orderBy('Id')->toSOQL(); // default order DESC SOQL::object('Account')->select('Id')->orderBy('Name', 'ACS')->toSOQL(); SOQL::object('Account')->select('Id')->limit(1)->toSOQL();
ORM 使用
当您需要完全控制查询时,查询构建器很好,但在需要选择对象的所有字段或加载子/父对象行时,它会变得繁琐。此包还提供对象关系映射器 (ORM) 支持,使得与 SOQL 交互变得轻松愉快。
生成对象类
要开始,让我们创建一个对象类,该类默认位于 app/Objects
目录,并扩展 AhmadWaleed\Soquel\Object\BaseObject
类,但您可以在配置文件中更改默认目录。您可以使用 make:object
artisan 命令生成新的对象类
php artisan make:object Account
上述命令将生成以下类
<?php namespace App\Objects; use AhmadWaleed\Soquel\Object\BaseObject; class Account extends BaseObject { }
如果您想生成自定义对象类,可以使用 --type
或 -t
选项
php artisan make:object Job --type=custom
上述命令将生成以下类
<?php namespace App\Objects; use AhmadWaleed\Soquel\Object\BaseObject; class Job extends BaseObject { protected string $sobject = 'Job__c'; }
默认情况下,将检索 Salesforce 对象的 Id 字段,您也可以在模型上定义您想要与每条记录一起返回的字段。
public array $fields = [ 'Name', 'Email', ];
默认情况下,Id 字段是只读的,您可以在模型上指定在执行插入/更新操作时应排除哪些字段。
protected array $readOnly = ['Name'];
检索对象
一旦创建了对象,您就可以开始从 Salesforce 检索数据了。您可以将每个对象类视为一个功能强大的查询构建器,允许您流畅地查询 Salesforce 对象数据。get 方法将检索关联对象的所有记录(Salesforce 限制为 2000 条)。
use App\Objects\Account; foreach(Account::new()->query()->get() as $account) { echo $account->name; }
构建查询
每个对象类都充当查询构建器,您可以通过添加额外的约束到查询中,并调用 get 方法来检索结果
$accounts = Account::new() ->query() ->where('name', 'LIKE', '%john%') ->limit(10) ->get();
集合
正如我们所看到的,对象方法(如 get)从 Salesforce 检索多条记录。然而,这些方法不返回普通的 PHP 数组。相反,返回的是 Illuminate\Database\Eloquent\Collection 的实例。
对象类扩展了 Laravel 的基础 Illuminate\Support\Collection 类,它为与数据集合交互提供了一系列有用的方法。例如,可以使用 reject 方法根据调用的闭包的结果从集合中删除对象。
$accounts = Account::new()->query()->whereNotNull('Email')->get(); $accounts = $accounts->reject(fn (Account $account) => $account->isActive);
关系
Salesforce的对象通常相互关联。例如,一个账户可能有许多联系人,或者一个联系人可以与账户相关联。SOQL ORM使得管理和处理这些关系变得简单,并且支持父子关系。
定义关系
关系被定义为对象类上的方法。由于关系也作为强大的查询构建器,将关系定义为方法提供了强大的方法链和查询能力。例如,我们可以在这种联系人关系上链额外的查询约束。
$account->contacts()->where('Name', 'LIKE', '%john%');
但是,在深入使用关系之前,让我们学习如何定义每种类型的关系。
子到父
子到父关系是Salesforce关系中最基本的一种类型。例如,联系人对象可能与一个账户对象相关联。为了定义这种关系,我们将在联系人对象上放置一个账户方法。账户方法应该调用父关系方法并返回其结果。父关系方法通过AhmadWaleed\Soquel\Object\BaseObject基类对您的模型可用。
<?php namespace AhmadWaleed\Soquel\Tests\Objects; use AhmadWaleed\Soquel\Object\BaseObject; use AhmadWaleed\Soquel\Object\ParentRelation; class Contact extends BaseObject { public Account $account; public function account(): ParentRelation { return $this->parentRelation(Account::class); } }
传递给父关系方法的第一参数是相关对象类的名称。一旦定义了关系,我们可以使用以下查询检索相关记录:
$account = Contact::new()->query()->with('account')->find('id')->account;
此外,您还可以将对象类型和关系名称作为第二和第三参数传递给父关系方法;
return $this->parentRelation(Job::class, 'Job__c');
对于自定义对象,orm假定关系名称,例如对于自定义对象Job__c,关系名称将是Job__r。但是,如果您想覆盖默认约定,可以将关系名称作为第三个参数传递。
return $this->parentRelation(Job::class, 'Job__c', 'jobs');
父到子
父到子关系用于定义单个对象是父对象到一个或多个子对象的关系。例如,一个账户可能有无限数量的联系人。像所有其他Salesforce关系一样,父到子关系是通过在对象类上定义方法来定义的。
<?php namespace AhmadWaleed\Soquel\Tests\Objects; use AhmadWaleed\Soquel\Object\BaseObject; use AhmadWaleed\Soquel\Object\ChildRelation; use Illuminate\Support\Collection; class Account extends BaseObject { public Collection $contacts; public function contacts(): ChildRelation { return $this->childRelation(Contact::class); } }
传递给childRelation方法的第一个参数是相关对象类的名称。一旦定义了关系,我们可以使用以下查询检索相关记录:
$contacts = Account::new()->query()->with('contacts')->find('id')->contacts;
此外,您还可以将对象类型和关系名称作为第二和第三参数传递给childRelation方法;
return $this->childRelation(Attachment::class, 'Attachment__c');
对于自定义对象,orm假定关系名称,例如对于自定义对象Attachment__c,关系名称将是Attachment__r。但是,如果您想覆盖默认约定,可以将关系名称作为第三个参数传递。
return $this->childRelation(Attachment::class, 'Attachment__c', 'attachments');
插入和更新
- 插入
$contact = new Contact(); $contact->LastName = 'doe'; $contact->Email = 'john@example.com'; $contact->save(); // OR $contact = Contact::create(['LastName' => 'doe', 'Email', 'john@example.com']);
- 插入集合
$contacts = collect([ new Contact(['Email' => 'email1@test.com']), new Contact(['Email' => 'email2@test.com']) ]); Contact::saveMany($contacts); // OR $contacts = collect([ ['Email' => 'email1@test.com'], ['Email' => 'email2@test.com'] ]); Contact::saveMany($contacts);
- 更新
$contact = new Contact(); $contact->LastName = 'michael'; $contact->save(); // OR $contact = $contact->update(['LastName' => 'michael', 'Email', 'michael@example.com']);
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。