# msgraph-sdk-php: the Microsoft Graph client for PHP

> The Microsoft Graph SDK for PHP is a service client that covers the Graph API with request builders and models, and it splits authentication from calling in a way that is easy to reason about. A token request context carries the credentials, the SDK turns that into a cached and refreshed access token, and the client is built on top of it. Calls are asynchronous by default and return a promise, which is the one place PHP developers have to adjust.

**microsoftgraph/msgraph-sdk-php** — Microsoft Graph Library for PHP.

- Repository: https://github.com/microsoftgraph/msgraph-sdk-php
- Stars: 667 · Forks: 149
- Language: PHP
- License: NOASSERTION
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/microsoftgraph-msgraph-sdk-php

## A Composer dependency and a PHP version

The SDK is installed the ordinary way, as a Composer requirement in your manifest.

```json
{
    "require": {
        // x-release-please-start-version
        "microsoft/microsoft-graph": "^3.8.0"
        // x-release-please-end
    }
}
```

The comments around the version line are a detail with a purpose. They are markers for a release tool, which is how the version constraint in every consuming project gets updated when a new major version is released, and the same mechanism is visible in the repository, which carries a release manifest and a release configuration for it.

The prerequisite is PHP 8.2 or later, with a link to the list of supported PHP versions.

The first step after installing is not code, it is registering the application. You register the application to use the Graph API through the Azure Active Directory portal in the tenant's directory, either to support work or school users for your tenant, or to support multiple tenants. That choice matters more than it looks, because a single tenant registration and a multi tenant one have different consent and different token shapes, and picking the wrong one is the kind of decision that is expensive to change later.

The project is published on Packagist as a Microsoft package, the readme carries the build status and the download counters, and the copyright notice is Microsoft's with the MIT licence, along with the Microsoft Open Source Code of Conduct.

## The token request context and the three flows

The central abstraction is the token request context, which contains the credentials used to authenticate requests. The SDK supports three, one for each of the OAuth flows that matter in practice: the client credentials flow, the authorization code flow, and the on-behalf-of flow, with support for both secret based and certificate based client authentication.

Under the hood, that context is passed to an authentication provider, and the provider fetches, caches, and refreshes the access tokens, so that every request is authenticated against the Microsoft identity platform without the caller handling a token.

The two contexts you will use most are small.

```php
<?php
use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext;
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;

$tokenRequestContext = new ClientCredentialContext(
    'tenantId',
    'clientId',
    'clientSecret'
);
```

That is the flow for getting access without a user, and the example is the application acting as itself.

```php
<?php
use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;

$tokenRequestContext = new AuthorizationCodeContext(
    'tenantId',
    'clientId',
    'clientSecret',
    'authCode',
    'redirectUri'
);
```

That is the flow for getting access on behalf of a user, and the readme is explicit about the part the application has to do itself: it must handle redirecting the user to the Microsoft identity login page to obtain the authorization code that is then passed into the context. The SDK does not own the browser round trip.

One detail is easy to miss and is worth stating plainly. The namespace of the authentication classes is the Kiota one, not a Graph one, because the authentication layer is shared across the Kiota generated SDKs rather than being specific to Graph. The Graph specific part is the provider class, which is imported from the Graph namespace in both examples.

## The service client and its default scopes

Once you have a context, the service client is a single constructor call, and the second argument is where the interesting default lives.

```php
use Microsoft\Graph\GraphServiceClient;

// Defaults to using https://graph.microsoft.com/.default scopes
$graphServiceClient = new GraphServiceClient($tokenRequestContext);

// With specific scopes
$scopes = ['User.Read', 'Mail.ReadWrite'];
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
```

The default is the well known scopes form for the Graph endpoint, which asks for whatever the application registration already grants. The alternative is an explicit list of delegated scopes, and the two examples make the difference clear: the client credentials flow does not have a user, so its permissions come from the application registration, while the authorization code flow can ask for delegated scopes per call.

There is also a path for the case where your application already holds a token, or where you want the token the SDK fetched, which the readme handles in the section on access token management, along with the guidance for keeping a user signed in across several requests in a session. That last point is the one PHP developers get wrong most often, because a PHP process is usually a single request, so a token cached in memory is a token that has to be fetched again on the next request unless something outside the process keeps it.

The documentation points at a separate page for that, and at a page with more examples for the client configuration, both in the docs directory of the repository.

## Promises, and the wait that PHP needs

There is one behaviour in this SDK that surprises people who arrive from the other Microsoft Graph libraries, and the readme calls it out twice.

The SDK is designed to make asynchronous requests by default. The operations, the get and the post and the rest, return a promise, and to get the result you call wait on it afterwards.

```php
$user = $graphServiceClient->users()->byUserId('[userPrincipalName]')->get()->wait();
echo "Hello, I am {$user->getGivenName()}";
```

So the shape of a call is: build the request with the request builders, invoke the operation, and wait for the promise. The last part is the part that is specific to this SDK, because PHP has no built-in await, and the underlying promise implementation is a promise library for PHP rather than a language feature.

The error handling is the other half of the pattern, and it uses a dedicated exception type from the abstractions namespace.

```php
} catch (ApiException $ex) {
    echo $ex->getError()->getMessage();
}
```

The error object is a structured thing rather than a string, so the message is one field of a response body that also carries the error code, which is what a caller actually wants when it needs to distinguish a permissions problem from a not found.

The full example in the readme puts the two together, with the context, the client, the call with the wait, and the catch, which is the shape most PHP applications will end up with.

## me and users, and the permission difference behind them

The two entry points in the readme are worth reading together, because they differ in a way that is about permissions rather than about syntax.

The first fetches a user by their principal name through the users collection, which is an application permission, and it works with the client credentials context alone.

The second calls the me endpoint, and the readme puts a note next to it: calling me requires a signed-in user, and therefore delegated permissions, obtained with the authorization code flow. The example uses the authorization code context, asks for the user read scope, and then calls me and waits.

That is a genuinely useful distinction to have written down, because me is the endpoint most people reach for first, and it is the one that will fail with an application-only registration.

The other thing the readme notes about the model layer is that the operations are built from request builders, with byUserId and similar methods on the collection, and that the results are typed models with getter methods. The user object is asked for its given name, not for a property, which is the model layer's shape throughout the SDK.

## The release rhythm, the upgrade guide, and what is in the tree

The last part of the readme is the part that tells you how the project is run.

The update schedule is stated precisely: the Microsoft Graph PHP SDK is scheduled to be updated during the second and fourth week of each month. That is a useful commitment to know about, because a Graph SDK that tracks a fast moving API is either updated on a rhythm or updated in a panic.

For upgrades there is a dedicated guide, the upgrading document in the repository, and the readme says to check it for breaking changes, bug fixes, and new functionality introduced during major upgrades. The release notes in the readme are a good example of why: the version line in the Composer block is updated automatically by a release tool, and the same release tool writes the changelog, which is in the repository along with a release manifest and a release configuration.

For development, the test suite is run with the PHPUnit binary in the vendor directory, from the base directory. The repository also carries a static analysis configuration, a documentation configuration for generated API reference, a pipeline definition, an editor configuration, a security policy, a file for third party notices, and the code of conduct and contributing guides.

The source lives in a src directory and the tests in a tests directory, with the documentation in a docs directory, and the readme points at the documentation index for both the general documentation and the examples.

So the shape is a generated SDK with the usual supporting material: a pipeline, a static analyser, a test suite, a release tool, and an upgrade guide that exists because a Graph client has to change under you whether you want it to or not.

## Conclusion

msgraph-sdk-php fits a PHP application that has to read from or write to Microsoft 365 or Entra ID and would rather use request builders and models than assemble URLs and payloads by hand. It does not fit a codebase that expects a synchronous client, because every operation returns a promise that has to be waited on, and that is the adjustment the readme keeps having to point out. Verify first that the PHP version in use is 8.2 or later, which the readme states as a prerequisite, that the application registration in the directory has the permissions the calls need, since a permission error here looks like an authentication failure, and that you have read the upgrade guide before moving to a new major version, because the project ships one of those for every breaking release.

## FAQ

### What do I need to install the Microsoft Graph SDK for PHP?

PHP 8.2 or later, and the Composer package microsoft/microsoft-graph, added to the require section of your manifest with a caret constraint on the version. After that you register the application in the Azure Active Directory portal for your tenant, or for multiple tenants.

### Which authentication flows does the Microsoft Graph PHP SDK support?

The client credentials flow, the authorization code flow, and the on-behalf-of flow, with both secret based and certificate based client authentication. The first is represented by a client credential context, the second by an authorization code context, which also needs the application to redirect the user to the Microsoft identity login page to obtain the code.

### Why does the Microsoft Graph PHP SDK return a promise?

The SDK is designed to make asynchronous requests by default, so the operations such as get and post return a promise, and you call wait on it to get the result. That is the one adjustment a PHP developer has to make, and the readme calls it out explicitly.

### Can I call the me endpoint with an application only registration?

No. The readme notes that calling me requires a signed-in user and therefore delegated permissions obtained with the authorization code flow, whereas a call to the users collection by principal name works with the client credentials context.

### How often is the Microsoft Graph PHP SDK updated?

The readme states that the SDK is scheduled to be updated during the second and fourth week of each month. For major upgrades there is a separate upgrade guide in the repository, covering the breaking changes, bug fixes, and new functionality.

## Sources

- [Issues](https://github.com/microsoftgraph/msgraph-sdk-php/issues)
- [microsoftgraph/msgraph-sdk-php on GitHub](https://github.com/microsoftgraph/msgraph-sdk-php)
- [README](https://github.com/microsoftgraph/msgraph-sdk-php/blob/main/README.md)
- [Releases](https://github.com/microsoftgraph/msgraph-sdk-php/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/microsoftgraph-msgraph-sdk-php
