Salesforce REST API integration in PHP
In recent months, more and more customers are asking us about the possibility of outsourcing a project to XSolve, in which particular emphasis would be placed on integration with the CRM Sa system used by them and extremely popular in the worldlesforce. Of course, we are not afraid of challenges and such integration is not a big problem for us, but we noticed that the existing solutions in PHP do not meet our standards and are written in technologies that can be safely called obsolete.
Official SDK version supplied by Salesforce itself, it is written in PHP 5, whose active support was closed at the end of last year. In addition, we found several problems in this library:
does not use autoloading (PSR-4),
not compliant with PSR-1/2,
it is used to communicate with the Soap API, there is no REST client, which we think would be better in terms of, among other things, performance for the basic scenarios that we wanted to cover (mainly CRUD operations, basic data synchronization),
it is not developed since March 2015, which means that it supports API up to version 27, with the current 38.
Of course, we did not finish our search on the official SDK, but we also looked at ready-made solutions created by the open source community. Most are no longer developed or maintained. Exception he’s here. eventfarm/restforcephp, which during the execution of the research was not as developed as at the time when we write this article.
The solution to this problem could be to integrate with the REST API each time creating dedicated a project-specific solution. However, this would not be efficient due to the need to duplicate the code and the time it takes to adapt the changes to newer versions of the Salesforce API.
That is why we decided to start work on the library, which can now be found at https://github.com/xsolve-pl/salesforce-client.
In our intention, the created API client should be as light as possible, with as few external dependencies as possible, in order to allow relatively easy installation and avoid, as far as possible, conflicts with other dependencies of the project to which the SDK would be added.
As for the PHP version, the natural choice was the currently supported version 7. We also considered adapting the project to Php 7.1. However, we gave up because this version of the language was only a few days old when we started working on the library.
Looking at dependency lists in the project, you can see that for the purpose of serializing data to a form that can be transferred between the application and the REST API, we use JMS Serializer ( http://jmsyst.com/libs/serializer ). It is a very well – known, stable and widely used by us in many projects library, whose task is to convert your own objects with the help of the appropriate configuration (mapping) to a given text format (supported by default: json, XML and YAML) and vice versa-from the text format to the form of objects.
Functionality known from other programming languages enumeration it is provided by a small library eloquent / enumeration. It makes it possible to use typehints for enumerators, which avoids the need for each time to check the correctness of the value passed as an enumerator.
The Salesforce Client does not have its own HTTP client implementation to ensure the flexibility of the solution operates on interfaces from the library Httplug. There are many things for her ready adapters, and writing your own is very simple. For example, you can use the overlay on the popular guzzle – php-http / guzzle6-adapter.
We used the Salesforce API version of authentication as the basic version flow using login and password, however, if necessary, you can easily add another implementation. In addition, to avoid asking the server each time for a new token, it is necessary to store it somewhere. In our library you can find ready-made solutions for storing access tokens: in Redis using blablacar / redis-client is the simplest storage implementation that uses caching and stores the token data in an object. However, nothing prevents you from creating your own implementation of tokenstorageinterface and saving it in another way – for example, in a relational database.
We started the library project by analyzing the most common use cases in order to cover as many of the most popular API queries as possible in the functional scope. Together, we came to the conclusion that such a common problem is the need to synchronize objects that occur in our applications with their counterparts in Salesforce CRM. The next step was to create a list of objects from Salesforce that are most often used in integration and elements that, in our opinion, could significantly speed up the work with both the library and the API itself.
In the first iteration, a kind of project basis was created – a simple REST client that allows you to authenticate in the Salesforce API, save an access token and send any query to the endpoint and return the result.
In the second sprint, we focused on maximizing the simplicity of using the API by structuring popular queries and creating abstractions from the most popular objects found in Salesforce. The result was:
uprising QueryBuildera which makes it easy to create queries SOQL;
introducing a unified repository interface for CRUD operations;
add support for previously selected standard objects (SObjects): Account, Case, Contact, Contract, Lead, Opportunity, Order, Pricebook2, Pricebookentry, Product2, Solution.
The library covers CRUD operations on models, but we were not able to create mappings for every object that is located in Salesforce and is available in the API – there are simply too many of them. If you haven’t found the model you need in our library, documentation you will find information how you can create it. We also encourage you to share its implementation by opening pull request to the repository 😉
Of course, you can also use the library without mapping the object, more on this in documentation.
Often, the actions performed by users in the application should also be reflected in Salesforce, so that you can better track them and plan future actions. For example, when we run a chain of stores:
The customer will place an order in one of them and we would like to add information with all the details of the order.
Someone will create an account in our store and we would like to add them as a potential customer.
Another company has placed a recurring order and we want to have information in the CRM about when deliveries should be completed.
Find out if the email address you provided is already in our salesforce contacts.
Of course, the examples can be multiplied and they depend on the project, but all the above actions are possible to perform using our library, moreover, you do not need to know how to properly prepare the query, or what fields the object has. To not quote documentation, which can be found on GitHub, below is an example for Point 2 using SObjectRepository:
We can just as easily carry out the task from point 4. They serve for this QueryBuilder and QueryExecutor:
In the near future, we plan to add more models representing sobjects, but since the most commonly used PHP framework is symfony3, it seems an obvious step to prepare a bundle and integrate it with the dependency injection container to further facilitate the use of the library. In addition to the DI configuration, the bundle can also integrate with Doctrine 2 events. This would allow easy synchronization of data between the application and Salesforce.
We encourage you to review the project, report bugs, ideas and corrections. We look forward to your valuable feedback and we hope that Salesforce client will prove useful to you!
Paweł Krynicki (Senior Software Developer at XSolve)
Adrian Waler (Junior Software Developer at XSolve)