PHPackages                             justbetter/laravel-dynamics-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. justbetter/laravel-dynamics-client

ActivePackage[HTTP &amp; Networking](/categories/http)

justbetter/laravel-dynamics-client
==================================

A client to connect with Microsoft Dynamics

1.10.0(3mo ago)4328.2k—6.9%11[1 PRs](https://github.com/justbetter/laravel-dynamics-client/pulls)MITPHPPHP ^8.3CI passing

Since Jul 27Pushed 3mo ago4 watchersCompare

[ Source](https://github.com/justbetter/laravel-dynamics-client)[ Packagist](https://packagist.org/packages/justbetter/laravel-dynamics-client)[ Docs](https://github.com/justbetter/laravel-dynamics-client)[ RSS](/packages/justbetter-laravel-dynamics-client/feed)WikiDiscussions main Synced 2d ago

READMEChangelog (10)Dependencies (16)Versions (27)Used By (0)

[ ![Package banner](./art/banner.svg)](https://github.com/justbetter/laravel-dynamics-client "JustBetter")Laravel Dynamics Client
=======================

[](#laravel-dynamics-client)

This package will connect you to your Microsoft Dynamics web services via OData. Custom web services can easily be implemented and mapped to your liking. It uses the [HTTP client](https://laravel.com/docs/master/http-client) of Laravel which means that you can easily fake requests when writing tests.

The way we interact with OData has been inspired by Laravel's Query Builder.

```
$customer = Customer::query()->findOrFail('1000');

$customer->update([
    'Name' => 'John Doe',
]);

$customers = Customer::query()
    ->where('City', '=', 'Alkmaar')
    ->lazy();

$items = Item::query()
    ->whereIn('No', ['1000', '2000'])
    ->get();

$customer = Customer::new()->create([
    'Name' => 'Jane Doe',
]);
```

Installation
------------

[](#installation)

Install the composer package.

```
composer require justbetter/laravel-dynamics-client
```

Setup
-----

[](#setup)

Publish the configuration of the package.

```
php artisan vendor:publish --provider="JustBetter\DynamicsClient\ServiceProvider" --tag=config
```

Configuration
-------------

[](#configuration)

Add your Dynamics credentials in the `.env`:

```
DYNAMICS_BASE_URL=https://127.0.0.1:7048/DYNAMICS
DYNAMICS_VERSION=ODataV4
DYNAMICS_COMPANY=
DYNAMICS_USERNAME=
DYNAMICS_PASSWORD=
DYNAMICS_PAGE_SIZE=1000

```

Be sure the `DYNAMICS_PAGE_SIZE` is set equally to the `Max Page Size` under `OData Services` in the configuration of Dynamics. This is crucial for the functionalities of the `lazy` method of the `QueryBuilder`.

### Authentication

[](#authentication)

> **Note:** Be sure that Dynamics has been properly configured for OData.

This package uses NTLM authentication by default. If you are required to use basic auth or OAuth you can change this in your `.env`.

```
DYNAMICS_AUTH=basic

```

#### OAuth

[](#oauth)

To setup OAuth add the following to your `.env`

```
DYNAMICS_AUTH=oauth
DYNAMICS_OAUTH_CLIENT_ID=
DYNAMICS_OAUTH_CLIENT_SECRET=
DYNAMICS_OAUTH_REDIRECT_URI=
DYNAMICS_OAUTH_SCOPE=
```

When using D365 cloud with [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow) your redirect uri will be: `https://login.microsoftonline.com//oauth2/v2.0/token`and your base url should be `https://api.businesscentral.dynamics.com/v2.0//`.

### Connections

[](#connections)

Multiple connections are supported. You can easily update your `dynamics` configuration to add as many connections as you wish.

```
// Will use the default connection.
Customer::query()->first();

// Uses the supplied connection.
Customer::query('other_connection')->first();
```

By default, the client will use the `company` field to select the Dynamics company. If you wish to use the company's UUID you can simply add an `uuid` field:

```
        'Company' => [
            'base_url' => env('DYNAMICS_BASE_URL'),
            'version' => env('DYNAMICS_VERSION', 'ODataV4'),
            'company' => 'Company Name',
            'uuid' => 'Company UUID', // The UUID will be prioritized over the company name
```

Adding web services
-------------------

[](#adding-web-services)

Adding a web service to your configuration is easily done. Start by creating your own resource class to map te data to.

```
use JustBetter\DynamicsClient\OData\BaseResource;

class Customer extends BaseResource
{
    //
}
```

### Primary Key

[](#primary-key)

By default, the primary key of a resource will default to `No` as a string. You can override this by supplying the variable `$primaryKey`.

```
public array $primaryKey = [
    'Code',
];
```

### Data Casting

[](#data-casting)

Fields in resources will by default be treated as a string. For some fields, like a line number, this should be casted to an integer.

```
public array $casts = [
    'Line_No' => 'int',
];
```

### Registering Your Resource

[](#registering-your-resource)

Lastly, you should register your resource in your configuration file to let the package know where the web service is located. This should correspond to the service name configured in Dynamics.

If your resource class name is the same as the service name, no manual configuration is needed.

> **Note:** Make sure your web service is published.

```
return [

    /* Resource Configuration */
    'resources' => [
        Customer::class => 'CustomerCard',
    ],

];
```

Query Builder
-------------

[](#query-builder)

Querying data is easily done using the QueryBuilder.

Using the `get` method will only return the first result page. If you wish to efficiently loop through all records, use `lazy` instead.

```
$customers = Customer::query()
    ->where('City', '=', 'Alkmaar')
    ->lazy()
    ->each(function(Customer $customer): void {
        //
    });
```

See the `QueryBuilder` class for all available methods.

Relations
---------

[](#relations)

Any relations published on a page can be accessed as well using the resource.

```
$salesOrder = SalesOrder::query()->first();

// Get the lines via the "relation" method.
$salesLines = $salesOrder->relation('Relation_Name', SalesLine::class)->get();

// Or use the "lines" helper on the SalesOrder.
$salesLines = $salesOrder->lines('Relation_Name')->get();
```

Note that the `relation` method itself returns an instance of a query builder. This means that you can add additional where-clauses like you would be able to on a regular resource.

Creating records
----------------

[](#creating-records)

Create a new record.

```
Customer::new()->create([
    'Name' => 'John Doe'
])
```

Updating records
----------------

[](#updating-records)

Update an existing record.

```
$customer = Customer::query()->find('1000');
$customer->update([
    'Name' => 'John Doe',
]);
```

Deleting records
----------------

[](#deleting-records)

Delete a record.

```
$customer = Customer::query()->find('1000');
$customer->delete();
```

Debugging
---------

[](#debugging)

If you wish to review your query before you sent it, you may want to use the `dd` function on the builder.

```
Customer::query()
    ->where('City', '=', 'Alkmaar')
    ->whereIn('No', ['1000', '2000'])
    ->dd();

// Customer?$filter=City eq 'Alkmaar' and (No eq '1000' or No eq '2000')
```

Commands
--------

[](#commands)

You can run the following command to check if you can successfully connect to Dynamics.

```
php artisan dynamics:connect {connection?}
```

Extending
---------

[](#extending)

If needed, it is possible to extend the provided `ClientFactory` class by creating your own. You **must** implement the `ClientFactoryContract` interface and its methods.

```
use JustBetter\DynamicsClient\Exceptions\DynamicsException;
use JustBetter\DynamicsClient\Contracts\ClientFactoryContract;

class MyCustomClientFactory implements ClientFactoryContract
{
    public function __construct(public string $connection)
    {
        $config = config('dynamics.connections.'.$connection);

        if (! $config) {
            throw new DynamicsException(
                __('Connection ":connection" does not exist', ['connection' => $connection])
            );
        }

        $this
            ->header('Authorization', 'Bearer ' . $config['access_token'])
            ->header('Accept', 'application/json')
            ->header('Content-Type', 'application/json');
    }

    ...
}
```

You will then need to bind your custom factory as the implementation of the contract, in any of your `ServiceProvider` register method :

```
