web-dev-qa-db-fra.com

Google API Comment se connecter pour recevoir les valeurs d'un tableur

Je me suis lancé dans ce projet en pensant que ce serait simple. Bien des heures plus tard, je réalise que l'API Google est un peu un labyrinthe avec plusieurs API et bibliothèques. J'ai vraiment besoin d'instructions claires sur la façon de procéder.

J'ai créé plusieurs feuilles de calcul Google Doc que j'ai autorisées à modifier pour les autres utilisateurs.

Tout ce dont j'ai besoin est de récupérer par programmation les informations de ces feuilles de calcul à l'aide de PHP. Cependant, je n'arrive pas à comprendre comment se connecter pour démarrer la récupération.

Voici ce que j'ai fait jusqu'à présent:

1 - Installation des bibliothèques d'API Google PHP. 

2 - Création d'un projet Google API dans le même compte. Je ne sais pas de quelle API j'ai besoin ni de quelles clés oAuth.

3 - Installation du client Google API Spreadsheet à partir de https://github.com/asimlqt/php-google-spreadsheet-client

Et maintenant quoi? Comment puis-je envoyer la commande API pour récupérer la feuille de calcul souhaitée? Je ne sais pas comment s'authentifier et comment récupérer. Jusqu'à présent, j'ai essayé d'utiliser la clé de serveur API pour Google Drive ci-dessous. Il ne s'agissait que d'une supposition. J'ai copié et collé le texte ci-dessous à partir de l'exemple du client Google API Spreadsheet:

<?php
require_once 'php-google-spreadsheet-client-master\src\Google\Spreadsheet\Autoloader.php';

$accessToken = 'xxxxxxxxxxxxxxxxxxxxxxx';
$request = new Google\Spreadsheet\Request($accessToken);
$serviceRequest = new Google\Spreadsheet\DefaultServiceRequest($request);
Google\Spreadsheet\ServiceRequestFactory::setInstance($serviceRequest);


$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();
?>

Je reçois l'erreur suivante:

Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in C:\php\php-google-spreadsheet-client-master\src\Google\Spreadsheet\SpreadsheetFeed.php:43 Stack trace: #0 C:\php\php-google-spreadsheet-client-master\src\Google\Spreadsheet\SpreadsheetFeed.php(43): SimpleXMLElement->__construct('') #1 C:\php\php-google-spreadsheet-client-master\src\Google\Spreadsheet\SpreadsheetService.php(39): Google\Spreadsheet\SpreadsheetFeed->__construct(false) #2 C:\php\google_docd.php(11): Google\Spreadsheet\SpreadsheetService->getSpreadsheets() #3 {main} thrown in C:\php\php-google-spreadsheet-client-master\src\Google\Spreadsheet\SpreadsheetFeed.php on line 43  

S'il vous plaît s'il vous plaît. Instructions claires. Je suis un débutant dans l'API Google. Merci. Des exemples sur la façon de tester dans SOAPUI ou via bash seraient également utiles car je pourrai ensuite les utiliser pour comprendre comment envoyer une demande Curl. Merci beaucoup!

14
user2029890

J'ai finalement réussi à le faire fonctionner, malgré toutes les tentatives des documents pour le rendre impossible, voici ma configuration:

Vous devez créer les informations d'identification sur la console de l'API: https://console.developers.google.com/ Vous devez d'abord créer un projet et créer un ensemble d'informations authentifiées pour votre app: dans le menu de gauche, cliquez sur API & Auth, puis sur Credentials. Cliquez sur Créer un nouvel ID client (bouton rouge), puis sélectionnez Compte de service. Vous allez télécharger un fichier, protégez-le. vous allez le télécharger avec votre script.

De plus, veuillez noter que cela n’a jamais fonctionné que si: mon document était le «vieux tableur». J'avais également besoin de partager le classeur avec l'ID utilisateur (celui qui pouvait être un courrier électronique) généré sur la console de Google. Le document contient une ligne supérieure qui est gelée avec les colonnes appropriées nom (nom, âge). .

Voici le script php que j'ai utilisé en combinaison avec ce qui précède:

<?php
require_once 'php-google-spreadsheet/src/Google/Spreadsheet/Autoloader.php';
require_once 'google-api-php-client/src/Google_Client.php';

const G_CLIENT_ID       = 'fill_with_info_from_console.apps.googleusercontent.com';
const G_CLIENT_EMAIL    = '[email protected]';
const G_CLIENT_KEY_PATH = 'key/keep_the_complex_filename_here_privatekey.p12';
const G_CLIENT_KEY_PW   = 'notasecret';

$obj_client_auth  = new Google_Client ();
$obj_client_auth -> setApplicationName ('test_or_whatever_you_like');
$obj_client_auth -> setClientId (G_CLIENT_ID);
$obj_client_auth -> setAssertionCredentials (new Google_AssertionCredentials (
    G_CLIENT_EMAIL, 
    array('https://spreadsheets.google.com/feeds','https://docs.google.com/feeds'), 
    file_get_contents (G_CLIENT_KEY_PATH), 
    G_CLIENT_KEY_PW
));
$obj_client_auth -> getAuth () -> refreshTokenWithAssertion ();
$obj_token  = json_decode ($obj_client_auth -> getAccessToken ());
$accessToken = $obj_token->access_token;

$request = new Google\Spreadsheet\Request($accessToken);
$serviceRequest = new Google\Spreadsheet\DefaultServiceRequest($request);
Google\Spreadsheet\ServiceRequestFactory::setInstance($serviceRequest);
$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();
$spreadsheet = $spreadsheetFeed->getByTitle('title_of_the_spreadsheet_doc');
$worksheetFeed = $spreadsheet->getWorksheets();
$worksheet = $worksheetFeed->getByTitle('title_of_the_tab');
$listFeed = $worksheet->getListFeed();

// this bit below will create a new row, only if you have a frozen first row adequatly labelled

$row = array('name'=>'John', 'age'=>25);
$listFeed->insert($row);

?>

Je devrais aussi noter:

  • Tout ceci est encore un travail en cours, mais j'espère que cela aidera quelqu'un à écrire des instructions étonnantes pour que quiconque puisse mieux comprendre la réalité.

  • C’est une compilation de morceaux des deux documentations de Google, quelques réponses sur stackoverflow et des informations des 2 bibliothèques d’API

  • Cela a été terriblement douloureux de faire fonctionner cela et ce ne devrait vraiment pas être le cas; Je suppose que c’est parce que Google met en parallèle l’authentification, l’interface de la console et les versions de l’API en même temps.

  • EDIT: Il semble que les noms de colonnes dans le document Google soient restreints: aucun espace autorisé (?), Aucun trait de soulignement autorisé (?), CamelCase semble gênant. J'ai seulement réussi à faire fonctionner les tirets, comme dans "placement-autre", sinon l'api lance une "exception non capturée"

  • EDIT: J'ai utilisé exactement la même configuration pour un nouveau projet et fonctionne toujours, avec le nouveau modèle Spreadsheet introduit par Google récemment. Ce qui me tient que j'ai oublié: une cellule vide n'est pas autorisée, les en-têtes doivent être gelés sans espaces, et ils sont minuscules lorsqu'ils sont interrogés par PHP.

J'espère que cela t'aides!

18
jrgd

Cette réponse est censée être un complément à la réponse de jrgd, et je la poste ici, en tant que réponse, car elle contient du code. 

Les problèmes de connexion eux-mêmes m'ont suspendu. Voici ce que j’avais à faire pour résoudre ce problème: Essayer d’obtenir Google accessToken . De plus, le tableur doit également être partagé avec l’e-mail généré par Google que vous trouvez dans votre code. 

Aussi, jrgd, pour répondre à votre question sur cet objet Request: il n’existe pas avec l’API Google Spreadsheet;/* Je ne pouvais pas le trouver lorsque j'ai utilisé Composer pour télécharger la bibliothèque */ À la place, j'ai fini par faire ce que GingerDog a fait: 

$serviceRequest = new Google\Spreadsheet\DefaultServiceRequest($accessToken); Google\Spreadsheet\ServiceRequestFactory::setInstance($serviceRequest);

Il existe également une probabilité significative que le code génère une exception lors de l'utilisation de getSpreadsheets(), en raison du code d'erreur HTTP renvoyé supérieur à 300. La classe SpreadsheetService a cette méthode (voici son code: /** * Fetches a list of spreadhsheet spreadsheets from google drive. * * @return \Google\Spreadsheet\SpreadsheetFeed */ public function getSpreadsheets() { return new SpreadsheetFeed( ServiceRequestFactory::getInstance()->get('feeds/spreadsheets/private/full') ); } Notez qu'il existe une autre classe qui "effectue le sale travail ici": la classe DefaultServiceRequest. Voici la get() qui est en train d'être utilisé:

/**
     * Perform a get request
     * 
     * @param string $url
     * 
     * @return string
     */
    public function get($url)
    {
        $ch = $this->initRequest($url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
        return $this->execute($ch);
    }
    /**
     * Executes the api request.
     * 
     * @return string the xml response
     *
     * @throws \Google\Spreadsheet\Exception If the was a problem with the request.
     *                                       Will throw an exception if the response
     *                                       code is 300 or greater
     *                                       
     * @throws \Google\Spreadsheet\UnauthorizedException
     */
    protected function execute($ch)
    {
        $ret = curl_exec($ch);

        $info = curl_getinfo($ch);
        $httpCode = (int)$info['http_code'];

        if($httpCode > 299) {
            if($httpCode === 401) {
                throw new UnauthorizedException('Access token is invalid', 401);
            } else {
                throw new Exception('Error in Google Request', $info['http_code']);
            }
        }

        return $ret;
    }

Notez que la fonction, de son aide la plus interne, a une chance de renvoyer un http_code qui provoquera une exception du code. Pas bon pour les affaires. 

La solution

La solution que j’ai résolue consiste à modifier la ligne de code suivante: $spreadsheetFeed = $spreadsheetService->getSpreadsheets();

à cette boucle while: 

/* my way of "making" it work; // I just getSpreadsheets() until there stops being an exception thrown */
    $googleException = new Exception();
    while ($googleException != null)
    {
        try
        {
            $spreadsheetFeed = $spreadsheetService->getSpreadsheets();  # This line randomly throws exception, for some reason. 
            $googleException = null;
        }
        catch (Exception $e)
        {
            $googleException = $e;
        }
    }
    //var_dump($spreadsheetFeed->getArrayCopy());   // test line
1
Mike Warren

J'ai écrit une classe wrapper pour l'authentification Google Sheets et l'édition de cellules de feuille dans mon projet récent. Testé au 2 septembre 2015, il est donc très à jour!

Prérequis:

Pour utiliser la classe wrapper:

// Initialise Google Sheets instance
$sheets = new GoogleSheets();

$sheets->clientID      = 'YOUR CLIENT ID FROM GOOGLE DEV CONSOLE';
$sheets->clientEmail   = 'YOUR CLIENT EMAIL FROM GOOGLE DEV CONSOLE';
$sheets->clientKeyPath = 'PATH TO THE P12 FILE YOU DOWNLOADED FROM GOOGLE DEV CONSOLE';
$sheets->clientKeyPw   = 'IT IS USUALLY notasecret';

$sheets->appName          = 'WHATEVER NAME YOU WANT';
$sheets->spreadsheetTitle = 'TITLE FOR THE SPREADSHEET YOU WANT TO EDIT';
$sheets->worksheetTitle   = 'WORKSHEET TITLE IN THAT SPREADSHEET';

// Authenticate with Google
$sheets->authenticate();

// Now update the specific row cell
$sheets->updateListEntry(ROW_HEADER, $submissionID, CELL_HEADER, CELL_VALUE);
echo "updated!";

Et voici la classe wrapper - n'hésitez pas à la modifier - la majeure partie du code est à peu près standard, du code passe-partout. Testé de travail!

// Autoload classes thanks to Composer
require_once('vendor/autoload.php');

class GoogleSheets {
  // Instance variables
  public $clientID, $clientEmail, $clientKeyPath, $clientKeyPw, $appName, $spreadsheetTitle, $worksheetTitle;
  private $spreadsheetFeed;

  // connect to Google using OAuth2, boilerplate code...
  public function authenticate() {
    $obj_client_auth  = new Google_Client ();
    $obj_client_auth -> setApplicationName ($this->appName);
    $obj_client_auth -> setClientId ($this->clientID);
    $obj_client_auth -> setAssertionCredentials (new Google_Auth_AssertionCredentials (
        $this->clientEmail, 
        array('https://spreadsheets.google.com/feeds','https://docs.google.com/feeds'), 
        file_get_contents ($this->clientKeyPath), 
        $this->clientKeyPw
    ));
    $obj_client_auth -> getAuth () -> refreshTokenWithAssertion ();
    $obj_token  = json_decode ($obj_client_auth -> getAccessToken ());
    $accessToken = $obj_token->access_token;

    $serviceRequest = new Google\Spreadsheet\DefaultServiceRequest($accessToken);
    Google\Spreadsheet\ServiceRequestFactory::setInstance($serviceRequest);
    $spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
    $this->spreadsheetFeed = $spreadsheetService->getSpreadsheets();
}

// Find matching row with header $field and cell value $value, and update cell with header $cellHeader to $cellValue
public function updateListEntry($field, $value, $cellHeader, $cellValue) {
    // Get the required spreadsheet, then worksheet by title
    $spreadsheet = $this->spreadsheetFeed->getByTitle($this->spreadsheetTitle);
    $worksheetFeed = $spreadsheet->getWorksheets();
    $worksheet = $worksheetFeed->getByTitle($this->worksheetTitle);

    // sq stands for structured query
    $listFeed = $worksheet->getListFeed(array("sq" => $field . " = " . $value));
    $entries = $listFeed->getEntries();
    $listEntry = $entries[0];

    $values = $listEntry->getValues();
    $values[$cellHeader] = $cellValue;
    $listEntry->update($values);
}

}

1
zrll2