Schreiben einer PHP-App zum Abrufen von Outlook-Mail, -Kalender und -KontaktenWrite a PHP app to get Outlook mail, calendar, and contacts

In diesem Leitfaden werden Sie schrittweise durch den Prozess des Erstellens einer PHP-App zum Abrufen von Nachrichten in Office 365 oder Outlook.com geführt. Wenn Sie die hier beschriebenen Schritte ausführen, sollte der Quellcode in diesem Repository das Ergebnis sein.The purpose of this guide is to walk through the process of creating a simple PHP app that retrieves messages in Office 365 or Outlook.com. The source code in this repository is what you should end up with if you follow the steps outlined here.

In diesem Leitfaden wird https://developer.microsoft.com/en-us/graph/)Microsoft Graph zum Zugriff auf Outlook-Mail verwendet.This guide will use Microsoft Graph(https://developer.microsoft.com/en-us/graph/) to access Outlook mail. Microsoft empfiehlt die Verwendung von Microsoft Graph für den Zugriff auf Outlook-Mail, -Kalender und -Kontakte.Microsoft recommends using Microsoft Graph to access Outlook mail, calendar, and contacts. Verwenden Sie die Outlook-APIs nur dann direkt (über https://outlook.office.com/api), wenn Sie ein Feature benötigen, das in den Graph-Endpunkten nicht verfügbar ist.This guide will use the Microsoft Graph to access Outlook mail. Microsoft recommends using the Microsoft Graph to access Outlook mail, calendar, and contacts. You should use the Outlook APIs directly (via https://outlook.office.com/api) only if you require a feature that is not available on the Graph endpoints. Eine Version dieses Beispiels mit Verwendung der Outlook-APIs finden Sie in dieser Verzweigung.For a version of this sample that uses the Outlook APIs, see this branch.

In diesem Leitfaden wird davon ausgegangen, dass Sie PHP bereits installiert haben und auf Ihrem Entwicklungscomputer ausführen. Das Lernprogramm wurde mit PHP 5.6.30 erstellt.This guide assumes that you already have PHP installed and working on your development machine. The tutorial was created using PHP 5.6.30.

Erstellen der AppCreate the app

Lassen Sie uns direkt loslegen. Zu Beginn verwenden wir PHP 7.1, Composer und Laravel zum schnellen Erstellen unserer PHP-App. Wenn Sie diese Tools noch nicht installiert haben, installieren Sie sie, bevor Sie fortfahren.Let's dive right in! To start, we're going to use PHP 7.1, Composer and Laravel to quickly create our PHP app. If you don't already have these tools installed, please install them before proceeding.

Öffnen Sie auf Ihrem Entwicklungscomputer die Eingabeaufforderung oder Shell für ein Verzeichnis, in dem Sie das neue Projekt erstellen möchten. Geben Sie zum Erstellen des Projekts den folgenden Befehl ein.On your development machine, open your command prompt or shell to a directory where you want to create your new project. Enter the following command to create the project.

laravel new php-tutorial

Dadurch werden das Verzeichnis php-tutorial sowie ein Gerüst für das Projekt erstellt und Abhängigkeiten heruntergeladen. Sobald der Befehl abgeschlossen ist, sollten wir sicherstellen, dass alles funktioniert. Ändern Sie das aktuelle Verzeichnis in das Verzeichnis php-tutorial, und führen Sie den folgenden Befehl aus, um den Laravel-Entwicklungsserver zu starten.This will create new php-tutorial directory, scaffold the project, and download dependencies. Once the command completes, let's make sure that everything is working. Change your current directory to the php-tutorial directory, and run the following command to start the Laravel development server.

php artisan serve

Öffnen Sie Ihren Browser, und navigieren Sie zu http://localhost:8000. Daraufhin sollte die standardmäßige Laravel-Startseite angezeigt werden.Open your brower and browse to http://localhost:8000. You should see a default Laravel start page.

Entwerfen der AppDesigning the app

Unsere App ist sehr einfach. Wenn ein Benutzer die Website besucht, sieht er einen Link zum Anmelden und Anzeigen seiner E-Mails. Beim Klicken auf den Link gelangt er zur Azure-Anmeldeseite, wo er sich mit seinem Office 365- oder Outlook.com-Konto anmelden und unserer App Zugriff gewähren kann. Schließlich wird er zurück zu unserer App geleitet, die eine Liste der neuesten E-Mails im Posteingang des Benutzers anzeigt.Our app will be very simple. When a user visits the site, they will see a link to log in and view their email. Clicking that link will take them to the Azure login page where they can login with their Office 365 or Outlook.com account and grant access to our app. Finally, they will be redirected back to our app, which will display a list of the most recent email in the user's inbox.

Beginnen wir mit dem Erstellen eines Layouts. Erstellen Sie eine neue Datei mit dem Namen layout.blade.php im Verzeichnis ./php-tutorial/resources/views, und fügen Sie den folgenden Code hinzu.Let's begin by creating a layout. Create a new file named layout.blade.php in the ./php-tutorial/resources/views directory and add the following code.

Inhalt der Datei ./php-tutorial/resources/views/layout.blade.phpContents of the ./php-tutorial/resources/views/layout.blade.php file

<!DOCTYPE html>
<html>
  <head>
    <title>PHP Outlook Sample</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
    <link rel="stylesheet" href="{{ asset('/css/app.css') }}">
  </head>
  <body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">PHP Outlook Sample</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li class="<?php echo ($_SERVER['REQUEST_URI'] == '/' ? 'active' : '');?>"><a href="/">Home</a></li>
            <li class="<?php echo ($_SERVER['REQUEST_URI'] == '/mail' ? 'active' : '');?>"><a href="/mail">Inbox</a></li>
          </ul>
          <?php if(isset($username)) { ?>
          <ul class="nav navbar-nav navbar-right">
            <li><p class="navbar-text">Hello <?php echo $username ?>!</p></li>
          </ul>
          <?php } ?>
        </div><!--/.nav-collapse -->
      </div>
    </nav>

    <div class="container" role="main">
      @yield('content')
    </div>

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
  </body>
</html>

So erhalten wir eine grundlegende HTML-Struktur, und es wird Bootstrap für die Formatierung hinzugefügt.This just gives us a basic HTML structure and adds Bootstrap for styling.

Nun entfernen wir den Standard-CSS-Code aus ./php-tutorial/public/css/app.css und fügen eine einfache Formatierung hinzu, deshalb verwenden wir nur die Standardwerte von Bootstrap. Öffnen Sie die Datei, und ersetzen Sie den gesamten Inhalt durch Folgendes.Now let's remove the default CSS code from ./php-tutorial/public/css/app.css and add some basic styling so we're just using Bootstrap's defaults. Open the file and it's entire contents with the following.

Inhalt der Datei ./php-tutorial/public/css/app.cssContents of the ./php-tutorial/public/css/app.css file

body {
  padding-top: 70px;
  padding-bottom: 30px;
}

Nun ändern wir die vorhandene Startseite so, dass dieses Layout verwendet wird. Öffnen Sie die Datei ./php-tutorial/resources/views/welcome.blade.php, und ersetzen Sie den Inhalt durch den folgenden Code.Now we'll modify the existing home page to use this layout. Open the ./php-tutorial/resources/views/welcome.blade.php file and replace it's contents with the following code.

Inhalt der Datei ./php-tutorial/resources/views/welcome.blade.phpContents of the ./php-tutorial/resources/views/welcome.blade.php file

@extends('layout')

@section('content')
<div class="jumbotron">
  <h1>PHP Outlook Sample</h1>
  <p>This example shows how to get an OAuth token from Azure using the <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-code" target="_blank">authorization code grant flow</a> and to use that token to make calls to the Outlook APIs in the <a href="https://developer.microsoft.com/en-us/graph/" target="_blank">Microsoft Graph</a>.</p>
  <p>
    <a class="btn btn-lg btn-primary" href="/signin" role="button" id="connect-button">Connect to Outlook</a>
  </p>
</div>
@endsection

Die Schaltfläche Verbindung mit Outlook herstellen führt noch keine Aktion aus, aber das werden wir bald ändern.The Connect to Outlook button doesn't do anything yet, but we'll fix that soon.

Registrieren der AppRegister the app

Wichtig

Neue App-Registrierungen sollten im Anwendungsregistrierungsportal erstellt und verwaltet werden, damit sie mit Outlook.com kompatibel sind. Erstellen Sie neue App-Registrierungen nur dann im Azure-Verwaltungsportal Folgendes auf Ihre App zutrifft:New app registrations should be created and managed in the new Application Registration Portal to be compatible with Outlook.com. Only create new app registrations in the Azure Management Portal if your app:

  • Sie verwendet den OAuth2 Client Credentials Grant-Fluss oderUses the OAuth2 Client Credentials Grant Flow, or
  • Sie muss neben Outlook auf andere Office 365-Arbeitslasten zugreifen (z. B. OneDrive for Business oder SharePoint)Needs to access other Office 365 workloads besides Outlook (such as OneDrive for Business or SharePoint)

Beachten Sie, dass mithilfe des Azure-Verwaltungsportals registrierte Apps nicht mit Outlook.com kompatibel sind und dass Berechtigungsbereiche nicht dynamisch angefordert werden können.Bear in mind that apps registered using the Azure Management Portal will not be compatible with Outlook.com, and will not be able to dynamically request permissions scopes. Vorhandene App-Registrierungen, die im Azure-Verwaltungsportal erstellt wurden, funktionieren weiterhin nur für Office 365.Existing app registrations that were created in the Azure Management Portal will continue to work for Office 365 only. Diese Registrierungen werden nicht im Anwendungsregistrierungsportal angezeigt und müssen im Azure-Verwaltungsportal verwaltet werden.These registrations do not show up in the Application Registration Portal and must be managed in the Azure Management Portal.

KontoanforderungenAccount requirements

Um das Anwendungsregistrierungsportal zu verwenden, benötigen Sie entweder ein Office 365-Geschäfts- oder Schulkonto oder ein Microsoft-Konto. Wenn Sie nicht über eines dieser Konten verfügen, haben Sie verschiedene Möglichkeiten:In order to use the Application Registration Portal, you need either an Office 365 work or school account, or a Microsoft account. If you don't have either of these, you have a number of options:

  • Registrieren Sie sich hier für ein neues Microsoft-Konto.Sign up for a new Microsoft account here.
  • Sie haben mehrere Möglichkeiten, ein Office 365-Abonnement zu erhalten:You can obtain an Office 365 subscription in a couple of different ways:

REST-API-VerfügbarkeitREST API availability

Die REST-API ist derzeit auf allen Office 365-Konten, die über Exchange Online verfügen, sowie auf allen Outlook.com-Konten aktiviert.The REST API is currently enabled on all Office 365 accounts that have Exchange Online, and all Outlook.com accounts.

Wechseln Sie zum App-Registrierungsportal, um schnell eine App-ID und einen geheimen Schlüssel abzurufen.Head over to the Application Registration Portal to quickly get an application ID and secret.

  1. Melden Sie sich über den Link Anmelden mit Ihrem Microsoft-Konto (Outlook.com) oder Ihrem Geschäfts-, Schul- oder Unikonto (Office 365) an.Using the Sign in link, sign in with either your Microsoft account (Outlook.com), or your work or school account (Office 365).
  2. Klicken Sie auf die Schaltfläche App hinzufügen. Geben Sie php-tutorial für den Namen ein, und klicken Sie auf Anwendung erstellen.Click the Add an app button. Enter php-tutorial for the name and click Create application.
  3. Suchen Sie den Abschnitt Anwendungsgeheimnisse, und klicken Sie auf die Schaltfläche Neues Kennwort generieren. Kopieren Sie nun das Kennwort, und speichern Sie es an einem sicheren Ort. Nachdem Sie das Kennwort kopiert haben, klicken Sie auf Ok.Locate the Application Secrets section, and click the Generate New Password button. Copy the password now and save it to a safe place. Once you've copied the password, click Ok.
  4. Suchen Sie den Abschnitt Plattformen, und klicken Sie auf Plattform hinzufügen. Wählen Sie Web aus, und geben Sie dann http://localhost:8000/authorize unter Umleitungs-URIs ein.Locate the Platforms section, and click Add Platform. Choose Web, then enter http://localhost:8000/authorize under Redirect URIs.
  5. Klicken Sie auf Speichern, um die Registrierung abzuschließen. Kopieren Sie die App-ID, und speichern Sie sie zusammen mit dem Kennwort, das Sie zuvor kopiert haben. Wir benötigen diese Werte bald.Click Save to complete the registration. Copy the Application Id and save it along with the password you copied earlier. We'll need those values soon.

So sollten die Details Ihrer App-Registrierung aussehen, wenn Sie fertig sind.Here's what the details of your app registration should look like when you are done.

Screenshot der abgeschlossenen App-Registrierung im App-Registrierungsportal

Implementieren von OAuth2Implementing OAuth2

Unser Ziel in diesem Abschnitt ist es, die Schaltfläche auf unserer Homepage so einzurichten, dass der OAuth2-Autorisierungscodegenehmigungs-Fluss mit Azure AD initiiert wird.Our goal in this section is to make the button on our home page initiate the OAuth2 Authorization Code Grant flow with Azure AD.

Wir verwenden den League OAuth2-Client, um die Autorisierung und die Tokenanforderungen zu verarbeiten. Lassen Sie uns diesen installieren, bevor wir fortfahren.We'll use the League OAuth 2 Client to handle our authorization and token requests. Let's install that before proceeding.

Öffnen Sie die Datei ./php-tutorial/composer.json, und suchen Sie den require-Eintrag. Aktualisieren Sie diesen Eintrag so, dass "league/oauth2-client": "^2.0" hinzugefügt wird, und speichern Sie die Datei.Open the ./php-tutorial/composer.json file and locate the require entry. Update this entry to add "league/oauth2-client": "^2.0" and save the file.

Aktualisierter require-Eintrag in ./php-tutorial/composer.jsonUpdated require entry in ./php-tutorial/composer.json

"require": {
    "php": ">=5.6.4",
    "laravel/framework": "5.4.*",
    "laravel/tinker": "~1.0",
    "league/oauth2-client": "^2.0"
},

Führen den folgenden Befehl an der Eingabeaufforderung/Shell im Verzeichnis php-tutorial aus.Run the following command from your command prompt/shell in the php-tutorial directory.

composer update

Hierdurch werden der OAuth2-Client sowie Abhängigkeiten in Ihrem ./php-tutorial/vendors-Ordner installiert.This will install the OAuth 2 client and dependencies into your ./php-tutorial/vendors folder.

Nachdem das Herunterladen der erforderlichen Bibliotheken in Composer abgeschlossen ist, erstellen wir einen neuen Controller, der alle OAuth-Funktionen enthalten soll. Erstellen Sie eine neue Datei im ./php-tutorial/app/Http/Controllers-Verzeichnis mit dem Namen AuthController.php. Fügen Sie den folgenden Code hinzu.Once composer is done downloading the required libraries, let's create a new controller to contain all of our OAuth functions. Create a new file in the ./php-tutorial/app/Http/Controllers directory called AuthController.php. Add the following code.

Inhalt der Datei ./php-tutorial/app/Http/Controllers/AuthController.phpContents of the ./php-tutorial/app/Http/Controllers/AuthController.php file

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class AuthController extends Controller
{
  public function signin() 
  {
    if (session_status() == PHP_SESSION_NONE) {
      session_start();
    }

    // Initialize the OAuth client
    $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
      'clientId'                => env('OAUTH_APP_ID'),
      'clientSecret'            => env('OAUTH_APP_PASSWORD'),
      'redirectUri'             => env('OAUTH_REDIRECT_URI'),
      'urlAuthorize'            => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
      'urlAccessToken'          => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
      'urlResourceOwnerDetails' => '',
      'scopes'                  => env('OAUTH_SCOPES')
    ]);

    // Output the authorization endpoint
    echo 'Auth URL: '.$oauthClient->getAuthorizationUrl();
    exit();
  }
}

Jetzt müssen wir eine Route zu unserer neuen Controllermethode konfigurieren. Öffnen Sie die Datei ./php-tutorial/routes/web.php, und fügen Sie die folgende Zeile am Ende der Datei hinzu.Now we need to configure a route to our new controller method. Open the ./php-tutorial/routes/web.php file and add the following line at the bottom of the file.

Neuer Eintrag in ./php-tutorial/routes/web.phpNew entry in ./php-tutorial/routes/web.php

Route::get('/signin', 'AuthController@signin');

Lassen Sie uns nun die App konfigurieren. Wir werden die Umgebungsvariablen zum Speichern aller OAuth-Details verwenden. Öffnen Sie die Datei ./php-tutorial/.env, und fügen Sie die folgenden Zeilen am Ende der Datei hinzu.Now let's configure the app. We'll use environment variables to hold all of the OAuth details. Open the ./php-tutorial/.env file and add the following lines at the bottom.

Neue Einträge in ./php-tutorial/.envNew entries in ./php-tutorial/.env

OAUTH_APP_ID=YOUR_APP_ID_HERE
OAUTH_APP_PASSWORD=YOUR_APP_PASSWORD_HERE
OAUTH_REDIRECT_URI=http://localhost:8000/authorize
OAUTH_SCOPES='openid profile offline_access User.Read Mail.Read'
OAUTH_AUTHORITY=https://login.microsoftonline.com/common
OAUTH_AUTHORIZE_ENDPOINT=/oauth2/v2.0/authorize
OAUTH_TOKEN_ENDPOINT=/oauth2/v2.0/token

Ersetzen Sie YOUR_APP_ID_HERE und YOUR_APP_PASSWORD_HERE durch die App-ID und das Kennwort, die bzw. das Sie vom App-Registrierungstool abgerufen haben, und speichern Sie die Datei.Replace YOUR_APP_ID_HERE and YOUR_APP_PASSWORD_HERE with the application ID and password you obtained from the App Registration Tool and save the file.

Speichern Sie alle Änderungen, und starten Sie den Laravel-Entwicklungsserver (php artisan serve) neu. Navigieren Sie zu http://localhost:8000, und klicken Sie auf die Schaltfläche Verbindung mit Outlook herstellen. Auf der Seite sollte die Autorisierungs-URL angezeigt werden. Dies sollte folgendermaßen aussehen:Save all your changes and restart the Laravel development server (php artisan serve). Browse to http://localhost:8000 and click on the Connect to Outlook button. You should see the authorization URL printed to the page, which should look something like this.

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?state=48b0ad0b3b443a543cf823f98db760c4&scope=openid%20profile%20offline_access%20User.Read%20Mail.Read&response_type=code&approval_prompt=auto&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Foauth&client_id=<YOUR_CLIENT_ID>

Aktualisieren wir jetzt die App so, dass sie automatisch zu dieser URL navigiert, damit der Benutzer sich anmelden und Zugriff auf die App erteilen kann. Wir fügen auch eine weitere Controllermethode hinzu, um die Umleitung zurück vom Autorisierungsendpunkt aufzunehmen. Ersetzen Sie zunächst die vorhandene signin-Methode in ./php-tutorial/app/Http/Controllers/AuthController.php durch die folgende.Now let's update the app to actually navigate to that URL so the user can sign in and grant access to the app. We'll also add another controller method to receive the redirect back from the Azure authorization endpoint. First, replace the existing signin method in ./php-tutorial/app/Http/Controllers/AuthController.php with this one.

public function signin() 
{
  if (session_status() == PHP_SESSION_NONE) {
    session_start();
  }

  // Initialize the OAuth client
  $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
    'clientId'                => env('OAUTH_APP_ID'),
    'clientSecret'            => env('OAUTH_APP_PASSWORD'),
    'redirectUri'             => env('OAUTH_REDIRECT_URI'),
    'urlAuthorize'            => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
    'urlAccessToken'          => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
    'urlResourceOwnerDetails' => '',
    'scopes'                  => env('OAUTH_SCOPES')
  ]);

  // Generate the auth URL
  $authorizationUrl = $oauthClient->getAuthorizationUrl();

  // Save client state so we can validate in response
  $_SESSION['oauth_state'] = $oauthClient->getState();

  // Redirect to authorization endpoint
  header('Location: '.$authorizationUrl);
  exit();
}

Anstatt die URL in die Antwort zu drucken, wird der Clientstatus in der Sitzung gespeichert und der Location-Header zum Umleiten des Browsers verwendet.Instead of printing the URL to the response, it saves the client state to the session and uses the Location header to redirect the browser.

Jetzt fügen wir eine authorize-Methode hinzu, um die Umleitung zurück von Azure aufzunehmen und den Autorisierungscode aus der Antwort zu extrahieren. Fügen Sie die folgende Methode zu ./php-tutorial/app/Http/Controllers/AuthController.php hinzu:Now, let's add an authorize method to receive the redirect back from Azure and extract the authorization code from the response. Add the following method in ./php-tutorial/app/Http/Controllers/AuthController.php.

Neue gettoken-Methode in ./php-tutorial/app/Http/Controllers/AuthController.phpNew gettoken method in ./php-tutorial/app/Http/Controllers/AuthController.php

public function gettoken()
{
  if (session_status() == PHP_SESSION_NONE) {
    session_start();
  }

  // Authorization code should be in the "code" query param
  if (isset($_GET['code'])) {
    echo 'Auth code: '.$_GET['code'];
    exit();
  }
  elseif (isset($_GET['error'])) {
    exit('ERROR: '.$_GET['error'].' - '.$_GET['error_description']);
  }
}

Hinzufügen einer neuen Route zu ./php-tutorial/routes/web.phpAdd a new route in ./php-tutorial/routes/web.php

Neuer Eintrag in ./php-tutorial/routes/web.phpNew entry in ./php-tutorial/routes/web.php

Route::get('/authorize', 'AuthController@gettoken');

Speichern Sie Ihre Änderungen, und navigieren Sie zu http://localhost:8000. Wenn Sie dieses Mal auf die Seite Verbindung mit Outlook herstellen klicken, werden Sie zur Anmeldeseite umgeleitet. Wenn Sie Ihre Office 365- oder Outlook.com-Kontoinformationen eingeben und die angeforderten Berechtigungen akzeptieren, wird der Autorisierungscode in der App angezeigt. Führen wir nun eine Aktion damit aus.Save your changes and browse to http://localhost:8000. This time when you click on the Connect to Outlook button you should be redirected to the login page. If you enter your Office 365 or Outlook.com account information and accept the requested permissions, the app will display the authorization code. Now let's do something with it.

Austauschen des Codes durch ein TokenExchanging the code for a token

Lassen Sie uns die gettoken-Methode so aktualisieren, dass der OAuth2-Client verwendet wird, um eine Tokenanforderung vorzunehmen. Zunächst überprüfen wir, ob der in der Umleitung enthaltene Zustand dem Zustand entspricht, den wir nach dem Generieren der Autorisierung in der Sitzung gespeichert haben. Anschließend erstellen wir die eigentliche Tokenanforderung mithilfe des Autorisierungscodes. Ersetzen Sie die vorhandene gettoken durch diese neue.Let's update the gettoken method to use the OAuth 2 client to make a token request. First we'll verify that the state included in the redirect matches the one we saved in the session after generating the authorization URL, then we'll make the actual token request using the authorization code. Replace the existing gettoken with this new one.

Aktualisierte gettoken-Funktion in ./php-tutorial/app/Http/Controllers/AuthController.phpUpdated gettoken function in ./php-tutorial/app/Http/Controllers/AuthController.php

public function gettoken()
{
  if (session_status() == PHP_SESSION_NONE) {
    session_start();
  }

  // Authorization code should be in the "code" query param
  if (isset($_GET['code'])) {
    // Check that state matches
    if (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth_state'])) {
      exit('State provided in redirect does not match expected value.');
    }

    // Clear saved state
    unset($_SESSION['oauth_state']);

    // Initialize the OAuth client
    $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
      'clientId'                => env('OAUTH_APP_ID'),
      'clientSecret'            => env('OAUTH_APP_PASSWORD'),
      'redirectUri'             => env('OAUTH_REDIRECT_URI'),
      'urlAuthorize'            => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
      'urlAccessToken'          => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
      'urlResourceOwnerDetails' => '',
      'scopes'                  => env('OAUTH_SCOPES')
    ]);

    try {
      // Make the token request
      $accessToken = $oauthClient->getAccessToken('authorization_code', [
        'code' => $_GET['code']
      ]);

      echo 'Access token: '.$accessToken->getToken();
    }
    catch (League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
      exit('ERROR getting tokens: '.$e->getMessage());
    }
    exit();
  }
  elseif (isset($_GET['error'])) {
    exit('ERROR: '.$_GET['error'].' - '.$_GET['error_description']);
  }
}

Speichern Sie Ihre Änderungen, und durchlaufen Sie den Anmeldevorgang bei der App erneut. Dieses Mal sollte das Zugriffstoken angezeigt werden.Save your changes and go through the login process in your app again. This time you should see the access token displayed.

Aktualisieren des ZugriffstokensRefreshing the access token

Von Azure zurückgegebene Zugriffstoken sind eine Stunde lang gültig. Wenn Sie das Token verwenden, nachdem es abgelaufen ist, geben die API-Aufrufe 401-Fehler zurück. Sie könnten den Benutzer bitten, sich erneut anzumelden, aber die bessere Option besteht darin, das Token automatisch zu aktualisieren. Lassen Sie uns nun also am Speichern und Aktualisieren der Token (bei Bedarf) arbeiten, bevor wir fortfahren.Access tokens returned from Azure are valid for an hour. If you use the token after it has expired, the API calls will return 401 errors. You could ask the user to sign in again, but the better option is to refresh the token silently. So let's work on storing the tokens and refreshing them if needed before we proceed.

Zunächst erstellen wir eine neue Klasse zum Verwalten des Speicherns und Abrufens des Tokens. Da es sich hierbei um ein Beispiel handelt, werden wir der Einfachheit halber alles in der Sitzung speichern. Für Produktionsszenarien wäre es besser, das Aktualisierungstoken in einer sicheren Datenbank zu speichern.First, let's create a new class to manage storing and retrieving the token. Since this is a sample, we'll keep it simple and store everything in the session. For production scenarios, it would be way better to store the refresh token in a secure database.

Erstellen Sie einen neuen Ordner im ./php-tutorial/app-Verzeichnis mit dem Namen TokenStore. Erstellen Sie in diesem neuen Ordner eine Datei mit dem Namen TokenCache.php, und fügen Sie den folgenden Code hinzu.Create a new folder in the ./php-tutorial/app directory called TokenStore. In this new folder, create a file called TokenCache.php and add the following code.

Inhalt der Datei ./php-tutorial/app/TokenStore/TokenCache.phpContents of the ./php-tutorial/app/TokenStore/TokenCache.php file

<?php

namespace App\TokenStore;

class TokenCache {
  public function storeTokens($access_token, $refresh_token, $expires) {
    $_SESSION['access_token'] = $access_token;
    $_SESSION['refresh_token'] = $refresh_token;
    $_SESSION['token_expires'] = $expires;
  }

  public function clearTokens() {
    unset($_SESSION['access_token']);
    unset($_SESSION['refresh_token']);
    unset($_SESSION['token_expires']);
  }

  public function getAccessToken() {
    // Check if tokens exist
    if (empty($_SESSION['access_token']) ||
        empty($_SESSION['refresh_token']) ||
        empty($_SESSION['token_expires'])) {
      return '';
    }

    // Check if token is expired
    //Get current time + 5 minutes (to allow for time differences)
    $now = time() + 300;
    if ($_SESSION['token_expires'] <= $now) {
      // Token is expired (or very close to it)
      // so let's refresh

      // Initialize the OAuth client
      $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
        'clientId'                => env('OAUTH_APP_ID'),
        'clientSecret'            => env('OAUTH_APP_PASSWORD'),
        'redirectUri'             => env('OAUTH_REDIRECT_URI'),
        'urlAuthorize'            => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
        'urlAccessToken'          => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
        'urlResourceOwnerDetails' => '',
        'scopes'                  => env('OAUTH_SCOPES')
      ]);

      try {
        $newToken = $oauthClient->getAccessToken('refresh_token', [
          'refresh_token' => $_SESSION['refresh_token']
        ]);

        // Store the new values
        $this->   storeTokens($newToken->getToken(), $newToken->getRefreshToken(), 
          $newToken->getExpires());

        return $newToken->getToken();
      }
      catch (League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
        return '';
      }
    }
    else {
      // Token is still valid, just return it
      return $_SESSION['access_token'];
    }
  }
}

Dadurch werden die drei neue Funktionen hinzugefügt. Die storeTokens-Funktion speichert die Werte in der Sitzung. Die clearTokens-Funktion entfernt diese. Die getAccessToken-Funktion überprüft den Ablauf des aktuellen Zugriffstokens und aktualisiert es, falls erforderlich.This adds three new functions. The storeTokens function will save the values in the session. The clearTokens function will remove them. The getAccessToken function will check expiration of the current access token and refresh it if necessary.

Nun aktualisieren wir die gettoken-Methode so, dass diese neue Klasse zum Speichern der Werte und zum Umleiten von /mail in unserer App verwendet wird. Ersetzen Sie die vorhandene gettoken durch diese neue. Version.Now let's update the gettoken method to use this new class to store the values and redirect to /mail in our app. Replace the existing gettoken with this new version.

Aktualisierte gettoken-Funktion in ./php-tutorial/app/Http/Controllers/AuthController.phpUpdated gettoken function in ./php-tutorial/app/Http/Controllers/AuthController.php

public function gettoken()
{
  if (session_status() == PHP_SESSION_NONE) {
    session_start();
  }

  // Authorization code should be in the "code" query param
  if (isset($_GET['code'])) {
    // Check that state matches
    if (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth_state'])) {
      exit('State provided in redirect does not match expected value.');
    }

    // Clear saved state
    unset($_SESSION['oauth_state']);

    // Initialize the OAuth client
    $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
      'clientId'                => env('OAUTH_APP_ID'),
      'clientSecret'            => env('OAUTH_APP_PASSWORD'),
      'redirectUri'             => env('OAUTH_REDIRECT_URI'),
      'urlAuthorize'            => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
      'urlAccessToken'          => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
      'urlResourceOwnerDetails' => '',
      'scopes'                  => env('OAUTH_SCOPES')
    ]);

    try {
      // Make the token request
      $accessToken = $oauthClient->getAccessToken('authorization_code', [
        'code' => $_GET['code']
      ]);

      // Save the access token and refresh tokens in session
      // This is for demo purposes only. A better method would
      // be to store the refresh token in a secured database
      $tokenCache = new \App\TokenStore\TokenCache;
      $tokenCache->storeTokens($accessToken->getToken(), $accessToken->getRefreshToken(),
        $accessToken->getExpires());

      // Redirect back to mail page
      return redirect()->route('mail');
    }
    catch (League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
      exit('ERROR getting tokens: '.$e->getMessage());
    }
    exit();
  }
  elseif (isset($_GET['error'])) {
    exit('ERROR: '.$_GET['error'].' - '.$_GET['error_description']);
  }
}

Bevor wir fortfahren, implementieren wir eine sehr einfache /mail-Route zum Testen unserer TokenCache-Klasse. Erstellen Sie zuerst einen neuen Controller für unsere E-Mail-Ansicht. Erstellen Sie eine neue Datei im ./php-tutorial/app/Http/Controllers-Verzeichnis mit dem Namen OutlookController.php. Fügen Sie den folgenden Code hinzu.Before we move on, let's implement a very simple /mail route to test our TokenCache class. First, create a new controller for our mail view. Create a new file in the ./php-tutorial/app/Http/Controllers directory called OutlookController.php. Add the following code.

Inhalt der Datei ./php-tutorial/app/Http/Controllers/OutlookController.phpContents of the ./php-tutorial/app/Http/Controllers/OutlookController.php file

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class OutlookController extends Controller
{
  public function mail() 
  {
    if (session_status() == PHP_SESSION_NONE) {
      session_start();
    }

    $tokenCache = new \App\TokenStore\TokenCache;

    echo 'Token: '.$tokenCache->getAccessToken();
  }
}

Öffnen Sie die Datei ./php-tutorial/routes/web.php, und fügen Sie die folgende Zeile am Ende der Datei hinzu.Open the ./php-tutorial/routes/web.php file and add the following line at the bottom of the file.

Neuer Eintrag in ./php-tutorial/routes/web.phpNew entry in ./php-tutorial/routes/web.php

Route::get('/mail', 'OutlookController@mail')->name('mail');

Speichern Sie Ihre Änderungen, wechseln Sie zu http://localhost:8000, und melden Sie sich erneut an. Dieses Mal sollte die App Sie zu https://localhost:8000/mail weiterleiten und das Token anzeigen. Auf diese Weise wird sichergestellt, dass unser Tokencache auf allen Controllern funktioniert. Da wir nun ein Zugriffstoken haben und es bei Bedarf aktualisieren können, sind wir bereit zur Verwendung der Mail-API.Save your changes, browse to http://localhost:8000 and sign in again. This time, the app should redirect to https://localhost:8000/mail and display the token, verifying that our token cache is working across controllers. Now that we have an access token and we can refresh if needed, we're ready to use the Mail API.

Verwenden der Mail-APIUsing the Mail API

Wir verwenden das Microsoft Graph-SDK für PHP für alle Outlook-API-Aufrufe. Beginnen wir also mit der Installation.We're going to use the Microsoft Graph SDK for PHP to make all of our Outlook API Calls, so let's start by installing it.

Öffnen Sie die Datei ./php-tutorial/composer.json, und suchen Sie den require-Eintrag. Aktualisieren Sie diesen Eintrag so, dass "microsoft/microsoft-graph": "1.0.*" hinzugefügt wird, und speichern Sie die Datei.Open the ./php-tutorial/composer.json file and locate the require entry. Update this entry to add "microsoft/microsoft-graph": "1.0.*" and save the file.

Aktualisierter require-Eintrag in ./php-tutorial/composer.jsonUpdated require entry in ./php-tutorial/composer.json

"require": {
    "php": ">=5.6.4",
    "laravel/framework": "5.4.*",
    "laravel/tinker": "~1.0",
    "league/oauth2-client": "^2.0",
    "microsoft/microsoft-graph": "1.0.*"
},

Führen den folgenden Befehl an der Eingabeaufforderung/Shell im Verzeichnis php-tutorial aus.Run the following command from your command prompt/shell in the php-tutorial directory.

composer update

Jetzt werden wir die Funktion mail ändern.Now let's modify the mail function. Bei der ersten Verwendung des Graph SDK rufen wir den Benutzernamen ab, um so sicherzustellen, dass wir die Microsoft Graph-API aufrufen können.Our first use of the Graph SDK here will be to get the user's name, just to verify that we can call the Microsoft Graph API.

Fügen Sie die folgenden Zeilen nach der use App\Http\Controllers\Controller;-Zeile in OutlookController.php hinzu.Add the following lines just after the use App\Http\Controllers\Controller; line in OutlookController.php.

use Microsoft\Graph\Graph;
use Microsoft\Graph\Model;

Ersetzen Sie die vorhandene mail-Funktion durch den folgenden Code.Replace the existing mail function with the following code.

Aktualisierte mail-Funktion in ./php-tutorial/app/Http/Controllers/OutlookController.phpUpdated mail function in ./php-tutorial/app/Http/Controllers/OutlookController.php

public function mail() 
{
  if (session_status() == PHP_SESSION_NONE) {
    session_start();
  }

  $tokenCache = new \App\TokenStore\TokenCache;

  $graph = new Graph();
  $graph->setAccessToken($tokenCache->getAccessToken());

  $user = $graph->createRequest('GET', '/me')
                ->setReturnType(Model\User::class)
                ->execute();

  echo 'User: '.$user->getDisplayName();
}

Speichern Sie die Änderungen, und aktualisieren Sie die E-Mail-Ansicht.Save your changes and refresh the mail view. Der Name des authentifizierten Benutzers sollte angezeigt werden.You should see the authenticated user's name. (Wenn nicht, fangen Sie von vorne bei http://localhost:8000 an, und melden Sie sich erneut an.)(If not, start over at http://localhost:8000 and login again.)

Fügen wir nun Code zum Abrufen der Nachrichten des Benutzers hinzu. Ersetzen Sie die vorhandene mail-Funktion durch Folgendes.Now let's add code to retrieve the user's messages. Replace the existing mail function with the following.

Aktualisierte mail-Funktion in ./php-tutorial/app/Http/Controllers/OutlookController.phpUpdated mail function in ./php-tutorial/app/Http/Controllers/OutlookController.php

public function mail() 
{
  if (session_status() == PHP_SESSION_NONE) {
    session_start();
  }

  $tokenCache = new \App\TokenStore\TokenCache;

  $graph = new Graph();
  $graph->setAccessToken($tokenCache->getAccessToken());

  $user = $graph->createRequest('GET', '/me')
                ->setReturnType(Model\User::class)
                ->execute();

  echo 'User: '.$user->getDisplayName().'<br/>';

  $messageQueryParams = array (
    // Only return Subject, ReceivedDateTime, and From fields
    "\$select" => "subject,receivedDateTime,from",
    // Sort by ReceivedDateTime, newest first
    "\$orderby" => "receivedDateTime DESC",
    // Return at most 10 results
    "\$top" => "10"
  );

  $getMessagesUrl = '/me/mailfolders/inbox/messages?'.http_build_query($messageQueryParams);
  $messages = $graph->createRequest('GET', $getMessagesUrl)
                    ->setReturnType(Model\Message::class)
                    ->execute();

  foreach($messages as $msg) {
    echo 'Message: '.$msg->getSubject().'<br/>';
  }
}

Zusammenfassung des neuen Codes in der mail-Funktion:To summarize the new code in the mail function:

  • Es wird ein Graph-Clientobjekt erstellt und initialisiert, um das an die Funktion übergebene Zugriffstoken zu verwenden.It creates a Graph client object and initializes it to use the access token passed to the function.
  • Die /me/mailfolders/inbox/messages-API wird aufgerufen, um die Posteingangsnachrichten abzurufen, und es werden weitere Methoden zum Steuern der Anforderung verwendet:It calls the /me/mailfolders/inbox/messages API to get inbox messages, and uses other methods to control the request:
    • Die top-Methode wird mit dem Wert 10 verwendet, um die Ergebnisse auf die ersten 10 einzuschränken.It uses the top method with a value of 10 to limit the results to the first 10.
    • Die select-Methode wird verwendet, um nur die Eigenschaften subject, from, receivedDateTime und isRead anzufordern.It uses the select method to only request the subject, from, receivedDateTime, and isRead properties.
    • Die orderby-Methode wird mit dem Wert receivedDateTime desc verwendet, um die neuesten Nachrichten zuerst abzurufen.It uses the orderby method with a value of receivedDateTime desc to get the newest messages first.
  • Er durchläuft die Ergebnisse und druckt den Betreff.It loops over the results and prints out the subject.

Wenn Sie die App jetzt neu starten, sollten Sie eine sehr einfache Auflistung des Ergebnis-Arrays erhalten. Wir fügen nun etwas HTML und PHP hinzu, um die Ergebnisse etwas ansprechender anzuzeigen.If you restart the app now, you should get a very rough listing of the results array. Let's add a little HTML and PHP to display the results in a nicer way.

Anzeigen der ErgebnisseDisplaying the results

Wir fügen unserer App eine einfache Anzeige zum Wiedergeben der Nachrichten hinzu. Erstellen Sie eine neue Datei im Ordner ./php-tutorial/resources/views mit dem Namen mail.blade.php, und fügen Sie den folgenden Code hinzu.We'll add a basic view to our app to render the messages. Create a new file in the ./php-tutorial/resources/views folder called mail.blade.php and add the following code.

Inhalt der Datei ./php-tutorial/resources/views/mail.blade.phpContents of the ./php-tutorial/resources/views/mail.blade.php file

@extends('layout')

@section('content')
<div id="inbox" class="panel panel-default">
  <div class="panel-heading">
    <h1 class="panel-title">Inbox</h1>
  </div>
  <div class="panel-body">
    Here are the 10 most recent messages in your inbox.
  </div>
  <div class="list-group">
    <?php if (isset($messages)) {
      foreach($messages as $message) { ?>
    <div class="list-group-item">
      <h3 class="list-group-item-heading"><?php echo $message->getSubject() ?></h3>
      <h4 class="list-group-item-heading"><?php echo $message->getFrom()->getEmailAddress()->getName() ?></h4>
      <p class="list-group-item-heading text-muted"><em>Received: <?php echo $message->getReceivedDateTime()->format(DATE_RFC2822) ?></em></p>
    </div>
    <?php  }
    } ?>
  </div>
</div>
@endsection

Aktualisieren Sie jetzt die mail -Funktion so, dass diese Ansicht zurückgegeben wird.Now update the mail function to return this view.

Aktualisierte mail-Funktion in ./php-tutorial/app/Http/Controllers/OutlookController.phpUpdated mail function in ./php-tutorial/app/Http/Controllers/OutlookController.php

public function mail() 
{
  if (session_status() == PHP_SESSION_NONE) {
    session_start();
  }

  $tokenCache = new \App\TokenStore\TokenCache;

  $graph = new Graph();
  $graph->setAccessToken($tokenCache->getAccessToken());

  $user = $graph->createRequest('GET', '/me')
                ->setReturnType(Model\User::class)
                ->execute();

  $messageQueryParams = array (
    // Only return Subject, ReceivedDateTime, and From fields
    "\$select" => "subject,receivedDateTime,from",
    // Sort by ReceivedDateTime, newest first
    "\$orderby" => "receivedDateTime DESC",
    // Return at most 10 results
    "\$top" => "10"
  );

  $getMessagesUrl = '/me/mailfolders/inbox/messages?'.http_build_query($messageQueryParams);
  $messages = $graph->createRequest('GET', $getMessagesUrl)
                    ->setReturnType(Model\Message::class)
                    ->execute();

  return view('mail', array(
    'username' => $user->getDisplayName(),
    'messages' => $messages
  ));
}

Speichern Sie die Änderungen, und aktualisieren Sie die E-Mail-Seite. Jetzt sollte eine ansprechende Liste von Nachrichten wiedergegeben werden.Save your changes and refresh the mail page. You should now get a nicely rendered list of messages.

Die fertige App, in der der Posteingang des Benutzers angezeigt wird.

Hinzufügen von Kalender- und Kontakte-APIsAdding Calendar and Contacts APIs

Da Sie nun das Aufrufen der Outlook-Mail-API gemeistert haben, dürfte es kein Problem mehr sein, das gleiche für Kalender- und Kontakte-APIs zu tun.Now that you've mastered calling the Outlook Mail API, doing the same for Calendar and Contacts APIs is similar and easy.

Tipp

Wenn Sie die Schritte in diesem Lernprogramm befolgt haben, haben Sie wahrscheinlich ein Zugriffstoken in Ihrem Sitzungscookie gespeichert. Dieses Token ist nur für den Mail.Read-Bereich gültig. Um die Kalender- oder Kontakte-API aufzurufen, müssen wir neue Bereiche hinzufügen. Starten Sie den Browser unbedingt neu, um das Sitzungscookie zu entfernen, damit Sie den Anmeldevorgang von vorne beginnen können, um ein neues Zugriffstoken zu erhalten.If you've followed along with the tutorial, you probably have an access token saved in your session cookie. That token will only be valid for the Mail.Read scope. In order to call the Calendar or Contacts API, we will need to add new scopes. Be sure to restart your browser to get rid of the session cookie so that you can start the login process from the beginning to get a new access token.

Für die Kalender-API:For Calendar API:

  1. Aktualisieren Sie den Wert OAUTH_SCOPES in .\php-tutorial\.env, um den Calendars.Read-Bereich einzuschließen.Update the OAUTH_SCOPES value in .\php-tutorial\.env to include the Calendars.Read scope.

    Hinweis

    Starten Sie den Entwicklungsserver unbedingt neu, nachdem Sie diese Datei geändert haben.Be sure to restart the development server after changing this file!

    OAUTH_SCOPES='openid profile offline_access User.Read Mail.Read Calendars.Read'
    
  2. Fügen Sie eine neue calendar-Funktion zur OutlookController-Klasse in ./php-tutorial/app/Http/Controllers/OutlookController.php hinzu.Add a new function calendar to the OutlookController class in ./php-tutorial/app/Http/Controllers/OutlookController.php.

    public function calendar() 
    {
      if (session_status() == PHP_SESSION_NONE) {
        session_start();
      }
    
      $tokenCache = new \App\TokenStore\TokenCache;
    
      $graph = new Graph();
      $graph->setAccessToken($tokenCache->getAccessToken());
    
      $user = $graph->createRequest('GET', '/me')
                    ->setReturnType(Model\User::class)
                    ->execute();
    
      $eventsQueryParams = array (
        // // Only return Subject, Start, and End fields
        "\$select" => "subject,start,end",
        // Sort by Start, oldest first
        "\$orderby" => "Start/DateTime",
        // Return at most 10 results
        "\$top" => "10"
      );
    
      $getEventsUrl = '/me/events?'.http_build_query($eventsQueryParams);
      $events = $graph->createRequest('GET', $getEventsUrl)
                      ->setReturnType(Model\Event::class)
                      ->execute();
    
      return view('calendar', array(
        'username' => $user->getDisplayName(),
        'events' => $events
      ));
    }
    
  3. Fügen Sie eine Route für /calendar zu ./php-tutorial/routes/web.php hinzu.Add a route for /calendar to ./php-tutorial/routes/web.php.

    Route::get('/calendar', 'OutlookController@calendar')->name('calendar');
    
  4. Fügen Sie eine neue Datei mit dem Namen calendar.blade.php zu ./php-tutorial/resources/views hinzu. Fügen Sie den folgenden Code hinzu.Add a new file called calendar.blade.php in ./php-tutorial/resources/views. Add the following code.

    @extends('layout')
    
    @section('content')
    <div id="inbox" class="panel panel-default">
      <div class="panel-heading">
        <h1 class="panel-title">Calendar</h1>
      </div>
      <div class="panel-body">
        Here are the 10 oldest events in your calendar.
      </div>
      <div class="list-group">
        <?php if (isset($events)) {
          foreach($events as $event) { ?>
        <div class="list-group-item">
          <h3 class="list-group-item-heading"><?php echo $event->getSubject() ?></h3>
          <p class="list-group-item-heading text-muted">Start: <?php echo (new DateTime($event->getStart()->getDateTime()))->format(DATE_RFC2822) ?></p>
          <p class="list-group-item-heading text-muted">End: <?php echo (new DateTime($event->getEnd()->getDateTime()))->format(DATE_RFC822) ?></p>
        </div>
        <?php  }
        } ?>
      </div>
    </div>
    @endsection
    
  5. Fügen Sie ein Navigationsleistenelement zu ./php-tutorial/resources/views/layout.blade.php direkt nach dem Eintrag für Posteingang hinzu.Add a nav bar item in ./php-tutorial/resources/views/layout.blade.php just after the entry for Inbox.

    <li class="<?php echo ($_SERVER['REQUEST_URI'] == '/calendar' ? 'active' : '');?>"><a href="/calendar">Calendar</a></li>
    
  6. Starten Sie die App neu. Nach der Anmeldung klicken Sie auf das Element Kalender in der Navigationsleiste.Restart the app. After signing in, click the Calendar item on the nav bar.

Für die Kontakte-API:For Contacts API:

  1. Aktualisieren Sie den Wert OAUTH_SCOPES in .\php-tutorial\.env, um den Contacts.Read-Bereich einzuschließen.Update the OAUTH_SCOPES value in .\php-tutorial\.env to include the Contacts.Read scope.

    Hinweis

    Starten Sie den Entwicklungsserver unbedingt neu, nachdem Sie diese Datei geändert haben.Be sure to restart the development server after changing this file!

    OAUTH_SCOPES='openid profile offline_access User.Read Mail.Read Contacts.Read'
    
  2. Fügen Sie eine neue contacts-Funktion zur OutlookController-Klasse in ./php-tutorial/app/Http/Controllers/OutlookController.php hinzu.Add a new function contacts to the OutlookController class in ./php-tutorial/app/Http/Controllers/OutlookController.php.

    public function contacts() 
    {
      if (session_status() == PHP_SESSION_NONE) {
        session_start();
      }
    
      $tokenCache = new \App\TokenStore\TokenCache;
    
      $graph = new Graph();
      $graph->setAccessToken($tokenCache->getAccessToken());
    
      $user = $graph->createRequest('GET', '/me')
                    ->setReturnType(Model\User::class)
                    ->execute();
    
      $contactsQueryParams = array (
        // // Only return givenName, surname, and emailAddresses fields
        "\$select" => "givenName,surname,emailAddresses",
        // Sort by given name
        "\$orderby" => "givenName ASC",
        // Return at most 10 results
        "\$top" => "10"
      );
    
      $getContactsUrl = '/me/contacts?'.http_build_query($contactsQueryParams);
      $contacts = $graph->createRequest('GET', $getContactsUrl)
                        ->setReturnType(Model\Contact::class)
                        ->execute();
    
      return view('contacts', array(
        'username' => $user->getDisplayName(),
        'contacts' => $contacts
      ));
    }
    
  3. Fügen Sie eine Route für /contacts zu ./php-tutorial/routes/web.php hinzu.Add a route for /contacts to ./php-tutorial/routes/web.php.

    Route::get('/contacts', 'OutlookController@contacts')->name('contacts');
    
  4. Fügen Sie eine neue Datei mit dem Namen contacts.blade.php zu ./php-tutorial/resources/views hinzu. Fügen Sie den folgenden Code hinzu.Add a new file called contacts.blade.php in ./php-tutorial/resources/views. Add the following code.

    @extends('layout')
    
    @section('content')
    <div id="inbox" class="panel panel-default">
      <div class="panel-heading">
        <h1 class="panel-title">Contacts</h1>
      </div>
      <div class="panel-body">
        Here are your first 10 contacts.
      </div>
      <div class="list-group">
        <?php if (isset($contacts)) {
          foreach($contacts as $contact) { ?>
        <div class="list-group-item">
          <h3 class="list-group-item-heading"><?php echo $contact->getGivenName().' '.$contact->getSurname() ?></h3>
          <p class="list-group-item-heading"><?php echo $contact->getEmailAddresses()[0]['address']?></p>
        </div>
        <?php  }
        } ?>
      </div>
    </div>
    @endsection
    
  5. Fügen Sie ein Navigationsleistenelement zu ./php-tutorial/resources/views/layout.blade.php direkt nach dem Eintrag für Posteingang hinzu.Add a nav bar item in ./php-tutorial/resources/views/layout.blade.php just after the entry for Inbox.

    <li class="<?php echo ($_SERVER['REQUEST_URI'] == '/contacts' ? 'active' : '');?>"><a href="/contacts">Contacts</a></li>
    
  6. Starten Sie die App neu. Nach der Anmeldung klicken Sie auf das Element Kontakte in der Navigationsleiste.Restart the app. After signing in, click the Contacts item on the nav bar.