-
Notifications
You must be signed in to change notification settings - Fork 58
Tutorial
On this page you can find a few samples of code using this toolkit.
Before you start using this library, you need to install it via Composer and include the generated autoloader into your application.
require_once 'vendor/autoload.php';
The library exposes a public API which includes an IOrganizationService-compatible Client. There are a few options to create a new instance of the client.
ClientFactory
provides a simple way to instantiate a new Client
with all dependencies in place. As Dynamics 365 (online) is currently the only supported type of deployment, ClientFactory
contains only one static method, ClientFactory::createOnlineClient
. For IFD and On-Premises support please refer to Roadmap.
The minimal set of values you need to connect to Dynamics 365 Online is as follows:
- Organization URI, e.g.
https://contoso.crm.dynamics.com
- Application ID - identifies the Azure AD application registration associated with your Dynamics 365 organization
- Application Secret - a password generated in Settings / API Access / Keys section of your Azure AD application registration
Read this article (archive) to understand how to register a new app in Azure Active Directory and associate it with an application user in Dynamics 365.
Once you have all three items, it's time to create a new client:
$client = \AlexaCRM\WebAPI\ClientFactory::createOnlineClient(
'https://contoso.crm.dynamics.com',
'00000000-0000-0000-0000-000000000000',
'Application Secret'
);
ClientFactory::createOnlineClient()
accepts an optional fourth argument. The method expects a map with logger
and cachePool
keys which hold as values PSR-3 compliant logger and PSR-6 compliant cache adapter correspondingly.
The library follows the lazy initialization pattern and doesn't actually validate the connection at client initialization time. To see how to handle errors, see below.
Sometimes you may want to create all necessary objects yourself. One case when this is useful is when you need to specify extra options in the client settings.
The first step is to create a Settings
object. For online deployments, use OnlineSettings
.
$settings = new \AlexaCRM\WebAPI\OData\OnlineSettings();
$settings->instanceURI = 'https://contoso.crm.dynamics.com';
$settings->applicationID = '00000000-0000-0000-0000-000000000000';
$settings->applicationSecret = 'Application Secret';
You can optionally supply a PSR-3 compliant logger.
$settings->setLogger( $logger );
You can optionally supply a PSR-6 compliant cache adapter.
$settings->cachePool = $cacheAdapter;
By default, the HTTP client used by the library verifies SSL certificates against the local CA certificate bundle. If it is broken, like as what happens often on development environments in Windows and OS X, you can either supply a valid CA bundle or disable verification.
$settings->caBundle = false;
$settings->caBundle = '/path/to/ca-bundle.crt';
The default Web API version which the plugin connects to is 8.2
. It is the minimal tested Web API version as well. (Although not tested, it might very well work with earlier versions, perhaps with some limitations.)
If you need to change the API version, it is also configured in the Settings object:
$settings->apiVersion = '9.0';
The authentication process kicks in when the request is being made. For Online deployments, that means receiving an access token from Azure AD and putting it into the Authorization
header of the request.
$middleware = new \AlexaCRM\WebAPI\OData\OnlineAuthMiddleware( $settings );
Under the hood works a helper object that creates OData-compliant requests to the service endpoint. It consumes the Settings and AuthMiddlewareInterface objects.
$odataClient = new \AlexaCRM\WebAPI\OData\Client( $settings, $middleware );
The Web API Client class is compatible with IOrganizationService from the CRM SDK. To create one, you need to provide the OData client created earlier.
$client = new \AlexaCRM\WebAPI\Client( $odataClient );
After this step, the client is ready to make requests to Dynamics 365 Web API.
To create a new record in CRM, make an Entity object and pass it to the Client::Create()
method.
$contact = new \AlexaCRM\Xrm\Entity( 'contact' );
$contact['firstname'] = 'Nancy';
$contact['lastname'] = 'Anderson';
$contact['emailaddress1'] = '[email protected]';
$contactId = $client->Create( $contact );
To retrieve a record, you need to specify its entity name, entity ID and a column set. Although you can retrieve all columns, it is strongly advised to select only necessary attributes for performance reasons, both at CRM and client side.
$retrievedContact = $client->Retrieve( 'contact', $contactId, new \AlexaCRM\Xrm\ColumnSet( [ 'fullname', 'emailaddress1' ] );
To retrieve all columns:
new \AlexaCRM\Xrm\ColumnSet( true )
Client::RetrieveMultiple()
is used to retrieve multiple records from Dynamics 365. It supports FetchExpression
and QueryByAttribute
. QueryExpression
is not currently supported. For advanced OData queries in Web API see below.
Client::RetrieveMultiple()
returns an EntityCollection
.
Querying data with FetchXML is pretty straightforward. Use FetchExpression
and supply a stringt with a FetchXML query.
$fetchXML = <<<FETCHXML
<fetch mapping="logical">
<entity name="contact">
<attribute name="accountid" />
<attribute name="fullname" />
<attribute name="emailaddress1" />
</entity>
</fetch>
FETCHXML;
$fetchExpression = new \AlexaCRM\Xrm\Query\FetchExpression( $fetchXML );
$collection = $client->RetrieveMultiple( $fetchExpression );
$query = new \AlexaCRM\Xrm\Query\QueryByAttribute( 'contact' );
$query->AddAttributeValue( 'lastname', 'Example' );
$query->AddOrder( 'firstname', \AlexaCRM\Xrm\Query\OrderType::Descending() );
$query->ColumnSet = new \AlexaCRM\Xrm\ColumnSet( [ 'fullname', 'emailaddress1' ] );
$collection = $client->RetrieveMultiple( $query );
$record = new \AlexaCRM\Xrm\Entity( 'contact', '00000000-0000-0000-0000-000000000000' );
$record['emailaddress1'] = '[email protected]';
$client->Update( $record );
$client->Delete( 'contact', '00000000-0000-0000-0000-000000000000' );
You can associate/disassociate records in two different ways: in a separate request (Associate
and Disassociate
) and during Create
/Update
.
The example given below will associate the account record with three contact records by setting contact[parentcustomerid]
lookup (Customer) attribute to the corresponding account lookup value.
$client->Associate(
'account',
'00000000-0000-0000-0000-000000000009',
new \AlexaCRM\Xrm\Relationship( 'contact_customer_accounts' ),
[
new \AlexaCRM\Xrm\EntityReference( 'contact', '00000000-0000-0000-0000-000000000001' ),
new \AlexaCRM\Xrm\EntityReference( 'contact', '00000000-0000-0000-0000-000000000002' ),
new \AlexaCRM\Xrm\EntityReference( 'contact', '00000000-0000-0000-0000-000000000003' ),
]
);
Client::Associate()
and Client::Disassociate()
have the same signature.
Dynamics 365 Web API allows you making associations between records during create/update request. When you prepare such a request, you need to know the corresponding navigation property for the given entity. In addition, lookup values with multiple targets like Customer lookups, require specifying different navigation properties for different entities (accounts and contacts for the Customer type).
This library does the heavy-lifting for you:
$contact = \AlexaCRM\Xrm\Entity( 'contact', '00000000-0000-0000-0000-000000000001' );
$contact['parentcustomerid'] = new \AlexaCRM\Xrm\EntityReference( 'account', '00000000-0000-0000-0000-000000000009' );
// or
$contact['parentcustomerid'] = new \AlexaCRM\Xrm\EntityReference( 'contact', '00000000-0000-0000-0000-000000000002' );
$client->Update( $contact );
At this point, calling Client::Execute()
will throw an exception saying "Execute request not implemented". To execute actions and functions, you will need to use the underlying OData helper client which is accessed via Client::getClient()
method.
Actions can be invoked via OData\Client::executeAction()
method. Only the first argument, $actionName
, is required. Specify action parameters in the second argument. If the action is bound, third and fourth optional arguments specify the collection name and record ID.
The return value is given without the OData context annotation.
Functions can be invoked via OData::executeFunction()
method. Only the first argument, $functionName
, is required. Specify function parameters in the second argument. If the function is bound, third and fourth optional arguments specify the collection name and record ID.
The return value is given without the OData context annotation.
If you want to construct an advanced OData query, you will need to use the HTTP client and query the data directly. The HTTP client is available via OData\Client::getHttpClient()
, and OData\Client
is available via Client::getClient()
.
The data retrieved is not unmarshalled into Entity objects and for the time being you're on your own in this regard.
Have fun!