我开始研究这个项目,认为这很简单。几个小时后,我意识到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请求。非常感谢!
答案 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);
}
}