GoogleApi+ Spreadsheet + PHP : Практика маленьких и полезных клиенту скриптов

Часто бывает, что ручная работа может занять недели, а программист — за день автоматизировать ее и сделать приятной. С наличием кучи библиотек в репозиториях гитхаба — важно выбрать нужную и рабочую. И правильно постучать молотком

Постановка задачи этого примера: клиент сделал огромную таблицу в гугл-документах, но забыл туда вставить важное поле (и приложил в письме еще большую таблицу со связкой «код товара» — «поле»). Клиенту приятно, мне не долго — все счастливы и веселы.

Авторизация

Зарегистрируем наше приложение (или даже возьмем одно из старых — нам по сути нужны только разрешения на «локальных» хост. Нам даже кода писать не нужно — целевая библиотека — https://github.com/google/google-api-php-client (хотя для крупных проектов я люблю все контролировать и не очень использую чужие приблуды)

google
<?php
session_start();
require 'vendor/autoload.php';
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'];
$client = new Google_Client();
$client->setClientId("9чтототам.apps.googleusercontent.com");
$client->setClientSecret("Hчтототамеще");
$client->setRedirectUri($redirect_uri);
$client->setScopes(array('email', 'https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive.file'));
 
if (isset($_REQUEST['logout'])) {
	unset($_SESSION['id_token_token']);
}
if (isset($_GET['code'])) {
	$token = $client->authenticate($_GET['code']);
	$_SESSION['id_token_token'] = $token;
	header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
if (@$_SESSION['id_token_token']) {
	$client->setAccessToken($_SESSION['id_token_token']);
	$token_data = json_decode($_SESSION['id_token_token'], true);
} else {
	$authUrl = $client->createAuthUrl();
	?>
	<div>
		<a href='<?= $authUrl ?>'>Connect Me!</a>
	</div>
	<?php
	exit;
}
?>
<div>
	<a href='?logout=1'>Logout</a>
</div>
//и дальше что угодно делаем с ключем

Получение нашего документа

Документация позволяет строить прямые запросы, но мы же хотим красиво и недолго делать задачу. Поэтому возьмем тоже готовое решение https://github.com/asimlqt/php-google-spreadsheet-client. Не без приключений, но оно вполне нам подойдет. Собственно эта заметка о приключениях

Например приключение номер один — в доках забыли указать что тип токена тоже нужен (по дефолту — это никак не Bearer, а нужен именно он)

use Google\Spreadsheet\DefaultServiceRequest;
use Google\Spreadsheet\ServiceRequestFactory;
ServiceRequestFactory::setInstance(new DefaultServiceRequest($token_data['access_token'], $token_data['token_type']));

Приключение номер два — кстати описанное в инете, но так и не решенное создателем либы —
Fatal error: Uncaught exception ‘Exception’ with message ‘String could not be parsed as XML’ in D:\NEWCORE\mz.loc\vendor\asimlqt\php-google-spreadsheet-client\src\Google\Spreadsheet\SpreadsheetService.php on line 55

Для того чтобы это убрать в классе DefaultServiceRequest отключите CURLOPT_SSL_VERIFYPEER — иначе приходит пустой ответ, он собственно и генерирует такую ошибку

$curlParams = array (
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_FAILONERROR => false,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_VERBOSE => false,
        );

Собственно работа с таблицей

Тут уже код с привязкой к специфике задачи — но общая суть достаточно проста, мы сравниваем по upc данные из таблицы в гугл-доках с полученными из текстовой таблицы (массив $parsed). И небольшой «лог» поиска и замен.

$spread = (new Google\Spreadsheet\SpreadsheetService())->getSpreadsheetById('номер из пути к файлу');
$works  = $spread->getWorksheets();
$indexes = array(0, 3); //у нас в задаче только нулевой и третий лист были нужны
echo '<table><tr><td>Status</td><td>UPC</td><td>Google</td><td>CSV</td><td>Date</td></tr>';
foreach($indexes AS $i) {
	$list = $works[$i]->getListFeed(); //взяли лист
	foreach ($list->getEntries() as $entry) { //взяли строку
		$values = $entry->getValues(); //взяли значения
		$upc = upc($values['upc']); //сделали нормализацию колонки
		if ($upc && isset($parsed[$upc])) {
			if ($values['date'] != $parsed[$upc]['date']) {
				$values['date'] = $parsed[$upc]['date'];
				$entry->update($values); //обновление данных в колонке по новым
			}
			echo '<tr style="color:green"><td>updated</td><td>' . $upc . '</td><td>' . $values['title'] . '</td><td>'
				. $parsed[$upc]['title'] . '</td><td>' . $parsed[$upc]['date']
				. '</td></tr>';
		} else {
			echo '<tr style="color:orange"><td>not found in csv</td><td>' . $upc . '</td><td>' . $values['title'] . '</td><td>&nbsp;</td><td>&nbsp;</td></tr>';
		}
	}
}

Оставить комментарий

XHTML: Вы можете использовать такие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">