1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PHP8.2.0にて、スプレッドシートの読み込みと書き込み時のエラー解決方法

Last updated at Posted at 2023-04-06

PHP8.2.0を使用してスプレッドシートの読み込み、書き込みを行う方法
何かの手順通りにやってみたところエラーが出て困ったので、解決方法を残しておきます

実行環境

windows10のxamppのlocalhost内に配置したphpファイルを、コマンドプロンプトから実行

php6.PNG

読み込み、書き込みに使用した実際のソースコード


require_once __DIR__ . '/vendor/autoload.php';

$key =  __DIR__ . '/API_KEY/independent-bay-xxxxxxxxxxx自分のファイルパスに書き換えてください。私はAPI_KEYフォルダの中に入れたので、こういうパスになっていますxxxxxxxxxxxxx.json';//取得したサービスキーのパスを指定

$client = new Google_Client();//Googleクライアントインスタンスを作成
$client->setScopes([//スコープを以下の内容でセット
    \Google_Service_Sheets::SPREADSHEETS,
    \Google_Service_Sheets::DRIVE,]);
$client->setAuthConfig($key);//サービスキーをセット

$sheet = new Google_Service_Sheets($client);//シートを操作するインスタンス
$sheet_id = 'xxxxxxxxxxx自分のスプレッドシートIDに書き換えてくださいxxxxxxxxxxxxxxxx';//対象のスプレッドシートのIDを指定

//取得範囲を指定(書き方: シート名+ビックリマーク+範囲の左上のセル+コロン+範囲の右下のセル)(data!A1:C3と書くと、dataというシートのセルA1~C3を指定したことになる)
//※自分のシート名と範囲に書き換えてください。私はシートの名前を「Sheet_spleadAPI」なので下記のようになっています。
$range = 'Sheet_spleadAPI!A1:C3';

//多分スプレッドシートにアクセスしている
$response = $sheet->spreadsheets_values->get($sheet_id, $range);

//返ってきたresponseから、セルの値(配列)を取得して、変数に格納
$values = $response->getValues();//帰ってきたresponseから値を取得

//取得したセルの値(配列)を表示してみる
print_r($values);

/*
print_r($values); の結果は下記のようにコマンドプロンプトに表示された。
※スプレッドシートには事前に"b"を書いて置いた

Array
(
    [0] => Array
        (
            [0] => b
            [1] => b
            [2] => b
        )

    [1] => Array
        (
            [0] => b
            [1] => b
            [2] => b
        )

    [2] => Array
        (
            [0] => b
            [1] => b
            [2] => b
        )

)
*/


//書き込み範囲を指定(書き方: シート名+ビックリマーク+範囲の左上のセル+コロン+範囲の右下のセル)(data!A1:C3と書くと、dataというシートのセルA1~C3を指定したことになる)
//必ず、書き込む内容の配列と同じ形にする。今回は2行3列のデータを書き込むので、A6:C7(2行3列)を指定している
$range = 'Sheet_spleadAPI!A6:C7';

//書き込む内容を配列にて指定指定
$values = [
    ["jog","dio","audi"],
    ["jog","dio","audi"]
    ];


//書き込む内容を収めた配列をbodyに格納
$body = new Google_Service_Sheets_ValueRange(['values' => $values]);

/*
 いよいよシートの該当範囲に書き込む内容を反映します。
 ValueInputOptionは値を書き込む際の形式指定で、
 「RAWS」、もしくは「USER_ENTERED」のいずれかで指定します。
 特にこだわりがない場合は「USER_ENTERED」で問題ありません。 (との事。)
*/
$sheet->spreadsheets_values->update($sheet_id, $range, $body, ["valueInputOption" => 'USER_ENTERED']);

下準備

Google Sheets APIを利用する準備

PHPでスプレッドシートの読み書きを行う場合、Google Sheets APIを使用することが一般的です。Google Sheets APIを使用するには、vendorをインストールする必要があるらしいので、
windows コマンドプロンプトにて、"phpファイルを置いてあるディレクトリに移動した後"、下記コマンドを実行する。
すると当該ディレクトリにvendorフォルダが作成される。(その中には沢山のphpファイル(API)が入っていました。)

composer require google/apiclient:"^2.0"

スプレッドシートにアクセスするためのAPIを有効化して、認証情報(.jsonファイル)をダウンロードしておく

下記記事にAPIの有効化方法と、認証情報(.jsonファイル)のダウンロード方法が書いてあります
https://sterfield.co.jp/programmer/google%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92php%E3%81%A7%E5%8F%96%E5%BE%97/

ダウンロードしたjsonファイルは、任意の場所に保存しておきましょう。
私はphpファイルと同じ階層に「API_KEY」というフォルダを作り、その中に入れました。
このjsonファイルのパスは、phpファイルに記述してください。

スプレッドシートの共有で(APIを利用するサービスアカウント? ※すみませんこのあたりはあまり理解していない)を招待する。

ダウンロードした認証情報(.jsonファイル)をテキストエディタで開くと、下記のようなメールアドレスがあります。
●●●●●●●●●@independent-bay-●●●●●●.iam.gserviceaccount.com
スプレッドシートを開いて、右上の「共有」を押して、[ユーザーやグループを追加]という入力フォームにメールアドレスを入れて、「編集者」を選択して、「送信」を押下。これだけでOK。
※メールを開いてクリックとかそういうのはいらない。「送信」を押すだけで、共有された事になりました

エラー解決方法

スプレッドシート書き込み時のエラー

PHP Fatal error:  Uncaught TypeError: implode(): Argument #2 ($array) must be of type ?array, string given in C:\xampp\htdocs\youtube_live\php_spleadSheetAPI_test\vendor\google\apiclient\src\Google\Service\Resource.php:295

原因は、PHPの純正のimplode()メソッドの仕様変更によるものらしい。
下記サイトによると、引数の順番が変更になっている。
https://www.php.net/manual/ja/function.implode.php

//▼古い書き方。(エラーになる書き方)
implode(配列,文字列)
//▼新しい書き方
implode(文字列, 配列)

上記を直す為に、インストールしたvendor内にある下記のphpファイルを、下記のように書き換えます

▼書き換え前

vendor\google\apiclient\src\Google\Service\Resource.php 290行目あたり
    if (count($queryVars)) {
      $requestUrl .= '?' . implode($queryVars, '&');
    }

▼書き換え後。以下のように修正すると、エラーが無くなり、スプレッドシートに書き込みが出来た。

修正内容:implode関数に渡されている引数の順番を逆にした。$queryVarsは配列だったので、第二引数に持ってきた。

vendor\google\apiclient\src\Google\Service\Resource.php
    if (count($queryVars)) {
      $requestUrl .= '?' . implode('&', $queryVars);
    }

スプレッドシート読み込みする時に出るエラー

Fatal error: Uncaught TypeError: count():

これを解消する方法は下記です。インストールしたvendor内にある下記のphpファイルを書き換えます

vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php 64行目あたり
    public function release(EasyHandle $easy)
    {
        $resource = $easy->handle;
        unset($easy->handle);
        //以下の1行をコメントアウトしました。
        //if (count($this->handles) >= $this->maxHandles) {
        //以下の1行を追加しました
        if(count((array)$this-> handles) >= $this-> maxHandles){
            curl_close($resource);
        } else {
            // Remove all callback functions as they can hold onto references
            // and are not cleaned up by curl_reset. Using curl_setopt_array
            // does not work for some reason, so removing each one
            // individually.
            curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
            curl_setopt($resource, CURLOPT_READFUNCTION, null);
            curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
            curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
            curl_reset($resource);
            $this->handles[] = $resource;
        }
    }

(参考ページ:https://qiita.com/Takahiro_Inoway/items/fb2c847a23e7ff039840)

まとめ

上記2つのphpファイルを修正した事により、
PHPにてスプレッドシートのとある範囲の読み込みと、
PHPにてスプレッドシートのとある範囲への書き込みが出来ました。

▼PHPプログラム実行前のスプレッドシートの状態(読み込み予定のセルに ひらがな を入れておきました)
1.PNG

▼PHPプログラム実行後のコンソールの状態(スプレッドシートの値を読み込む事に成功している)
2.PNG

▼PHPプログラム実行後のスプレッドシートの状態(A6:C7の範囲への書き込みに成功している)
3.PNG

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?