takaya030の備忘録

PHP、Laravel、Docker などの話がメインです

Windows + VirtualBox + docker-machine 環境のアップデート

Windows 上に構築した Docker 環境のアップデート手順のメモ

検証環境

Windows10 Home Edition
VirtualBox 5.1.22
Git for Windows 2.9.3
Docker version 17.05.0-ce, build 89658be
docker-machine version 0.6.0, build e27fb87

アップデートの方針

Docker Toolbox を使用すれば VirtualBox、msysgit も同時にインストールされますが、必ずしも最新版がインストールされるとは限らないため、個別にインストールする

VirtualBox のアップデート

こちらのサイトから最新版インストーラをダウンロードします
上書きインストールで OK です
Oracle VM VirtualBox

Git for Windows (msysgit) のアップデート

こちらのサイトから最新版インストーラをダウンロードします
上書きインストールで OK です
git-for-windows.github.io

Docker Toolbox のアップデート

こちらのサイトから最新版インストーラをダウンロードします
www.docker.com
VirtualBox と Git for Windows のチェックは外してインストールします
f:id:takaya030:20171119233839p:plain

Docker ホストのアップデート

必要に応じて Docker ホスト(CoreOS) のアップデートを実行します

$ docker-machine start default
Starting "default"...
(default) Check network to re-create if needed...
(default) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
(default) Waiting for an IP...
Machine "default" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
default   -        virtualbox   Running   tcp://192.168.99.100:2376           v17.05.0-ce

$ docker-machine upgrade default
Waiting for SSH to be available...
Detecting the provisioner...
Upgrading docker...
Stopping machine to do the upgrade...
Upgrading machine "default"...
Default Boot2Docker ISO is out-of-date, downloading the latest release...
Latest release for github.com/boot2docker/boot2docker is v17.10.0-ce
Downloading C:\Users\takaya030\.docker\machine\cache\boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v17.10.0-ce/boot2docker.iso...
0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100%
Copying C:\Users\takaya030\.docker\machine\cache\boot2docker.iso to C:\Users\takaya030\.docker\machine\machines\default\boot2docker.iso...
Starting machine back up...
(default) Check network to re-create if needed...
(default) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
(default) Waiting for an IP...
Restarting docker...

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v17.10.0-ce

アップデート結果

自分の環境では下記の通りにアップデートされました

VirtualBox 5.1.30

$ git version
git version 2.15.0.windows.1

$ docker -v
Docker version 17.10.0-ce, build f4ffd25

$ docker-machine -v
docker-machine.exe version 0.13.0, build 9ba6da9

参考サイト

takaya030.hatenablog.com

GAE/Go + Echo でセッションを使う

Google App Engine for Go (GAE/Go) で動作している Echo の環境でセッションを使用する手順メモ

検証環境

Windows10 Home Edition
VirtualBox 5.1.22
Docker version 17.05.0-ce, build 89658be
docker-compose version 1.6.2, build 4d72027

GAE/Go, Echo 開発環境について

今回は下記サイトの手順で構築したものを使用します
takaya030.hatenablog.com

session パッケージについて

gorilla/sessions を GAE 対応させた下記パッケージを使用します
github.com

ディレクトリ構成

+---gaego
|   |   docker-compose.yml
|   |   
|   +---config
|   |   
|   +---data
|   |       Dockerfile
|   |   
|   +---glide
|   |       
|   +---sdk
|           Dockerfile
|            
+---logs
|    
+---www
    |       
    +---app
    |       app.yaml
    |       main.go
    |
    +---src
        |
        +---hello
                app.go
                app-engine.go
                app-standalone.go
                glide.yaml
                hello.go

各種ファイルの詳細

www/app/app.yaml

runtime: go
api_version: go1

handlers:
- url: /.*
  script: _go_app

www/app/main.go

package main

import (
	_ "hello"
)

func init() {
}

www/src/hello/app.go

package hello

var e = createMux()

www/src/hello/app-engine.go

// +build appengine

package hello

import (
    "github.com/labstack/echo"
    "github.com/labstack/echo/engine/standard"
    "net/http"
)

func createMux() *echo.Echo {
    e := echo.New()

    // note: we don't need to provide the middleware or static handlers, that's taken care of by the platform
    // app engine has it's own "main" wrapper - we just need to hook echo into the default handler
    s := standard.New("")
    s.SetHandler(e)
    http.Handle("/", s)

    return e
}

// main()は書かなくて良い

www/src/hello/app-standalone.go

// +build !appengine,!appenginevm

package hello

import (
    "github.com/labstack/echo"
    "github.com/labstack/echo/engine/standard"
    "github.com/labstack/echo/middleware"
)

// ログの設定や静的ファイルの場所指定などをしています
func createMux() *echo.Echo {
    e := echo.New()

    e.Use(middleware.Recover())
    e.Use(middleware.Logger())
    e.Use(middleware.Gzip())

    e.Use(middleware.Static("public"))

    return e
}

func main() {
    e.Run(standard.New(":8080"))
}

www/src/hello/glide.yaml

package: hello
import:
- package: github.com/labstack/echo
  version: v2.2.0
  subpackages:
  - engine/standard
  - middleware
- package: github.com/rs/cors
- package: github.com/gorilla/sessions
- package: github.com/gorilla/context
- package: github.com/dsoprea/goappenginesessioncascade
- package: github.com/dsoprea/go-logging

www/src/hello/hello.go

package hello

import (
    "net/http"
    "strconv"

    "github.com/labstack/echo"
    "github.com/labstack/echo/engine/standard"
    "github.com/rs/cors"

    "github.com/dsoprea/goappenginesessioncascade"
)

const (
    sessionName = "MainSession"
)

var (
    sessionSecret = []byte("SessionSecret")
    sessionStore = cascadestore.NewCascadeStore(cascadestore.DistributedBackends, sessionSecret)
)

func init() {

    g := e.Group("/hello")
    g.Use(standard.WrapMiddleware(cors.Default().Handler))

    g.GET("", getWorld)
}


// hello world

func getWorld(c echo.Context) error {

    w := c.Response().(*standard.Response).ResponseWriter
    r := c.Request().(*standard.Request).Request

    var foo int
    if sess, err := sessionStore.Get(r, sessionName); err != nil {
        panic(err)
    } else {

        if val, found := sess.Values["foo"]; found == false {
            foo = 0
        } else {
            foo = val.(int) + 1
        }

        sess.Values["foo"] = foo
        if err := sess.Save(r, w); err != nil {
            panic(err)
        }
    }

    return c.String(http.StatusOK, "Hello, World! foo is " + strconv.Itoa(foo))
}

glide によるパッケージインストール

$ cd gaego
$ docker-compose run --rm sdk /bin/bash -c "cd src/hello;glide up"

動作確認

以下のコマンドで開発用サーバーが起動します

$ docker-compose up -d

web ブラウザで http://192.168.99.100:8080/hello にアクセスして以下のような文字列が表示されれば成功です

Hello, World! foo is 0

"foo is" の数値はセッションに保存されていて、アクセスの度にインクリメントします
ブラウザをリロードすると数値がインクリメントするのが確認できます

Laravel で Tumblr API の Access Token を取得

Laravel で Tumblr API のアクセストークンを取得するプログラムを動かしたときのメモ

検証環境

$ php --version
PHP 7.1.4 (cli) (built: May 11 2017 17:22:31) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

$ php artisan --version
Laravel Framework 5.4.33

Tumblr API の認証についての注意点

  • 認証プロトコルは OAuth 1.0a
  • Twitter などと違い、開発コンソール画面で Access Token の確認ができないため、Web アプリケーションなどで Access Token が必要な場合は認証プログラムを使って取得する必要がある

OAuth パッケージについて

今回は Laravel5 対応の以下のパッケージを使用します
github.com

oriceon/oauth-5-laravel のインストール

composer.jsonrequire セクションに下記内容を追加

    "require": {
        "oriceon/oauth-5-laravel": "dev-master"
    }

その後 composer update でインストール

$ composer update

config/app.php を下記のように変更してパッケージを登録

--- config/app.php.orig Fri Aug 18 12:25:23 2017
+++ config/app.php      Wed Aug 16 16:55:38 2017
@@ -177,6 +177,11 @@
         App\Providers\EventServiceProvider::class,
         App\Providers\RouteServiceProvider::class,

+        /*
+         * OAuth
+         */
+        Artdarek\OAuth\OAuthServiceProvider::class,
+
     ],

     /*
@@ -212,6 +217,7 @@
         'Log' => Illuminate\Support\Facades\Log::class,
         'Mail' => Illuminate\Support\Facades\Mail::class,
         'Notification' => Illuminate\Support\Facades\Notification::class,
+        'OAuth'     => Artdarek\OAuth\Facade\OAuth::class,
         'Password' => Illuminate\Support\Facades\Password::class,
         'Queue' => Illuminate\Support\Facades\Queue::class,
         'Redirect' => Illuminate\Support\Facades\Redirect::class,

以下の内容で config/oauth-5-laravel.php を作成

<?php

return [

	/*
	|--------------------------------------------------------------------------
	| oAuth Config
	|--------------------------------------------------------------------------
	*/

	/**
	 * Storage
	 */
	'storage' => '\\OAuth\\Common\\Storage\\Session',

	/**
	 * Consumers
	 */
	'consumers' => [

		'Tumblr' => [
			'client_id'     => env('TUMBLR_CLIENT_ID'),
			'client_secret' => env('TUMBLR_CLIENT_SECRET'),
			// No scope - oauth1 doesn't need scope
		],

	]

];

.env に Consumer Key, Consumer Secret を追加

TUMBLR_CLIENT_ID=Your-Consumer-Key
TUMBLR_CLIENT_SECRET=Your-Consumer-Secret

OAuth 認証プログラム

app/Http/Controllers/TumblrAuthController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TumblrAuthController extends Controller
{
	public function loginWithTumblr(Request $request)
	{
		// get data from request
		$token  = $request->get('oauth_token');
		$verify = $request->get('oauth_verifier');
		
		// get tumblr service
		$tmb = \OAuth::consumer('Tumblr');
		
		// check if code is valid
		
		// if code is provided get user data and sign in
		if ( ! is_null($token) && ! is_null($verify))
		{
			// This was a callback request from tumblr, get the token
			$token = $tmb->requestAccessToken($token, $verify);
			
			//Var_dump
			//display whole array.
			dd($token);
		}
		// if not ask for permission first
		else
		{
			// get request token
			$reqToken = $tmb->requestRequestToken();
			
			// get Authorization Uri sending the request token
			$url = $tmb->getAuthorizationUri(['oauth_token' => $reqToken->getRequestToken()]);

			// return to tumblr login url
			return redirect((string)$url);
		}
	}
}

routes/web.php

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/tumblr', 'TumblrAuthController@loginWithTumblr');

OAuth 認証プログラムの実行

以下のコマンドで開発用サーバーが起動します

$ php artisan serve

web ブラウザで http://127.0.0.1:8000/tumblr にアクセスします
途中、以下の画面が表示されたときは Allow をクリックします
f:id:takaya030:20170818161156p:plain

web ブラウザに以下のような Access Token の表示が出れば成功です

StdOAuth1Token {#175 ▼
  #requestToken: "xxxxx...."
  #requestTokenSecret: "xxxxx..."
  #accessTokenSecret: "xxxxx..."
  #accessToken: "xxxxx..."
  #refreshToken: null
  #endOfLife: -9002
  #extraParams: []
}

glide で GAE/Go プロジェクトのパッケージ管理

Google App Engine for Go (GAE/Go) の開発環境に glide でパッケージをインストールする手順メモ

検証環境

Windows10 Home Edition
VirtualBox 5.1.22
Docker version 17.05.0-ce, build 89658be
docker-compose version 1.6.2, build 4d72027

GAE/Go 開発環境について

今回は下記サイトの手順で構築したものを使用します
takaya030.hatenablog.com

GAE/Go 環境での vendoring の注意点

  • app.yaml があるディレクトリ以下の go ファイルはビルド時にすべてリンクされるため、外部パッケージは別ディレクトリにインストールする (パッケージ内で syscall や unsafe を使用しているとエラーになるため、かつ必要なものだけをリンクするようにするため)
  • vendor ディレクトリは $GOPATH/src 以下に配置されていないと import の対象にならない

ディレクトリ構成

上記を踏まえた上でのディレクトリ構成

+---gaego
|   |   docker-compose.yml
|   |   
|   +---config
|   |   
|   +---data
|   |       Dockerfile
|   |   
|   +---glide
|   |       
|   +---sdk
|           Dockerfile
|            
+---logs
|    
+---www
    |       
    +---app
    |       app.yaml
    |       main.go
    |
    +---src
        |
        +---hello
                app.go
                app-engine.go
                app-standalone.go
                hello.go

各種ファイルの詳細

Echo を使って "Hello, World!" を表示するサンプルプログラムです
(前回記事から追加、変更のあるもののみ)

www/app/main.go

package main

import (
	_ "hello"
)

func init() {
}

www/src/hello/app.go

package hello

var e = createMux()

www/src/hello/app-engine.go

// +build appengine

package hello

import (
    "github.com/labstack/echo"
    "github.com/labstack/echo/engine/standard"
    "net/http"
)

func createMux() *echo.Echo {
    e := echo.New()

    // note: we don't need to provide the middleware or static handlers, that's taken care of by the platform
    // app engine has it's own "main" wrapper - we just need to hook echo into the default handler
    s := standard.New("")
    s.SetHandler(e)
    http.Handle("/", s)

    return e
}

// main()は書かなくて良い

www/src/hello/app-standalone.go

// +build !appengine,!appenginevm

package hello

import (
    "github.com/labstack/echo"
    "github.com/labstack/echo/engine/standard"
    "github.com/labstack/echo/middleware"
)

// ログの設定や静的ファイルの場所指定などをしています
func createMux() *echo.Echo {
    e := echo.New()

    e.Use(middleware.Recover())
    e.Use(middleware.Logger())
    e.Use(middleware.Gzip())

    e.Use(middleware.Static("public"))

    return e
}

func main() {
    e.Run(standard.New(":8080"))
}

www/src/hello/hello.go

package hello

import (
    "net/http"

    "github.com/labstack/echo"
    "github.com/labstack/echo/engine/standard"
    "github.com/rs/cors"
)

func init() {

    g := e.Group("/hello")
    g.Use(standard.WrapMiddleware(cors.Default().Handler))

    g.GET("", getWorld)
    g.GET("/:id", getUser)
}

func getWorld(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World!")
}

func getUser(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, " + c.P(0) + "!")
}

glide のインストール

$ cd gaego
$ docker-compose run --rm sdk go get github.com/Masterminds/glide

glide.yaml の作成

$ cd gaego
$ docker-compose run --rm sdk /bin/bash -c "cd src/hello;glide create"
Starting gaego_data_1
[INFO]  Generating a YAML configuration file and guessing the dependencies
[INFO]  Attempting to import from other package managers (use --skip-import to skip)
[INFO]  Scanning code to look for dependencies
[INFO]  --> Found reference to github.com/labstack/echo
[INFO]  --> Adding sub-package engine/standard to github.com/labstack/echo
[INFO]  --> Adding sub-package middleware to github.com/labstack/echo
[INFO]  --> Found reference to github.com/rs/cors
[INFO]  Writing configuration file (glide.yaml)
[INFO]  Would you like Glide to help you find ways to improve your glide.yaml configuration?
[INFO]  If you want to revisit this step you can use the config-wizard command at any time.
[INFO]  Yes (Y) or No (N)?
N
[INFO]  You can now edit the glide.yaml file. Consider:
[INFO]  --> Using versions and ranges. See https://glide.sh/docs/versions/
[INFO]  --> Adding additional metadata. See https://glide.sh/docs/glide.yaml/
[INFO]  --> Running the config-wizard command to improve the versions in your configuration

glide によるパッケージインストール

上記操作で作成された glide.yaml では Echo の最新版がインストールされますが、go1.6 では動作しないので旧バージョンを指定するように変更します
(glide.yaml 4行目に "version: v2.2.0" を追加)

www/src/hello/glide.yaml

package: hello
import:
- package: github.com/labstack/echo
  version: v2.2.0          # この行を追加
  subpackages:
  - engine/standard
  - middleware
- package: github.com/rs/cors

その後、以下の操作でインストール

$ cd gaego
$ docker-compose run --rm sdk /bin/bash -c "cd src/hello;glide up"
Starting gaego_data_1
[INFO]  Downloading dependencies. Please wait...
[INFO]  --> Fetching github.com/labstack/echo
[INFO]  --> Fetching github.com/rs/cors
[INFO]  --> Setting version for github.com/labstack/echo to v2.2.0.
[INFO]  Resolving imports
[INFO]  --> Fetching github.com/labstack/gommon
[INFO]  --> Fetching github.com/dgrijalva/jwt-go
[INFO]  --> Fetching github.com/mattn/go-isatty
[INFO]  --> Fetching github.com/valyala/fasttemplate
[INFO]  --> Fetching golang.org/x/net
[INFO]  --> Fetching github.com/mattn/go-colorable
[INFO]  --> Fetching golang.org/x/sys
[INFO]  --> Fetching github.com/valyala/bytebufferpool
[INFO]  Downloading dependencies. Please wait...
[INFO]  Setting references for remaining imports
[INFO]  Exporting resolved dependencies...
[INFO]  --> Exporting github.com/valyala/bytebufferpool
[INFO]  --> Exporting github.com/labstack/echo
[INFO]  --> Exporting github.com/dgrijalva/jwt-go
[INFO]  --> Exporting github.com/mattn/go-colorable
[INFO]  --> Exporting github.com/rs/cors
[INFO]  --> Exporting github.com/mattn/go-isatty
[INFO]  --> Exporting github.com/labstack/gommon
[INFO]  --> Exporting github.com/valyala/fasttemplate
[INFO]  --> Exporting golang.org/x/sys
[INFO]  --> Exporting golang.org/x/net
[INFO]  Replacing existing vendor dependencies
[INFO]  Project relies on 10 dependencies.

以上で www/src/hello/vendor 以下に Echo v2 がインストールされました

動作確認

以下のコマンドで開発用サーバーが起動します

$ docker-compose up -d

web ブラウザで http://192.168.99.100:8080/hello にアクセスして "Hello, world!" の文字が表示されれば成功です
f:id:takaya030:20170805155642p:plain

http://192.168.99.100:8080/hello/takaya030 にアクセスすると "Hello, takaya030!" と表示されます
f:id:takaya030:20170805155700p:plain

ローカルの Docker 環境で Cloud9 IDE を動かす

Cloud9 IDE を Docker コンテナで動作させたときの手順メモ

検証環境

Windows10 Home Edition
VirtualBox 5.1.22
Docker version 17.05.0-ce, build 89658be
docker-compose version 1.6.2, build 4d72027

インストールにあたっての注意点

  • Cloud9 IDE は node.js で動作しているが、使用するバージョンは v0.10 または v0.12 とする
  • Cloud9 IDE のインストールは一般ユーザー権限で行う

ディレクトリ構成

+---c9
    |   docker-compose.yml
    |   
    +---workspace
    |   
    +---data
    |       Dockerfile
    |       
    +---ide
            Dockerfile

各種設定ファイル

c9/docker-compose.yml

version: "2"
services:
  data:
    build: ./data
    volumes:
      - ./workspace:/workspace
  ide:
    build: ./ide
    volumes_from:
      - data
    volumes:
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "8080:8080"
    command: node /home/docker/cloud9/server.js --port 8080 -w /workspace -l 0.0.0.0 --auth docker:tcuser

c9/data/Dockerfile

FROM busybox
LABEL maintainer "takaya030"

RUN mkdir -p /workspace
VOLUME ["/workspace"]
CMD ["true"]

c9/ide/Dockerfile

FROM ubuntu:16.04
LABEL maintainer "takaya030"

RUN apt-get update -y \
	&& apt-get install -y nodejs npm curl git sudo \
	&& apt-get clean \
	&& rm -fr /var/lib/apt/lists/*

RUN npm cache clean \
	&& npm install n -g

RUN n 0.12.18 \
	&& ln -sf /usr/local/bin/node /usr/bin/node \
	&& apt-get purge -y nodejs npm

# create docker user
RUN useradd -d /home/docker -m -s /bin/bash -u 1000 -g 50 docker

USER 1000
RUN git clone https://github.com/c9/core.git /home/docker/cloud9 \
	&& cd /home/docker/cloud9 \
	&& ./scripts/install-sdk.sh

USER root
RUN mkdir -p /workspace
VOLUME ["/workspace"]
WORKDIR /workspace

USER 1000

イメージのビルド

c9 ディレクトリに移動後、以下のコマンドでイメージをビルドする

$ docker-compose build

動作確認

以下のコマンドで Cloud9 IDE が動作します

$ docker-compose up -d

web ブラウザで http://192.168.99.100:8080 にアクセスすると Basic 認証で UserId と Password の入力を求められるので次の通りに入力する

  • UserId: docker
  • Password: tcuser

その後、以下の画像のように表示されれば成功です
f:id:takaya030:20170725232924p:plain

gcloud app deploy : This deployment has too many files

Laravel のプロジェクトを GAE にデプロイしたときに以下のエラーが発生したときの対処手順メモ

ERROR: (gcloud.app.deploy) Error Response: [400] This deployment has too many files. New versions are limited to 10000 files for this app.

エラー原因

Laravel のプロジェクトに Google APIs Client Library for PHP (google/apiclient) を追加したことでプロジェクトのファイル数が 10,000 を超えたため
(GAE は 1 バージョンあたり 10,000 ファイルまでしかアップロードできない)

# before installing google/apiclient
$ cd laravel
$ ls -FR | grep -v / | grep -v "^$" | wc -l
5688

# after installing google/apiclient
$ cd laravel
$ composer require google/apiclient:v2.1.3
$ ls -FR | grep -v / | grep -v "^$" | wc -l
10868

google/apiclient をインストールしただけで 5180 ファイルも増えている

対処方法

調べたところ増加したファイルの大半は google/apiclient-services のファイルだった
これらは Google の各種サービスにアクセスするためのクラス群であるが、ソースを見たところ各サービスは独立していて互いに参照していないように見受けられた
今回は Gmail API のみ使えればよいので、それ以外のファイルは削除した

$ cd laravel
$ mv vendor/google/apiclient-services/src/Google/Service/Gmail /tmp
$ mv vendor/google/apiclient-services/src/Google/Service/Gmail.php /tmp
$ rm -rf vendor/google/apiclient-services/src/Google/Service/*
$ mv /tmp/Gmail vendor/google/apiclient-services/src/Google/Service/
$ mv /tmp/Gmail.php vendor/google/apiclient-services/src/Google/Service/

$ ls -FR | grep -v / | grep -v "^$" | wc -l
5832

再度 "gcloud app deploy" を実行したところデプロイが正常に完了し、GAE で Gmail API が動作していることを確認した

Lumen でお手軽に Google API を使う

以前、Laravel から Google API を使う記事を書きましたが、今回は Lumen からより簡単に使ってみます

検証環境

$ php --version
PHP 5.5.34 (cli) (built: Jun 24 2017 00:40:52)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies

$ php artisan --version
Laravel Framework version Lumen (5.1.7) (Laravel Components 5.1.*)

OAuth クライアント ID、Refresh Token の取得

以下の記事を参考に Google API で使用する Client ID、Access Token を取得する
takaya030.hatenablog.com

Google APIs Client Library for PHP のインストー

前回 oauth2 ライブラリは oriceon/oauth-5-laravel を使用しましたが、今回は google/apiclient を使います

$ composer require google/apiclient:v2.1.3

サンプルコード

.env

.env に以下の内容を追加

# oauth
GOOGLE_CLIENT_ID=Your-Clinet-Id
GOOGLE_CLIENT_SECRET=Your-Clinet-Secret
GOOGLE_REFRESH_TOKEN=Your-Refresh-Token

app/Http/Controllers/GmailController.php

<?php

namespace App\Http\Controllers;

class GmailController extends Controller
{
    // show labels
    public function showLabels()
    {
        $client = new \Google_Client();
        $client->setClientId( env('GOOGLE_CLIENT_ID') );
        $client->setClientSecret( env('GOOGLE_CLIENT_SECRET') );
        $client->setScopes([ "https://mail.google.com/" ]);
        $client->refreshToken( env('GOOGLE_REFRESH_TOKEN') );

        $service = new \Google_Service_Gmail($client);

        // Print the labels in the user's account.
        $user = 'me';
        $results = $service->users_labels->listUsersLabels($user);

        $labels = [];
        if (count($results->getLabels()) == 0) {
            $labels[] = "No labels found.";
        } else {
            $labels[] = "Labels:";
            foreach ($results->getLabels() as $label) {
                $labels[] = sprintf("- %s", $label->getName());
            }
        }

        return view( 'gmail.labels', ['labels' => $labels] );
    }
}

app/Http/routes.php

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*/

$app->get('/gmail/labels', 'GmailController@showLabels');

resources/views/gmail/labels.blade.php

<!doctype html>
<html>
    <head>
        <title>gmail labels</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
    @foreach($labels as $label)
        {{ $label }}<br />
    @endforeach
    </body>
</html>

動作確認

テストサーバー起動

$ php artisan serve

WEBブラウザで http://localhost:8000/gmail/labels を開いて下の画像のように表示されれば成功です
f:id:takaya030:20170715001557p:plain

まとめ

oriceon/oauth-5-laravel のときはエンドポイントの url を文字列で直接指定したり、レスポンスの json を自分でパースしなければならなかったりといろいろ手間がかかりましたが、google/apiclient ではそれらをライブラリ側で吸収してくれているので以前より簡潔なコードになっています