Google API如何连接以从电子表格接收值

时间:2014-01-31 00:28:54

标签: php google-api google-sheets

我开始研究这个项目,认为这很简单。几个小时后,我意识到Google API有点迷宫,有多个API和库。我真的需要明确指示如何去做这件事。

我创建了几个Google Doc电子表格,我已授予其他用户编辑权限。

我只需要使用PHP以编程方式从这些电子表格中检索信息。但是,我无法弄清楚如何连接甚至开始检索。

这是我到目前为止所做的:

1 - 安装了Google PHP API库。

2 - 在同一帐户中创建了一个Google API项目。我不知道我需要哪种API以及我需要哪些oAuth密钥。

3 - 从https://github.com/asimlqt/php-google-spreadsheet-client安装了Google API电子表格客户端。

嗯,现在怎样?如何发送API命令以检索我想要的电子表格。我不确定如何验证以及如何检索。到目前为止,我使用API​​驱动程序的API服务器密钥尝试了以下....这只是一个猜测。我在Google API电子表格客户端中复制并粘贴了以下示例:

<?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();
?>

我收到以下错误:

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  

拜托,拜托。明确说明。我是一个完整的Google API新手。谢谢。关于如何在SOAPUI中或通过bash进行测试的示例也会有所帮助,因为我可以使用它来弄清楚如何发出Curl请求。非常感谢!

3 个答案:

答案 0 :(得分:18)

我终于让它工作了,尽管文件中的所有尝试都让它看起来不可能,这是我的设置:

您需要在API控制台上创建凭据:https://console.developers.google.com/ 在那里,您需要首先创建一个项目并为您的应用创建一组身份验证信息:在左侧菜单中,单击API&amp; Auth,然后是凭据。单击“创建新客户端ID”(红色按钮),然后选择“服务帐户”。您将下载文件,确保安全。你将用你的剧本上传它。

另外,请注意:除非:我的文档是“旧电子表格”,否则它永远不会有效。我还需要与Google控制台上生成的用户ID(可能是电子邮件的用户ID)共享电子表格文档。 该文档包含一个使用适当的列名称(名称,年龄)冻结的顶行。

这是我与上面结合使用的php脚本:

<?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    = 'fill_with_info_from_console@developer.gserviceaccount.com';
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);

?>

我还应该注意:

  • 所有这些仍在进行中,但希望有助于某人为任何人写出惊人的指示,以便更好地理解细节

  • 这是来自谷歌文档的点点滴滴的汇编,有关stackoverflow的一些答案和来自2个api库的信息

  • 让这个工作变得非常痛苦,它确实不应该;我假设这是因为谷歌正在同时转换身份验证,控制台界面和api版本。

  • 编辑:似乎谷歌文档中的列名称受到限制:不允许空格(?),不允许下划线(?),CamelCase似乎很麻烦。我只是设法让破折号起作用,比如“放置 - 其他”,否则api抛出一些“未捕获的异常”

  • 编辑:我使用完全相同的设置进行新项目仍然有效,最近Google推出了新的电子表格模型。是什么让我忘记了:不允许空白单元格,标题必须在没有空格的情况下冻结,从PHP查询时它们是小写的。

希望这有帮助!

答案 1 :(得分:1)

这个答案是jrgd的回答的补充,我在这里发布,作为答案,因为它包含代码。

连接问题本身让我感到困惑。以下是我必须采取的措施来解决这个问题:Trying to Get Google accessToken。 此外,电子表格必须与您在代码中找到的Google生成的电子邮件共享。

另外,jrgd,回答有关该Request个对象的问题:它与Google电子表格API不存在; / *当我使用Composer下载库时我无法找到它* / 相反,我最终做了GingerDog做的事情:

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

由于返回的HTTP错误代码高于300,因此使用getSpreadsheets()时代码抛出异常的可能性也很大。 SpreadsheetService类有该方法(这是它的代码: /** * 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') ); } 请注意,还有另一个类在这里进行肮脏的工作&#34;:DefaultServiceRequest类。以下是正在使用的get()

/**
     * 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;
    }

请注意,该函数从其最内层的帮助程序中有机会返回http_code,这将导致代码抛出异常。对商业不利。

解决方案

我纠正的方法是更改​​以下代码行: $spreadsheetFeed = $spreadsheetService->getSpreadsheets();

到这个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

答案 2 :(得分:1)

我在最近的项目中为Google表格身份验证和表格单元格编辑编写了一个包装类。测试工作截至2015年9月2日,所以它是最新的!

<强>先决条件:

使用包装类:

// 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!";

这里是包装类 - 随意修改它 - 大多数代码都是非常标准的样板代码。经过测试工作!

// 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);
}

}

相关问题