A production-ready PHP SDK for Microsoft Graph API, automatically generated from OpenAPI specifications with strict type-safe DTOs and request builder architecture.
- ✅ Request Builder Architecture - Fluent, chainable API calls
- ✅ Strict Type-Safe DTOs - Full property validation and type hints with array support
- ✅ Array-like Collections - CollectionResponse implements ArrayAccess, Countable, and IteratorAggregate
- ✅ PSR-7/PSR-18 Compliant - Standard HTTP client integration
- ✅ Multiple Authentication Methods - Bearer token and Client Credentials flow
- ✅ Auto-generated from OpenAPI - Always up-to-date with Microsoft Graph API
- ✅ Symfony Serializer - Robust request/response handling
- ✅ Interactive Tinker Shell - REPL for debugging and exploration
composer installRun the generator script to download the OpenAPI spec and generate the SDK:
php generate.phpThis will:
- Download the latest Microsoft Graph OpenAPI specification
- Generate strict DTOs and models
- Create request builder classes
- Set up authentication providers
- Format all code with PHP CS Fixer
<?php
use ApeDevDe\MicrosoftGraphSdk\GraphServiceClient;
use ApeDevDe\MicrosoftGraphSdk\Authentication\BearerTokenAuthenticationProvider;
use Symfony\Component\HttpClient\Psr18Client;
use Nyholm\Psr7\Factory\Psr17Factory;
// Create HTTP client and factories
$httpClient = new Psr18Client();
$psr17Factory = new Psr17Factory();
// Create authentication provider
$authProvider = new BearerTokenAuthenticationProvider('YOUR_ACCESS_TOKEN');
// Create Graph client
$graphClient = GraphServiceClient::create(
$httpClient,
$psr17Factory,
$psr17Factory,
$authProvider
);
// Use the SDK
$user = $graphClient->me()->get();
echo "Hello, " . $user->getDisplayName();<?php
use ApeDevDe\MicrosoftGraphSdk\GraphServiceClient;
use ApeDevDe\MicrosoftGraphSdk\Authentication\ClientCredentialsAuthenticationProvider;
use Symfony\Component\HttpClient\Psr18Client;
use Nyholm\Psr7\Factory\Psr17Factory;
$httpClient = new Psr18Client();
$psr17Factory = new Psr17Factory();
$authProvider = new ClientCredentialsAuthenticationProvider(
'YOUR_TENANT_ID',
'YOUR_CLIENT_ID',
'YOUR_CLIENT_SECRET',
$httpClient,
$psr17Factory,
$psr17Factory
);
$graphClient = GraphServiceClient::create(
$httpClient,
$psr17Factory,
$psr17Factory,
$authProvider
);$me = $graphClient->me()->get();
echo $me->getDisplayName();
echo $me->getMail();$users = $graphClient->users()->get();
// Collections implement ArrayAccess, Countable, and IteratorAggregate
foreach ($users as $user) {
echo $user->getDisplayName() . "\n";
}
// Or use traditional getValue()
foreach ($users->getValue() as $user) {
echo $user->getDisplayName() . "\n";
}$user = $graphClient->users()->byId('user-id')->get();
echo $user->getDisplayName();use ApeDevDe\MicrosoftGraphSdk\Models\User;
$newUser = new User();
$newUser->setDisplayName('John Doe');
$newUser->setUserPrincipalName('john.doe@contoso.com');
$newUser->setMailNickname('johndoe');
$newUser->setAccountEnabled(true);
$createdUser = $graphClient->users()->post($newUser);$user = $graphClient->users()->byId('user-id')->get();
$user->setJobTitle('Senior Developer');
$updatedUser = $graphClient->users()->byId('user-id')->patch($user);$graphClient->users()->byId('user-id')->delete();$messages = $graphClient->me()->messages()->get();
// Direct iteration
foreach ($messages as $message) {
echo $message->getSubject() . "\n";
}
// Array-like access
echo $messages[0]->getSubject(); // First message
echo count($messages); // Count messages// Select specific fields
$user = $graphClient->me()->get([
'$select' => 'displayName,mail,jobTitle'
]);
// Filter users
$users = $graphClient->users()->get([
'$filter' => "startsWith(displayName,'John')",
'$top' => 10
]);
// Order by
$users = $graphClient->users()->get([
'$orderby' => 'displayName'
]);All collection responses implement ArrayAccess, Countable, and IteratorAggregate for intuitive array-like behavior:
$users = $graphClient->users()->get();
// ArrayAccess - Access like an array
$firstUser = $users[0];
$secondUser = $users[1];
// Countable - Use count() directly
$count = count($users);
// IteratorAggregate - Direct iteration
foreach ($users as $user) {
echo $user->getDisplayName() . "\n";
}
// Check existence
if (isset($users[0])) {
echo "Has users!";
}
// Traditional method still works
$users->getValue(); // Returns array of User objectsModel properties that are arrays are properly typed with PHPDoc annotations:
$user = $graphClient->me()->get();
// businessPhones is typed as array with string[] PHPDoc
$phones = $user->getBusinessPhones(); // Returns: string[]
// All array properties work correctly
$licenses = $user->getAssignedLicenses(); // Returns: AssignedLicense[]
$addresses = $user->getProxyAddresses(); // Returns: string[]Debug and explore the Graph API with the interactive REPL:
php tinker.phpFeatures:
- ✅ Arrow key history - Navigate previous commands with Up/Down
- ✅ Tab completion - Autocomplete commands
- ✅ Error handling - Errors don't crash the shell
- ✅ Keyboard shortcuts - Ctrl+D to exit, Ctrl+C to interrupt
Example session:
[1] > $users = $client->users()->get()
=> UserCollectionResponse { count: 42 }
[2] > $users[0]->getDisplayName()
=> "John Doe"
[3] > count($users)
=> 42
[4] > foreach ($users as $u) { echo $u->getDisplayName() . "\n"; }
John Doe
Jane Smith
...Request builders provide a fluent API for constructing Graph API requests:
GraphServiceClient
├── me() → MeRequestBuilder
│ ├── get()
│ ├── messages() → MessagesRequestBuilder
│ ├── mailFolders() → MailFoldersRequestBuilder
│ └── calendar() → CalendarRequestBuilder
├── users() → UsersRequestBuilder
│ ├── get()
│ ├── post()
│ ├── byId() → UserItemRequestBuilder
│ │ ├── get()
│ │ ├── patch()
│ │ ├── delete()
│ │ ├── messages()
│ │ └── mailFolders()
│ └── count()
├── groups() → GroupsRequestBuilder
└── applications() → ApplicationsRequestBuilder
All models are strictly typed PHP classes generated from the OpenAPI specification:
- Full property type hints
- Getters and setters for all properties
- Validation support
- Serialization/deserialization via Symfony Serializer
Two authentication providers are included:
- BearerTokenAuthenticationProvider - For pre-acquired access tokens
- ClientCredentialsAuthenticationProvider - OAuth 2.0 client credentials flow with automatic token refresh
- PHP 8.1 or higher
- PSR-7 HTTP Message implementation
- PSR-18 HTTP Client implementation
- Symfony Serializer
To regenerate the SDK with the latest OpenAPI specification:
php generate.phpYou can extend the generated request builders to add custom functionality:
namespace ApeDevDe\MicrosoftGraphSdk\RequestBuilders;
class CustomUsersRequestBuilder extends UsersRequestBuilder
{
public function searchByDepartment(string $department): UserCollectionResponse
{
return $this->get([
'$filter' => "department eq '{$department}'"
]);
}
}This SDK is auto-generated from Microsoft Graph OpenAPI specifications.
Alexis Peters (info@alexispeters.de)