Google Spreadsheet APIを使ってみる その1

はじめに

こんにちは、イメージ・マジックのもあいです。
GoogleのSpreadsheet APIを仕事で使用したので備忘録として残しておきます。

プロジェクトの作成

Googleアカウントでログインしておいて、Google Cloud コンソール の APIライブラリページ にアクセスし、プロジェクトの選択をクリックします


新しいプロジェクトをクリックします

プロジェクト名を入力して作成をクリック

しばらくするとプロジェクトが作成されます。

APIを有効にする

プロジェクトを作成した後、プロジェクトを選択すると下記の様になるので、Drive APIとSpreadsheet APIを有効にします。

Google Drive APIを選択して、有効にするをクリックします

Google Spreadsheet APIを選択して、有効にするをクリックします


認証情報の作成

Google Drive APIとGoogle Spreadsheet APIを有効にしたら認証情報を作成をクリックします

認証情報の作成は下記の様に選択をして次へボタンをクリックします

サービスアカウントIDを入力して作成して続行ボタンをクリック。サービスアカウントが作成できましたと表示されるので、完了ボタンをクリックします。

これでサービスアカウントが作成できました。
左ペインの認証情報をクリックして、サービスアカウント欄のサービスアカウントをクリックします。

キーをクリックします

鍵を追加をクリックし、新しい鍵を作成をクリックします

JSONを選択して作成をクリックします

jsonファイルがダウンロードされました。今後このファイルと画面に表示されているサービスアカウントのメールアドレス(testsample@testsample-398107.iam.gserviceaccount.com)を保存しておいてください。Driveでのファイルオーナーになります。

終わりに

今回はプロジェクト作成から認証情報の作成までとなります。認証情報作成で取得したjsonファイルの取扱には注意してください。間違ってもGitHub等のソースコード管理にコミットしてはいけません。

IllustratorのVer UPによるPNG読込挙動について

はじめに

こんにちは、イメージ・マジックのもあいです。
弊社では印刷用データの自動処理でPhotoshopやIllustratorのスクリプトを使用する事があるのですが、最近でIllustratorのバージョンアップを行ったら正常に動作しなくなったと言うことがありました。
その事象について備忘録として記事を残しておくことにします。

事象

具体的にどうなったのかというと、Illustratorに配置している画像がずれていてかつ大きさが小さくなるという事象でした。 報告を受けて使用しているIllustratorのバージョンを報告者に確認したところ26.1.0/26.2.1は問題が発生しないが、26.5だと発生するとのことでした。こういう事象が発生したときにバージョンを確認するとよくあるのが「最新版」という報告ですが、それが無かっただけでも良かったと思っています。
ただ、それでも不明なバージョンもあったので、Adobe Creative Cloudでバージョンダウングレードテストも行って、結果としては26.2まではOKで26.3/26.4/26.5はNGでした。

原因

Illustrator上で画像が小さくなったとのことでしたので、最初から解像度の問題であることを疑いましたし、それが正解でした。サーバ上で解像度(DPI値)のみを埋め込んでいたのですが、単位までは埋め込んでいなかったのが原因で、それによってIllustratorのバージョンによって解釈が異なっていることがわかりました。 Illustratorは解像度を埋め込んでいない画像については72dpiとして扱います。26.2までは解像度のみを埋め込んでも72dpi扱いで、単位を埋め込んで初めて認識します。26.3からは解像度のみを埋め込むと単位をdpiで認識していました。これが原因して今まで動いていたものが動かなくなりました。

検証

5種類の画像を用意してIllustratorの26.2と26.5に読み込ませたらどうなるかを検証しました。
下記のような5種類の画像を用意しました。
No 解像度 単位 大きさ(px) 備考
1 なし なし 800 x 80 何も埋め込んでいないバーコード画像
2 なし なし 610 x 88 1に余白をつけたバーコード画像
3 200 なし 610 x 88 1に余白をつけて解像度を付与
4 200 PixelPerInch 610 x 88 1に余白をつけて解像度/単位を付与
5 72 PixelPerInch 610 x 88 1に余白をつけて解像度/単位を付与
下記の画像ですが上記の表の画像を上から順にIllustrator 26.2.1に読み込ませました。
No4は200dpiとして認識しているので小さく表示されていますが、それ以外は一緒です。   次にIllustrator26.5で読み込ませた結果です。
No4はバージョンが異なっても同じですが、No3の解像度のみ指定している画像も200dpi扱いになって小さく表示されます。 ※上記2つの画像は同じ拡大率で表示してるものを縦に並べてスクリーンショットをとっています。

結論

画像の解像度を埋め込む場合は、解像度とともに単位も設定する。片方だけだと誤動作するので厳密に値を設定するのがよい。

ものすごく基本的な話ですが…

はじめに

こんにちは、イメージ・マジックのもあいです。
bashで簡単なツールを作っているときに、つまらない内容ではまってしまったので、備忘録としておいておきます。

bashで関数

あまり、bashで関数は作らないのですが、スクリプトの長さがそこそこあるのとパラメータによる分岐があったので関数かしてソースコードを整理していた時に、スクリプトが正常に動作しなくなってしまいました。そのソースコードの主な抜粋は下記のようになります。
#!/bin/bash
FIRST=${1}

function add ()
{
  echo add function
}

function remove ()
{
  echo remove function;
}

if [ "${FIRST}" = "add" ]; then
  add
elif [ "${FIRST}" = "remove" ]; then
  remove
else
  echo ${0} add|remove 以下使い方
fi
そしてこのスクリプトを実行したときの結果は下記の通り
remove function
想定としては「add|remove 以下使い方」が表示されることでしたが、remove関数実行されてしまいました。

結論

結論はechoに|removeと書いてしまっているからでした。あまりBashで深くスクリプトを作成していないので、この行に行き着くのにものすごく時間がかかりました。このechoの後ろの文字を”で囲めば想定した動作になりました。 使い方として記載したechoで関数が呼び出されることになるのは考えていなかったのでびっくりしました。

PHP7.4移行作業の苦労小話

はじめに

こんにちは、イメージ・マジックのもあいです。 今回は直近で作業をしていたPHP7.0からPHP7.4への移行作業について、手動での対応ではまった点についての備忘録です。

プロパティの型が指定できることによって・・・

PHP7.4の大きな違いの一つとしてはプロパティの型が明示できるようになったことがあると思いますが、これにより移行作業が思った以上に手間だったという印象がありました。自分が体験した内容を記していきます。 サンプルとして下記コードを用意しました。

<?php
declare(strict_types=1);

class Hoge {
        private $prop1;
        private string $prop2;
        public function getProp1() {
                return $this->prop1;
        }
        public function getProp2():string {
                return $this->prop2;
        }
}
$a = new Hoge();
var_dump($a->getProp1());
var_dump($a->getProp2());

サンプルとして用意したコードですが、このコードは16行目でエラーとなり実行が止まります。Hogeクラスのプロパティprop2ですが、string型を明示しているため、初期化しないでアクセスすると下記のようなエラーとなります。

PHP Fatal error:  Uncaught Error: Typed property Hoge::$prop2 must not be accessed before initialization in /home/moai/sample/test01.php:11

昔からPHPコードを書いていた人間としては、ここまでチェックされるとPHPの簡単なことが簡単なコードで実現できるという手軽さが無くなってきている印象を受けます。Javaのような言語に比べれば全然マシですけれども。それだけPHPが使われており単純なミスを抑止できるように型チェックをするようになっているとも言えます。 上記のエラーですが対応方法はいくつかあって、コンストラクタで初期化する、nullで初期化する、プロパティを参照するところで\Errorをcatchする、といったことができます。さすがに\Errorをcatchはやり過ぎな気もします。nullで初期化するのが妥当な気がします。

最後に

そのほかに、PHPが用意している文字列操作の関数引数にnullが入るとエラーになるという地味に面倒な物もありましたが、null合体演算子を入れれば比較的簡単に解決できますが、使用箇所が多いと地味に面倒でした。

Illustratorスクリプトあれこれ その2

はじめに

こんにちは、イメージ・マジックのもあいです。

今回は直近で作業をしていたIllustratorスクリプトの備忘録になります。

アートボードサイズと画像のサイズを一致させたかったが・・・ずれた

Illustratorのアートボードとそこに配置する画像のサイズを一致させる方法を、最初はサーバ側でImageMagickのIdentifyコマンドでピクセル数を求めてから加工に必要なDPIを使ってmm単位で算出していました。1259pxで200DPIですと159.893mmとなるので、切り上げて160mmとなります。この値をIllustratorでdocumtns.addの引数として渡していたのですが、アートボードのサイズと画像サイズが微妙にずれることが発覚しました。

原因としては、小数点を切り上げてしまったことが原因でした。

そもそも

Illustratorスクリプトでアートボードのサイズと画像のサイズを一致させるための操作方法は、「オブジェクト」→「アートボード」→「オブジェクト全体に会わせる」を選択する必要があるのですが、この操作をアクションで記録できなかったので、アートボードのサイズを指定するときに画像の大きさ(mm)を指定していました。
ですが、それがうまくいかない場合があるのが今回のパターンでした。

executeCommandMenu

Illustratorスクリプトにはドキュメントに記載が無い(少なくとも見つけられませんでした)executeCommandMenuというものがあり、この機能を使うことによりアクションで記録できない機能も実行することが可能になります。
今回の場合の具体的なコードですが

app.executeMenuCommand("Fit Artboard to artwork bounds");

となりました。この呼び出しだけでサーバ側の算出処理が不要になりました。

最後に

小数点以下の値を無視すると痛い目に遭いました。

Illustratorスクリプト開発の便利ツール

はじめに

こんにちは、イメージ・マジックのもあいです。

前回ブログを書いたのが約一年前、時間が経つのがどんどん早く感じられてきている今日この頃です。
富士ゼロックススーパーカップも終わり、Jリーグもそろそろ開幕する時期になってきました。 今回は、2018年7月頃に公開したIllustratorスクリプトのあれこれを書いた後にIllustratorスクリプトを開発するに当たって便利なツールを見つけましたので、簡単な使い方を紹介します。

ExtendScript Debugger

見つけたツールは、Microsoft社が公開しているVisual Studio Code のExtensionである ExtendScript Debugger というものです。これはAdobeが公開している公式なツールになります。

インストール

手順は下記の通りです
  • Visual Studio Codeをインストール
  • Visual Studio Codeの拡張機能(Ctrl + Shift + X)で ExtendScriptで検索
  • ExtendScript Debugger をクリック
  • インストール

使い方

  • デバッグしたいIllustratorスクリプトをVisual Studio Codeで開きます
  • Visual Stuio Codeのステータスバーにあるターゲットアプリケーションを選択をクリックし、画面上部に現れるターゲットアプリケーションを選択というボックスに使用するアプリケーション(今回はAdobe Illustrator 2020)を選択します。この時点でIllustratorが起動していない場合はIllustratorを起動するかどうかを聞いてきますのではいを選択します。
  • F5キーを押下し、環境の選択でExtendScript Debugを選択すれば、デバッグを開始できます。
  • ブレークポイントを設定すれば、そこで止めることも可能です。
  • 変数、ウォッチ式、コールスタックと行った情報を見ることができます。
  • グローバルなオブジェクトの情報も見られます。
  • ローカル変数の情報も当然見られます。

最後に

以前は Extendscript Toolkit CC をインストールしていましたが、このツール自体がEOLなので、インストール手順が煩雑なのと、新規ドキュメントを作成する処理を実行できないという問題がありましたが、今回紹介しているツールはそんなことも無くデバッグできるので、開発がだいぶ楽になったと思っています。

PHPでPDF帳票を作成する

はじめに

こんにちは、イメージ・マジックのもあいです。

春になり、JリーグやMotoGP等のスポーツも今シーズンが開幕、UCLや欧州サッカーも終盤を迎えて情報を追ったり観戦したりするのが大変な状態です。インターネットが発達してこんなに情報が増えようとは思いもしなかった今日この頃です。 今回はPHPでPDF帳票を作成するために必要だったことをまとめてみました。

使用するライブラリ

FPDFmPDFwkhtmltopdf という選択肢から、mPDFを使用しました。選定した理由は扱いやすさとライブラリ自身がそれなりの頻度で更新されているからです。

インストール

composerでインストールできます。
composer require mpdf/mpdf
そのほかに日本語を表示させるのであれば日本語フォントが必要になります。

使い方

htmlとcssを用意する

mPDFはhtmlとcssでPDF帳票のレイアウトを作成します。htmlなのでポジションを調整するのが難しいと思われますが、cssのposition:absoluteが条件付きで使用することができます。

ドキュメントにも記載されているのですが、body要素の直下の要素にだけposition:absoluteが適用できます。これを使うことによりレイアウトを調整できます。単位もpxでは無くてptやmmが使えますので帳票レイアウトの調整はそれほぞ難しくないです。
下記のようなコードの場合aクラスとbクラスはposition:absoluteが適用できますが、cクラスは適用できません。
<body>
  <div class="a"></div>
  <div class="b">
    <div class="c"></div>
  </div>
</body>

htmlを取得する

弊社ではSymfony4を使用して開発していますので、htmlを取得する場合はコントローラのrenderViewメソッドでtwigとデータを渡すとhtmlが取得できます。

PDFを生成する

mPDFのインスタンスを生成するときに設定情報を配列で引き渡します。この時に用紙の大きさ/向き/マージンやフォントファイルの場所やフォントにkanする方法を引き渡します。 設定情報はだいたい下記の通りです。
$config = [
    'mode' => 'ja+aCJK',
    'format' => [297, 210],
    'dpi' => 200,
    'tempDir' => '/tmp/',
    'margin_left' => 0,
    'margin_right' => 0,
    'margin_top' => 0,
    'margin_bottom' => 0,
    'orientation' => 'P',
    'fontDir' => [
        '/path/to/fontDir/,
    ],
    'fontdata' => [
        'ipag' => [
            'R' => 'ipag.ttf',
        ],
        'ipagp' => [
            'R' => 'ipagp.ttf',
        ],
    ],
];
A4縦でDPIは200、フォントにIPAゴシックとIPAゴシックプロポーショナルを指定し、fontdataの配下のipagとipagpというキーはcssのfont-familyで指定することができます。

設定情報をmPDFのインスタンスに渡してWriteHTMLメソッドを呼び出してからOutputメソッドを呼び出すとPDFを標準出力に出力します。
Symfony4で標準出力の結果をクライアントに送信する場合はStreamedResponseクラスを使用することになります。
$mpdf = new \Mpdf\Mpdf($config);
$mpdf->SetDefaultFont('ipagp');
$mpdf->WriteHTML($html);
$mpdf->Output();

最後に

htmlで帳票を作成するに際に、位置がずれると問題になる帳票を作成した際に調査した結果です。

PHPコードのチューニング

はじめに

こんにちは、イメージ・マジックのもあいです。

最近はサッカーを見るときには2つのチームがどのように動こうとしているのかを観察することによって、より面白く観戦できるようになってきました。日本代表チームがアジアカップの決勝でどのような戦い方をするのかが楽しみではありますが、相手チームであるカタールにも気をつけてみるとさらに面白くなります。

今回はPHP(Symfony4)のパフォーマンスチューニングについての記事になります。

記事の前提
 OS: Ubuntu 18.04
 PHP:7.2.10
 nginx:1.14.0
 PhpStorm:2018.3.3
 ※全てのソフトウェアはaptコマンドでインストールしています

Xdebugのプロファイラ機能

PHPで関数/メソッドの処理時間を測定するのにXdebugをインストールします。

sudo apt install php-xdebug

php.iniを編集して有効にします。
/etc/php/7.2/fpm/conf.d/20-xdebug.ini は下記の通り

xdebug.remote_enable=On
xdebug.remote_autostart=On
xdebug.remote_host=192.168.33.1
xdebug.profiler_enable=On
xdebug.profiler_output_dir=/tmp
xdebug.profiler_enable_trigger = 1;
xdebug.max_nesting_level=1000
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_timeout=2000

ポイントとしては、xdebug.profiler_enableをOnにするのと、xdebug.profiler_output_dirに測定結果を出力するディレクトリを指定してphp-fpmをreloadします。測定が終わったら xdebug.profiler_enable を Offにしてphp-fpmをreloadします。常にOnにするのは処理が非常に重たくなるのでおすすめできません。

プロファイラを有効にして測定したいURLを実行すると下記のようなファイルが作成されます
-rwxrwxrwx 1 moai moai 42986908  1月 17 17:09 cachegrind.out.26276
-rwxrwxrwx 1 moai moai     2644  1月 17 17:09 cachegrind.out.26276.0c892b
この2つのファイルをPhpStormをインストールしているマシンにコピーします。

PhpStormでプロファイル結果を解析

PhpStormでプロファイル結果を読み込みます。

Tool → Analyze Xdebug Profiler Snapshot…

ファイル選択ダイアログが開かれるので、ファイルサイズの大きいファイルを選択します。
デフォルトで処理時間の多い順番に表示されますが、これだけだとわかりにくいので、Call Treeタブをクリックして実行順表示にしてから処理に時間がかかっているのをドリルダウンして探します。

遅い部分を探して比較を行うと下記のような状態にすることができます。
改修前
DlvryController->jsonが19657msかかっています。ここで全体の53%の処理時間がかかってル事がわかります。ローカルの仮想マシンで測定しているとはいえ遅すぎます。
jsonが何を行っているかというと、Symfony4のEntityをjsonに変換しています。フレームワークの処理で遅くなっているのであれば手の施しようが無いような気もしますが、よくよく調べるとクライアント側で使っていない情報も返却していました。送る情報が少なくなればそれなりに速くなるのでは無いかという課程のもと、返却する情報を必要最低限の情報に絞った改修を行いました。

プロファイル結果は下記の通り。
改修後
3603msになりました。4.5倍速くなったことになります。
ここに出てくる処理時間はプロファイルを行っているため実際よりも大分遅いですし、VirtualBox上の仮想マシンで実行していますので、本番環境よりもさらに遅くなっていますが、どこで遅くなったかを把握するにはちょうど良い事になります。

最後に

プロファイルを行うことによりどこが遅いのかが一目瞭然でわかったのと、使っていないデータまで送ると遅くなる事がはっきりしました。

開発をしていると、面倒だからといってデータ取得の便利メソッドを使ってデータを取得し、そのままクライアントに返却することをやってしまうのですが、そういう事をすると最後にしっぺ返しが返ってくる良い例でした。

Doctrine2でMySQLのレプリケーションを設定する

はじめに

こんにちは、イメージ・マジックのもあいです。
弊社のシステムで、工場の生産を管理する生産管理システムがあるのですが、このシステムのデータベースはレプリケーションを行っており、読み取り専用のスレーブが存在します。
Symfony 4.1で生産管理のWeb開発を行っているのですが、レプリケーションの設定で調査を行った結果を記載したいと思います。

Doctrine2について

Symfony 4.1で使用するORMなのですが、Symfony専用というわけではなく、汎用的に使えるORMです。Doctrineの意味を調べてみるとちょっとお堅い感じの意味が出てきたのにはびっくりしました。

マスター/スレーブ構成とは

MySQLでは大分昔のバージョンから使えますが、一つのマスターDBと複数のスレーブDBからなるシステムで、スレーブは基本的には書き込みができません。スレーブDBに参照クエリを集めることにより、マスターDBの負荷を分散させることができるため、システムのスループット向上が見込めます。

Doctrine2の設定

doctrine.ymlにSlave設定を追加するだけで、現在のバージョンでは使用することが可能です。
slavesの配下にslaveのDB設定を追加すれば、スレーブを増やすこともできます。
現在のDoctrine2(2.5)ではこれだけです。

        connections:
            default:
                driver: 'pdo_mysql'
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_general_ci
                    row_format: dynamic
                dbname: 'dbname'
                user: 'db_user_name'
                password: 'db_user_password'
                host: 'db_master_host'
                port: 3306
                slaves:
                    slave1:
                        charset: utf8mb4
                        dbname: 'dbname'
                        user: 'db_user_name'
                        password: 'db_user_password'
                        host: 'db_slave_host'
                        port: 3306

これだけで、selectはスレーブ、update/insertはマスターを参照するようになります。

Vagrantのスナップショット機能

はじめに

こんにちは、イメージ・マジックのもあいです。
弊社開発部ではVirtualBoxを使ってローカルに開発環境を作成して開発を行っていますが、開発環境作成ではVagrantとAnsibleを使って自動で環境を作成しています。
今回は、この開発環境作成で便利なスナップショット機能を多用していましたので、どういった状況でどう使っていたのかを軽く説明します。

Vagrantとは

詳しくはWikiPedia等で確認してください。環境構築用ファイルから自動的に仮想マシンを作成して設定を行えるものです。
会社ではUbuntuをサーバOSとして使用していますので、BoxイメージはUbuntuの提供元が用意しているものを使用しています。

スナップショット機能とは

Vagrant+Ansibleで開発環境を作成するということは、Ansibleスクリプトを実行して正しい状態になることを確認します。
Ansibleスクリプトでは内容にもよりますが、設定変更が必要なときだけ設定変更を行います。
ということは、1回目と2回目で実行内容が異なるというわけです。テストではどちらの挙動も確認する必要があるのですが、
そのたびにVagrantで仮想マシンを破壊/作成を繰り返すのは非常に時間が掛かります。

そこで、VagrantにはVirtualBoxのスナップショット機能を簡単に使うコマンドが用意されていて

vagrant snapshot save foo

とすることでスナップショットを保存することができます。
この状態でAnsibleスクリプトを実行して、環境を戻したい場合は

vagrant snapshot restore foo

とすることで、スナップショットをとった状態に戻すことができます。
これでAnsibleスクリプトの再実行の時間が大幅に短縮されます。
fooとかいてあるところは名称ですので、いくつかスナップショットをとることもできます。