Salesforce/Force.com REST API client for Laravel. While it acts as more of a wrapper of the API methods, it should provide you with all the flexibility you will need to interact with the REST service.
Currently the only support is for Laravel 4, 5 and Lumen.
Interested in Eloquent Salesforce Models? Check out @roblesterjr04's EloquentSalesForce project that utilizes Forrest as it's API layer.
If you are upgrading to Version 2.0, be sure to re-publish your config file.
Forrest can be installed through composer. Open your composer.json
file and add the following to the require
key:
"omniphx/forrest": "2.*"
Next run composer update
from the command line to install the package.
Add the service provider and alias to your config/app.php
file:
Omniphx\Forrest\Providers\Laravel\ForrestServiceProvider::class
'Forrest' => Omniphx\Forrest\Providers\Laravel\Facades\Forrest::class
For Laravel 4, add
Omniphx\Forrest\Providers\Laravel4\ForrestServiceProvider
inapp/config/app.php
. Alias will remain the same.
class_alias('Omniphx\Forrest\Providers\Laravel\Facades\Forrest', 'Forrest');
$app->register(Omniphx\Forrest\Providers\Lumen\ForrestServiceProvider::class);
$app->configure('forrest');
$app->withFacades();
Then you'll utilize the Lumen service provider by registering it in the bootstrap/app.php
file.
You will need a configuration file to add your credentials. Publish a config file using the artisan
command:
php artisan vendor:publish
This will publish a config/forrest.php
file that can switch between authentication types as well as other settings.
After adding the config file, update your .env
to include the following values (details for getting a consumer key and secret are outlined below):
CONSUMER_KEY=123455
CONSUMER_SECRET=ABCDEF
CALLBACK_URI=https://test.app/callback
LOGIN_URL=https://login.salesforce.com
[email protected]
PASSWORD=password123
For Lumen, you should copy the config file from
src/config/config.php
and add it to aforrest.php
configuration file under a config directory in the root of your application.
For Laravel 4, run
php artisan config:publish omniphx/forrest
which createapp/config/omniphx/forrest/config.php
- Log into to your Salesforce org
- Click on Setup in the upper right-hand menu
- Under Build click
Create > Apps
- Scroll to the bottom and click
New
under Connected Apps. - Enter the following details for the remote application:
- Connected App Name
- API Name
- Contact Email
- Enable OAuth Settings under the API dropdown
- Callback URL
- Select access scope (If you need a refresh token, specify it here)
- Click
Save
After saving, you will now be given a Consumer Key and Consumer Secret. Update your config file with values for consumerKey
, consumerSecret
, loginURL
and callbackURI
.
Creating authentication routes
Route::get('/authenticate', function()
{
return Forrest::authenticate();
});
Route::get('/callback', function()
{
Forrest::callback();
return Redirect::to('/');
});
With the Username Password flow, you can directly authenticate with the Forrest::authenticate()
method.
To use this authentication you must add your username, and password to the config file. Security token might need to be ammended to your password unless your IP address is whitelisted.
Route::get('/authenticate', function()
{
Forrest::authenticate();
return Redirect::to('/');
});
Sometimes users will need to connect to a sandbox or custom url. To do this, simply pass the url as an argument for the authenticatation method:
Route::get('/authenticate', function()
{
$loginURL = 'https://test.salesforce.com';
return Forrest::authenticate($loginURL);
});
Note: You can specify a default login URL in your config file.
After authentication, your app will store an encrypted authentication token which can be used to make API requests.
Forrest::query('SELECT Id FROM Account');
Sample result:
{
"totalSize": 2,
"done": true,
"records": [
{
"attributes": {
"type": "Account",
"url": "\/services\/data\/v30.0\/sobjects\/Account\/001i000000xxx"
},
"Id": "001i000000xxx"
},
{
"attributes": {
"type": "Account",
"url": "\/services\/data\/v30.0\/sobjects\/Account\/001i000000xxx"
},
"Id": "001i000000xxx"
}
]
}
If you are querying more than 2000 records, you response will include:
{
"nextRecordsUrl" : "/services/data/v20.0/query/01gD0000002HU6KIAW-2000"
}
Simply, call Forrest::next($nextRecordsUrl)
to return the next 2000 records.
Records can be created using the following format.
$body = ;
Forrest::sobjects('Account',[
'method' => 'post',
'body' => ['Name' => 'Dunder Mifflin']
]);
Update a record with the PUT method.
Forrest::sobjects('Account/001i000000xxx',[
'method' => 'put',
'body' => [
'Name' => 'Acme',
'Phone' => '555-555-5555'
]
]);
Update a record with the PATCH method and if the external Id doesn't exist, it will insert a new record.
$externalId = 'XYZ1234';
Forrest::sobjects('Account/External_Id__c/' + $externalId, [
'method' => 'patch',
'body' => [
'Name' => 'Acme',
'Phone' => '555-555-5555'
]
]);
Delete a record with the DELETE method.
Forrest::sobjects('Account/001i000000xxx', ['method' => 'delete']);
Change the request/response format to XML with the format
key or make it default in your config file.
Forrest::sobjects('Account',['format'=>'xml']);
With the exception of the search
and query
resources, all resources are requested dynamically using method overloading.
First, determine which resources you have access to by calling:
Forrest::resources();
Result:
Array
(
[sobjects] => /services/data/v30.0/sobjects
[connect] => /services/data/v30.0/connect
[query] => /services/data/v30.0/query
[theme] => /services/data/v30.0/theme
[queryAll] => /services/data/v30.0/queryAll
[tooling] => /services/data/v30.0/tooling
[chatter] => /services/data/v30.0/chatter
[analytics] => /services/data/v30.0/analytics
[recent] => /services/data/v30.0/recent
[process] => /services/data/v30.0/process
[identity] => https://login.salesforce.com/id/00Di0000000XXXXXX/005i0000000aaaaAAA
[flexiPage] => /services/data/v30.0/flexiPage
[search] => /services/data/v30.0/search
[quickActions] => /services/data/v30.0/quickActions
[appMenu] => /services/data/v30.0/appMenu
)
Next, call resources by referring to the specified key. For instance:
Forrest::theme();
or
Forrest::appMenu();
Resource urls can be extended by passing additional parameters into the first argument:
Forrest::sobjects('Account/describe/approvalLayouts/');
You can also add optional parameters to requests:
Forrest::theme(['format'=>'xml']);
If a refresh token is set, the server can refresh the access token on the user's behalf. Refresh tokens are only for the Web Server flow.
Forrest::refresh();
If you need a refresh token, be sure to specify this under
access scope
in your Connected App. You can also specify this in your configuration file by adding'scope' => 'full refresh_token'
. Setting scope access in the config file is optional, the default scope access is determined by your Salesforce org.
This will revoke the authorization token. The session will continue to store a token, but it will become invalid.
Forrest::revoke();
Returns all currently supported versions. Includes the verison, label and link to each version's root:
Forrest::versions();
Returns list of available resources based on the logged in user's permission and API version.
Forrest::resources();
Returns information about the logged-in user.
Forrest::identity();
For a complete listing of API resources, refer to the Force.com REST API Developer's Guide
If you create a custom API using Apex, you can use the custom()
method for consuming them.
Forrest::custom('/myEndpoint');
Additional options and parameters can be passed in like this:
Forrest::custom('/myEndpoint', [
'method' => 'post',
'body' => ['foo' => 'bar'],
'parameters' => ['flim' => 'flam']]);
Read Creating REST APIs using Apex REST for more information.
If needed, you can make raw requests to an endpoint of your choice.
Forrest::get('/services/data/v20.0/endpoint');
Forrest::head('/services/data/v20.0/endpoint');
Forrest::post('/services/data/v20.0/endpoint', ['my'=>'param']);
Forrest::put('/services/data/v20.0/endpoint', ['my'=>'param']);
Forrest::patch('/services/data/v20.0/endpoint', ['my'=>'param']);
Forrest::delete('/services/data/v20.0/endpoint');
By default, this package will return the body of a response as either a deserialized JSON object or a SimpleXMLElement object.
There might be times, when you would rather handle this differently. To do this, simply use any format other than 'json' or 'xml' and the code will return a Guzzle response object.
$response = Forrest::sobjects($resource, ['format'=> 'none']);
$content = (string) $response->getBody(); // Guzzle response
This package makes use of Guzzle's event listers
Event::listen('forrest.response', function($request, $response) {
dd((string) $response);
});
For more information about Guzzle responses and event listeners, refer to their documentation.