codelicia/trineforce

salesforce Soql Doctrine Driver

1.2.1 2023-01-17 12:36 UTC

README

salesforce Soql Doctrine Driver 允许您使用 Doctrine DBAL 层编写 Soql 查询并与 Salesforce 实例交互。

现在可以忘记 Salesforce,在架构中实现一个愉快的 repository/query object 集成,而不会对常规项目结构造成太大影响。

安装

使用 composer 按以下方式安装此包

$ composer require codelicia/trineforce

配置

如果您熟悉 Doctrine,那么您可能已经知道如何配置和使用它。但为了使其正常工作,需要一些特殊的配置。

在创建新的 Connection 时,还应提供 salesforceInstanceconsumerKeyconsumerSecret 的配置密钥,并指向正确的 driverClass。通常还需要 userpassword

$config = new Configuration();
$connectionParams = [
    'salesforceInstance' => 'https://[SALESFORCE INSTANCE].salesforce.com',
    'apiVersion'         => 'v43.0',
    'user'               => 'salesforce-user@email.com',
    'password'           => 'salesforce-password',
    'consumerKey'        => '...',
    'consumerSecret'     => '...',
    'driverClass'        => \Codelicia\Soql\SoqlDriver::class,
    'wrapperClass'       => \Codelicia\Soql\ConnectionWrapper::class,
];

/** @var \Codelicia\Soql\ConnectionWrapper $conn */
$conn = DriverManager::getConnection($connectionParams, $config);
  • user 提供登录信息,通常是用于访问 Salesforce 实例的电子邮件。
  • password 提供与在 user 中提供的电子邮件相对应的密码。
  • salesforceInstance 指向 Salesforce 实例的 URL。
  • apiVersion 指定要与之一起工作的 Salesforce API 版本。
  • consumerKey 提供集成消费者密钥
  • consumerSecret 提供集成消费者密钥
  • driverClass 应指向 \Codelicia\Soql\SoqlDriver::class
  • wrapperClass 应指向 \Codelicia\Soql\ConnectionWrapper::class

通过设置 wrapperClass,我们可以使用一个适当的 QueryBuild 允许在 Salesforce 格式中进行 JOIN

当使用 doctrine 包和 dbal 通过 yaml 配置时,选项应以不同的方式传递,以便进行包的验证。

doctrine:
    dbal:
        driver: soql
        user: '%env(resolve:SALESFORCE_USERNAME)%'
        password: '%env(resolve:SALESFORCE_PASSWORD)%'
        driver_class: '\Codelicia\Soql\SoqlDriver'
        wrapper_class: '\Codelicia\Soql\ConnectionWrapper'
        options:
            salesforceInstance: '%env(resolve:SALESFORCE_ENDPOINT)%'
            apiVersion: v56.0
            consumerKey: '%env(resolve:SALESFORCE_CLIENT_ID)%'
            consumerSecret: '%env(resolve:SALESFORCE_CLIENT_SECRET)%'

使用 DBAL

现在您已设置连接,您可以使用 Doctrine QueryBuilder 查询一些数据,如下所示

$id = '0062X00000vLZDVQA4';

$sql = $conn->createQueryBuilder()
    ->select(['Id', 'Name', 'Status__c'])
    ->from('Opportunity')
    ->where('Id = :id')
    ->andWhere('Name = :name')
    ->setParameter('name', 'Pay as you go Opportunity')
    ->setParameter('id', $id)
    ->setMaxResults(1)
    ->execute();

var_dump($sql->fetchAll()); // All rest api result

或使用正常的 Connection#query() 方法。

基本操作

以下是基本 CRUD 操作的一些示例。

Connection#insert()

创建一个名为 JohnAccount

$connection->insert('Account', ['Name' => 'John']);

Connection#delete()

删除 Id = 1234Account

$connection->delete('Account', ['Id' => '1234']);

Connection#update()

更新 Id1234Account,名称为 Sr. John

$connection->update('Account', ['Name' => 'Sr. John'], ['Id' => '1234']);

使用 Composite API 进行事务操作

随着 Salesforce 发布了 composite API,它为我们提供了模拟数据库中事务的能力。因此,我们可以使用您已经熟悉的相同 Doctrine DBAL API 在 Salesforce 实例中执行事务操作。

$conn->beginTransaction();

$conn->insert('Account', ['Name' => 'John']);
$conn->insert('Account', ['Name' => 'Elsa']);

$conn->commit();

或者,甚至可以使用您喜欢的 Connection#transactional() 辅助函数。

引用其他记录

composite API 还使我们能够在一个请求中组合结构化数据以进行更改。因此,我们可以根据需要交叉引用记录。

让我们看看如何在单个 composite 请求中创建一个 Account 和一个链接到该 AccountContact

$conn->transactional(static function () use ($conn) {

    $conn->insert('Account', ['Name' => 'John'], ['referenceId' => 'account']);
    $conn->insert('Contact', [
        'FirstName' => 'John',
        'LastName' => 'Contact',
        'AccountId' => '@{account.id}' // reference `Account` by its `referenceId`
    ]);

});

🚫 已知限制

截至今天,我们无法使用 queryBuilder 消费 sObject 以从 sObject 获取所有字段。这是因为 Salesforce 不接受 SELECT * 作为有效查询。

解决这个问题的一种方法是向特定资源发送一个 GET 请求,然后可以抓取与该资源相关的所有数据。

$this->connection
    ->getNativeConnection() // : \GuzzleHttp\ClientInterface
    ->request(
        'GET',
        sprintf('/services/data/v40.0/sobjects/Opportunity/%s', $id)
    )
    ->getBody()
    ->getContents()
;

📈 图表

作者