microsoft/microsoft-graph-core
Install the package:
composer require microsoft/microsoft-graph-core
Register your app in Azure Portal and note:
tenantIdclientIdclientSecretFirst API call (e.g., fetch current user):
use Microsoft\Graph\Core\GraphClientFactory;
use Microsoft\Graph\Core\Authentication\ClientCredentialContext;
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
// Auth setup
$tokenRequestContext = new ClientCredentialContext(
'your-tenant-id',
'your-client-id',
'your-client-secret'
);
$tokenProvider = new GraphPhpLeagueAccessTokenProvider($tokenRequestContext);
$accessToken = $tokenProvider->getAuthorizationTokenAsync('https://graph.microsoft.com')->wait();
// HTTP client
$httpClient = GraphClientFactory::createWithConfig([
'headers' => ['Authorization' => 'Bearer ' . $accessToken]
]);
// Execute request
$response = $httpClient->get('/v1.0/me');
$user = json_decode($response->getBody());
/me, /users/{id}/me/messages, /users/{id}/mailFoldersBatchRequestContent)Client Credentials Flow (for app-only access):
$tokenProvider = new GraphPhpLeagueAccessTokenProvider(
new ClientCredentialContext($tenantId, $clientId, $clientSecret)
);
Custom Auth Provider (for OAuth2 flows like user/delegated):
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
$authProvider = new GraphPhpLeagueAuthenticationProvider(
new \League\OAuth2\Client\Provider\GenericProvider([...])
);
$httpClient = GraphClientFactory::createWithAuthProvider($authProvider);
Token Caching (for performance):
$tokenProvider = new GraphPhpLeagueAccessTokenProvider(
$tokenRequestContext,
new \League\OAuth2\Client\Token\AccessToken(['access_token' => 'cached-token'])
);
Simple GET Request:
$response = $httpClient->get('/v1.0/users');
$users = json_decode($response->getBody());
POST with Payload:
$response = $httpClient->post('/v1.0/me/sendMail', [
'json' => [
'message' => [...]
]
]);
Batch Requests (for efficiency):
use Microsoft\Graph\Core\Http\BatchRequestContent;
$batch = new BatchRequestContent();
$batch->addRequest('GET', '/v1.0/me/messages', null);
$batch->addRequest('GET', '/v1.0/me/calendar/events', null);
$response = $httpClient->post('/v1.0/$batch', [
'headers' => ['Content-Type' => 'application/json'],
'body' => $batch->getBody()
]);
Middleware: Extend GraphClientFactory to add custom middleware (e.g., logging, retries):
$stack = \GuzzleHttp\HandlerStack::create();
$stack->push(\GuzzleHttp\Middleware::tap(function ($request) {
// Log request
}));
$httpClient = GraphClientFactory::createWithConfig([
'handler' => $stack
]);
Pagination: Handle @odata.nextLink in responses for large datasets:
$nextLink = $response->getHeader('odata-nextlink')[0] ?? null;
while ($nextLink) {
$response = $httpClient->get($nextLink);
$nextLink = $response->getHeader('odata-nextlink')[0] ?? null;
}
Error Handling: Use try-catch with Microsoft\Graph\Core\Http\GraphServiceException:
try {
$response = $httpClient->get('/v1.0/nonexistent');
} catch (\Microsoft\Graph\Core\Http\GraphServiceException $e) {
logger()->error('Graph API Error: ' . $e->getMessage());
}
Token Expiry:
if ($tokenProvider->hasExpired()) {
$token = $tokenProvider->getNewToken()->wait();
}
National Clouds:
graph.microsoft.com may fail in non-US regions. Use GraphConstants::REST_ENDPOINT or specify custom endpoints:
$tokenProvider->getAuthorizationTokenAsync('https://graph.microsoft.us');
Batch Request Limits:
if ($batch->getRequests()->count() > 20) {
throw new \RuntimeException('Batch request exceeds 20 operations');
}
PHP Version:
CORS/Proxy Issues:
proxy option in GraphClientFactory:
$httpClient = GraphClientFactory::createWithConfig([
'proxy' => 'http://your-proxy:port'
]);
Enable Guzzle Debugging:
$httpClient = GraphClientFactory::createWithConfig([
'debug' => fopen('graph_debug.log', 'w'),
'headers' => ['Authorization' => 'Bearer ' . $accessToken]
]);
Validate Tokens:
Check Response Headers:
odata-nextlink, odata-count, and Retry-After headers for pagination/rate-limiting clues.Custom Models:
Microsoft\Graph\Core\GraphEntity to add domain-specific properties:
class CustomUser extends \Microsoft\Graph\Core\GraphEntity {
public string $customField;
}
Middleware Stack:
$stack->push(\GuzzleHttp\Middleware::retry(
function ($retries, $request, $exception) {
return $retries < 3 && $exception instanceof \GuzzleHttp\Exception\ConnectException;
},
function ($retries, \GuzzleHttp\RequestOptions $options) {
return 100 * $retries; // Exponential backoff
}
));
Authentication Providers:
Microsoft\Graph\Core\Authentication\IGraphAuthenticationProvider for custom auth flows (e.g., Azure AD B2C):
class CustomAuthProvider implements IGraphAuthenticationProvider {
public function authenticateRequest(\GuzzleHttp\Psr7\Request $request): \GuzzleHttp\Psr7\Request {
$request = $request->withHeader('Authorization', 'Bearer ' . $this->getToken());
return $request;
}
}
Accept: application/json and Content-Type: application/json by default. Override in GraphClientFactory if needed.$httpClient = GraphClientFactory::createWithConfig([
'timeout' => 30.0,
'connect_timeout' => 10.0
]);
How can I help you explore Laravel packages today?