我开始这个项目时认为它很简单。几个小时后,我意识到Google API有点像迷宫,有多个API和库。我真的需要请你为如何做这件事指明方向。
我创建了几个谷歌文档电子表格,并授予其他用户编辑权限。
我所需要的只是使用PHP以编程方式从这些电子表格中检索信息。然而,我甚至不知道如何连接才能开始检索。
以下是我迄今为止所做的:
1-安装了Google PHP API库。
2-在同一个帐户中创建了一个Google API项目。我不知道我需要哪个API和我需要哪个oAuth密钥。
3-从安装Google API电子表格客户端https://github.com/asimlqt/php-google-spreadsheet-client.
好吧,现在怎么办?如何发送API命令来检索所需的电子表格。我不确定如何进行身份验证和检索。到目前为止,我使用Google Drive的API服务器密钥尝试了以下操作。。。。这只是猜测。我从Google API电子表格客户端的示例中复制并粘贴了以下内容:
<?php
require_once 'php-google-spreadsheet-client-mastersrcGoogleSpreadsheetAutoloader.php';
$accessToken = 'xxxxxxxxxxxxxxxxxxxxxxx';
$request = new GoogleSpreadsheetRequest($accessToken);
$serviceRequest = new GoogleSpreadsheetDefaultServiceRequest($request);
GoogleSpreadsheetServiceRequestFactory::setInstance($serviceRequest);
$spreadsheetService = new GoogleSpreadsheetSpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();
?>
我收到以下错误:
Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in C:phpphp-google-spreadsheet-client-mastersrcGoogleSpreadsheetSpreadsheetFeed.php:43 Stack trace: #0 C:phpphp-google-spreadsheet-client-mastersrcGoogleSpreadsheetSpreadsheetFeed.php(43): SimpleXMLElement->__construct('') #1 C:phpphp-google-spreadsheet-client-mastersrcGoogleSpreadsheetSpreadsheetService.php(39): GoogleSpreadsheetSpreadsheetFeed->__construct(false) #2 C:phpgoogle_docd.php(11): GoogleSpreadsheetSpreadsheetService->getSpreadsheets() #3 {main} thrown in C:phpphp-google-spreadsheet-client-mastersrcGoogleSpreadsheetSpreadsheetFeed.php on line 43
求你了,求你了。清晰的说明。我是一个完全的谷歌API新手。谢谢关于如何在SOAPUI中或通过bash进行测试的示例也会很有帮助,因为我可以使用这些示例来了解如何发出Curl请求。非常感谢!
尽管文档试图让它看起来不可能,但我终于让它工作了,下面是我的设置:
- 用于OAuth2 php-lib的谷歌api;此处:https://code.google.com/p/google-api-php-client/
- 谷歌电子表格api php-lib;此处:https://github.com/asimlqt/php-google-spreadsheet-client
您需要在API控制台上创建凭据:https://console.developers.google.com/在那里,你需要首先创建一个项目,并为你的应用程序创建一组经过验证的信息:在左侧菜单中,点击API&Auth,然后是Credentials。单击创建新客户端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 GoogleSpreadsheetRequest($accessToken);
$serviceRequest = new GoogleSpreadsheetDefaultServiceRequest($request);
GoogleSpreadsheetServiceRequestFactory::setInstance($serviceRequest);
$spreadsheetService = new GoogleSpreadsheetSpreadsheetService();
$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上的一些答案和来自两个api库的信息的汇编
这是一个非常痛苦的工作,它真的不应该;我认为这是因为谷歌正在同时转换身份验证、控制台界面和api版本。
编辑:谷歌文档中的列名似乎受到了限制:不允许有空格(?),不允许有下划线(?)。CamelCase似乎很麻烦。我只是设法让破折号发挥作用,就像在"放置其他"中一样,否则api会抛出一些"未捕获的异常">
编辑:我在一个新项目中使用了完全相同的设置,现在仍然有效,谷歌最近推出了新的电子表格模型。让我印象深刻的是,我已经忘记了:不允许空白单元格,必须在没有空格的情况下冻结标题,并且从PHP查询时它们是小写的。
希望这能有所帮助!
这个答案是jrgd答案的附加组件,我把它作为答案发布在这里,因为它包含代码。
连接问题本身就把我挂断了。以下是我必须解决的问题:尝试获取Google accessToken。此外,电子表格必须与您在代码中找到的谷歌生成的电子邮件共享。
另外,jrgd,回答您关于Request
对象的问题:它不存在于Google电子表格API中;/*当我使用Composer下载库时找不到它*/相反,我最终做了GingerDog做的事:
$serviceRequest = new GoogleSpreadsheetDefaultServiceRequest($accessToken);
GoogleSpreadsheetServiceRequestFactory::setInstance($serviceRequest);
在使用getSpreadsheets()
时,由于返回的HTTP错误代码高于300,代码引发异常的可能性也很大。SpreadsheetService
类具有该方法(以下是其代码:/**
* Fetches a list of spreadhsheet spreadsheets from google drive.
*
* @return GoogleSpreadsheetSpreadsheetFeed
*/
public function getSpreadsheets()
{
return new SpreadsheetFeed(
ServiceRequestFactory::getInstance()->get('feeds/spreadsheets/private/full')
);
}
请注意,还有另一个类"在这里做脏活":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 GoogleSpreadsheetException If the was a problem with the request.
* Will throw an exception if the response
* code is 300 or greater
*
* @throws GoogleSpreadsheetUnauthorizedException
*/
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
我在最近的项目中为Google Sheets身份验证和表单单元格编辑编写了一个包装类。测试工作截止2015年9月2日,所以它是最新的!
先决条件:
- 准备好你的Google开发者密钥等(这是一篇关于如何获得API密钥等的优秀和最新文章。-http://konstantinshkut.com/blog/2014/11/01/how_to_get_data_from_google_spreadsheet_in_yii_php_application)
- 下载并安装Composer,这是两个必要的库googleapi php客户端和php-google电子表格客户端所必需的
- 使用Composer安装上述两个库;这是让库工作的推荐方法
使用包装类:
// 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 GoogleSpreadsheetDefaultServiceRequest($accessToken);
GoogleSpreadsheetServiceRequestFactory::setInstance($serviceRequest);
$spreadsheetService = new GoogleSpreadsheetSpreadsheetService();
$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);
}
}