codelicia/trineforce 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

codelicia/trineforce

Composer 安装命令:

composer require codelicia/trineforce

包简介

Salesforce Soql Doctrine Driver

README 文档

README

Salesforce Soql Doctrine Driver allows you to write Soql queries and interact with a Salesforce instance using the Doctrine DBAL layer.

Now one can forget about Salesforce and have a nice repository/query object integration on one's architecture without hurting that much on the usual project structure.

Installation

Use composer to install this package as bellow:

$ composer require codelicia/trineforce

Configuration

If you are familiar with Doctrine, then you probably already know how to configure and use it. But some special configuration is required in order to make it work.

When creating a new Connection, you should also provide the configuration keys for salesforceInstance, consumerKey, consumerSecret and point to the right driverClass. The usual user and password are also required.

$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 provides the login, which is usually an email to access the salesforce instance.
  • password provides the corresponding password to the email provided on user.
  • salesforceInstance points to the url of the Salesforce instance.
  • apiVersion specify a salesforce API version to work with.
  • consumerKey provides the integration consumer key
  • consumerSecret provides the integration consumer secret
  • driverClass should points to \Codelicia\Soql\SoqlDriver::class
  • wrapperClass should points to \Codelicia\Soql\ConnectionWrapper::class

By setting up the wrapperClass, we can make use of a proper QueryBuild that allow JOIN in the Salesforce format.

When using the doctrine bundle and the dbal is configured through yaml the options should be passed in a different way for the validation that the bundle does.

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)%'

Using DBAL

Now that you have the connection set up, you can use Doctrine QueryBuilder to query some data as bellow:

$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

or use the normal Connection#query() method.

Basic Operations

Here are some examples of basic CRUD operations.

Connection#insert()

Creating an Account with the Name of John:

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

Connection#delete()

Deleting an Account with the Id = 1234:

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

Connection#update()

Update an Account with the Name of Sr. John where the Id is 1234:

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

Be Transactional with Composite API

As salesforce released the composite api, it gave us the ability to simulate transactions as in a database. So, we can use the same Doctrine DBAL api that you already know to do transactional operations in your Salesforce instance.

$conn->beginTransaction();

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

$conn->commit();

Or even, use the Connection#transactional() helper, as you prefer.

Referencing another Records

The composite api, also enables us to compose a structure data to be changed in one single request. So we can cross reference records as it fits our needs.

Let's see how to create an Account and a linked Contact to that Account in a single composite request.

$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`
    ]);

});

🚫 Known Limitations

As of today, we cannot consume a sObject using the queryBuilder to get all fields from the sObject. That is because Salesforce doesn't accept SELECT * as a valid query.

The workaround that issue is to do a GET request to specific resources, then can grab all data related to that resource.

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

📈 Diagram

%%{init: {'sequence': { 'mirrorActors': false, 'rightAngles': true, 'messageAlign': 'center', 'actorFontSize': 20, 'actorFontWeight': 900, 'noteFontSize': 18, 'noteFontWeight': 600, 'messageFontSize': 20}}}%%
%%{init: {'theme': 'base', 'themeVariables': { 'actorBorder': '#D86613', 'activationBorderColor': '#232F3E', 'activationBkgColor': '#D86613','noteBorderColor': '#232F3E', 'signalColor': 'white', 'signalTextColor': 'gray', 'sequenceNumberColor': '#232F3E'}}}%%
sequenceDiagram
    autonumber
    Note left of ConnectionWrapper: Everything starts with <br/>the ConnectionWrapper.
    ConnectionWrapper->>QueryBuilder: createQueryBuilder()
    activate QueryBuilder
    alt 
        QueryBuilder->>QueryBuilder: execute() <br>Calls private executeQuery()<br>method
    end
    QueryBuilder->>+ConnectionWrapper: executeQuery()
    deactivate QueryBuilder
    ConnectionWrapper->>SoqlStatement: execute() 
    SoqlStatement->>+\Doctrine\DBAL\Driver\Result: execute()
    ConnectionWrapper->>+\Codelicia\Soql\DBAL\Result: new
    \Doctrine\DBAL\Driver\Result-->>\Codelicia\Soql\DBAL\Result: pass to
    \Codelicia\Soql\DBAL\Result-->>-ConnectionWrapper: returns
    ConnectionWrapper->>-SoqlStatement: fetchAll()
    SoqlStatement->>+\Codelicia\Soql\FetchDataUtility: fetchAll()
    \Codelicia\Soql\FetchDataUtility-->>+\GuzzleHttp\ClientInterface: send()
    Note right of \Codelicia\Soql\FetchDataUtility: Countable goes here?<br> before creating the Payload?
    \Codelicia\Soql\FetchDataUtility->>+\Codelicia\Soql\Payload: new
    \Codelicia\Soql\Payload-->>+SoqlStatement: returns
Loading

Author

codelicia/trineforce 适用场景与选型建议

codelicia/trineforce 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 11.71k 次下载、GitHub Stars 达 5, 最近一次更新时间为 2019 年 09 月 17 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 codelicia/trineforce 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 codelicia/trineforce 我们能提供哪些服务?
定制开发 / 二次开发

基于 codelicia/trineforce 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 11.71k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 5
  • 点击次数: 9
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 5
  • Watchers: 2
  • Forks: 6
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-09-17