Salesforce REST PHP Integration — Open-source solution by XSolve

XSolve
XSolve Blog

--

In the recent months, we had an influx of clients asking us if it is possible to outsource a project to us putting a special emphasis on integration with the globally recognized Salesforce CRM system used by them. Obviously, we’re not afraid of challenges and this kind of integration is not a problem for us; however, we’ve noticed that the existing PHP solutions do not meet our standards as they have been written in technologies which have simply become obsolete.

The official SDK version provided by Salesforce itself is written in PHP 5, whose active support ended at the end of 2016. Besides, we found several problems there:

  • it doesn’t make use of the benefits of autoloading (PSR-4)
  • it doesn’t comply with PSR-1/2
  • it serves to communicate with Soap API, there’s no REST client, which, in our opinion, would be much better when it comes to, for instance, efficiency for basic scenarios we wanted to cover (mainly CRUD operations, basic data sync)
  • it has not been developed since March 2015, which means that it supports API maximally until version 27, and now we’re at 38.

Of course, we did not limit our search to the official SDK. We also had a look at ready-made solutions created by the open source community. Most of them are not developed or maintained anymore. There is an exception, though: eventfarm / restforcephp, which was not as developed during our research as it is now that we’re writing this article.

A solution to this problem could be integrating with REST API anytime we create a dedicated solution adapted to a particular project. Still, that would not be very efficient as we would have to duplicate the code and need more time to adjust the changes to the new versions of API Salesforce.

That’s why we’ve decided to start working on a new library — you can find it now at https://github.com/xsolve-pl/salesforce-client.

Technologies

Our idea was to create an API client which would be as light as possible, with as few external dependencies as possible. We wanted to ensure relatively easy installation and avoid, if possible, conflicts with other dependencies of the project which would be provided with the SDK.

As far as the PHP language version is concerned, we naturally chose the currently supported version 7. We also considered adjusting the project to PHP 7.1, but, as this version was in fact released a couple of days before, we decided to wait until most target users (developers) start using this update in their projects.

If you take a quick look at the list of dependencies of the project, you will see that we employ JMS Serializer (http://jmsyst.com/libs/serializer) to serialize data into a format that can be transferred between the app and REST API. It’s a well-known, stable library, widely used by us in many projects; its task is to transform its own objects by means of an appropriate configuration (mapping) into a given text format (supported by default by JSON, XML, and YAML) and the other way round — from a text format into objects.

The enumeration functionality, known from other programming languages, is provided by a small library: eloquent/enumeration. Thanks to it, you can use type hinting for enumerators, and so you don’t need to check the accuracy of the value entered through enumeration all the time.

Salesforce Client has one default HTTP Client implementation, basing on the guzzlehttp / guzzle library; however, to enhance the flexibility of the solution, it’s not included in the requirement list. The Client is based on PSR-7, which allows you to use any kind of HTTP client implementation, as long as it fulfils the interface defined in this standard.

The basic way of authenticating in Salesforce API is username and password flow, but you can easily add another implementation if necessary. Additionally, to avoid the server calling each time for a new token, you need a place to store it. In our library, there is a ready solution for storing the access token: in Redis, using blablacar/ redis-client or the simplest storage implementation using the cache and storing the token’s data in the object’s property. However, you are free to create your own TokenStorageInterface implementation and save it in a different way — for example, in the relational database.

Functional scope

We started our library project by analyzing the most frequent usage cases so that our functional scope could cover as many most popular API queries as possible. Together, we came to the conclusion that the most frequent problem is the need to synchronize objects in our applications with their equivalents in Salesforce CRM. The next step was to create a list of Salesforce objects which are most often used for integration and the elements which, in our opinion, could considerably accelerate the work both with the library and API as such.

The first iteration brought a basis for the project — simple REST client allowing you to authorize yourself in API Salesforce, save the access token, send a query to the endpoint, and get the result.

In the second sprint, we concentrated on the maximum simplification of using API by means of structuring popular queries and creating abstractions for the most popular objects in Salesforce. This resulted in:

  • creating QueryBuilder, which enables you to easily build SOQL queries;
  • introducing a uniform interface of the repository for CRUD operations;
  • adding the option of supporting previously selected standard objects (SObjects): Account, Case, Contact, Contract, Lead, Opportunity, Order, Pricebook2, PricebookEntry, Product2, Solution.

The library covers CRUD operations for models, but we were not able to create a mapping for every object present in Salesforce and available in API — there are simply too many. If you haven’t found a model you need in our library, you will find information how to create it in the documentation. Feel free to share its implementation by creating a pull request to the repository.

Clearly, you can also use the library without object mapping. Read more about this in the documentation.

Examples of use

The users’ action in the application should also be reflected in Salesforce so that we could follow them better and make plans for the future. For example, if you have a chain of stores:

  1. A customer has placed an order in one of them and you want to add all the order details.
  2. Someone has opened an account in your store and you want to add them as a potential customer.
  3. Another company has made a recurring order and you want to have the information on when to finish the deliveries in CRM.
  4. You want to find out whether a given email address has already been added to the contact list in Salesforce.

Of course, there could be even more examples, as they depend on the project. However, all the above-mentioned actions are possible in our library; what’s more, you don’t need to know how to prepare an SOQL query or what field an object has. In order not to quote the documentation, which can be found at GitHub, we’re showing an example for the situation number 2, using SObjectRepository:

You can also easily realize task 4. To do that, you use QueryBuilder and QueryExecutor. Here’s an example:

Plans for the future

In the nearest future, we’re planning to add more models representing SObjects. Moreover, as the PHP framework which we use most frequently is Symfony3, a natural step forward will be to prepare a bundle and integrate it with Dependency Injection container to make using of the library even easier. Besides the DI configuration into a bundle, we might also integrate it with Doctrine 2 events. It would allow an easy data synchronization between the app and Salesforce.

Feel free to contribute to the project, report errors, share ideas, and corrections. We’re waiting for your valuable feedback and we do hope that Salesforce Client will prove useful for you!

Originally published at xsolve.software on May 12, 2017.

--

--

XSolve
XSolve Blog

Agile Software House focused on PHP/Symfony, Java, JavaScript and Mobile.