2020/03/02

composer update したところ、ext-dom がないから PHPUnitが入れられないようです。


$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - phpunit/phpunit 8.5.x-dev requires ext-dom * -> the requested PHP extension dom is missing from your system.
...

php-xml をインストール


# aptitude update
# aptitude install php-xml

再度 composer update する

今度は、インストールが進み、vendor もインストールされた。


$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 87 installs, 0 updates, 0 removals
As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.
This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.
Installing 'unzip' may remediate them.
  - Installing symfony/polyfill-ctype (v1.14.0): Loading from cache
...

  2020/02/08

DIについては、DI(依存性注入) を参照

DIコンテナは、DIのインスタンス生成を、別のファイルでコンテナ化して解決しようという設計パターンです。

共通クラスを用意

まず、共通で使う Animalクラスを用意します。
手っ取り早くファイル分割せず Animal.php にクラス(Dog、Cat)を記述しました。


interface Animal {
    public function bow();
}

class Dog implements Animal {
    public function bow() {
        echo 'wan! wan!'.PHP_EOL;
    }
}

class Cat implements Animal {
    public function bow() {
        echo 'nya-! nya-!'.PHP_EOL;
    }
}

DIでない例

下記のサンプルはコンストラクタ内で Dog を生成して鳴きます。


class AnimalConsole {
    protected $dog;

    public function __construct() {
        $this->dog = new Dog();
    }

    public function bow() {
        $this->dog->bow();
    }
}

$animal_console = new AnimalConsole();
$animal_console->bow();

この場合、コンストラクタで new Dog() するため、Dogが実装できるまで AnimalConsole が実装できません。

DI(?)の場合

コンストラクタの引数に、Dog、Cat インスタンスを注入します(コンストラクタインジェクション)
他の記事をみているとこれで「DI」となってますが、まだ Dog に依存しているため Cat に修正したい場合に手間がかかります。


require_once 'Animal.php';

class AnimalConsole {
    protected $dog;

    public function __construct(Dog $dog) {
        $this->dog = $dog;
    }

    public function bow() {
        $this->dog->bow();
    }
}

$animal_console = new AnimalConsole(new Dog());
$animal_console->bow();

インターフェイス(モック)を引数にしてみる

今度は Dog、Cat 両方扱えるように Amimal を引数とします。


require_once 'Animal.php';

class AnimalConsole {
    protected $animal;

    public function __construct(Amimal $animal) {
        $this->animal = $animal;
    }

    public function bow() {
        $this->animal->bow();
    }
}

$animal_console1 = new AnimalConsole(new Dog());
$animal_console1->bow();

$animal_console2 = new AnimalConsole(new Cat());
$animal_console2->bow();

これで、Dog、Cat どちらでも注入できるようになりました。

pimpleでDIコンテナを作成する

インスタンスを直接渡すのではなく、コンテナ(箱)内でインスタンスを作成して処理するのが、DIコンテナです。

今回は、composerのContainerライブラリ「pimple」を利用しています。

Pimpleインストール


$ composer require pimple/pimple ~3.0

PimpleによるDIコンテナ

下記の場合、Dog、Cat のインスタンスをコンテナ化しています。

また、$container['animal'] では、インスタンスを簡単に切り替えることができます。


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

use Pimple\Container;

class AnimalConsole {
    protected $animal;

    public function __construct(
        Animal $animal
        ) {
        $this->animal = $animal;
    }

    public function bow() {
        $this->animal->bow();
    }
}

$container = new Container();

$container['dog'] = function($c) {
    return new Dog();
};

$container['cat'] = function($c) {
    return new Cat();
};

$container['animal'] = function($c) {
    return $c['dog'];
};

$container['animalConsole'] = function ($c) {
    return new AnimalConsole($c['animal']);
};

$container['animalConsole']->bow();

Container の部分はファイル分離する必要はあります。

  2020/02/06

freee API は 開発者向けにOSS として公式公開されています。

https://developer.freee.co.jp/

 

ここでは、リファレンスを利用して認可コード・アクセストークン・API確認をしてみる。

実際の開発は各言語やSDKを使ってコーディングが必要だが、PHPに関しては、freee SDKを Laravel で使ってみる でやってみた。

開発者アカウント登録と環境・アプリ作成

まず、freeeアカウントを作成(一般ユーザアカウント)する

開発用テスト環境作成

次に開発ユーザでログインし、開発用テスト環境の作成する。

テスト環境の事業所を選択

アプリ追加

 アプリ追加画面でアプリを追加すると、Client ID, Client secret が発行される

作成したアプリは、アプリ管理 で管理する

freee API のドキュメント

API を試してみる

認可コード発行

「Webアプリ認証用URL」でブラウザでアクセスし、許可すると「認可コード」が発行される
※アクセストークンではない

アクセストークン発行

https://accounts.secure.freee.co.jp/public_api/authorize?client_id={client_id}&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=token 

上記のURLに freee アプリで発行された Client ID を入れてブラウザでリクエストする

事業所取得

https://developer.freee.co.jp/docs/accounting/reference#/Companies/get_companies

鍵マークをクリック

value に アクセストークンを入力して [Authorize]し、成功したら[Close]

[Try it out] をクリックし [Execute] するとAPIが実行される

事業所一覧取得API(companies)の場合

curl


curl -X GET "https://api.freee.co.jp/api/1/companies" -H "accept: application/json" -H "Authorization: Bearer {Client ID}"

Request Body


https://api.freee.co.jp/api/1/companies

Request URI


{
  "companies": [
    {
      "id": xxxxxxx,
      "name": "",
      "name_kana": "",
      "display_name": "個人事業主名",
      "role": "admin"
    },
    {
      "id": xxxxxxx,
      "name": null,
      "name_kana": null,
      "display_name": "個人事業主スタータープラン: 開発用テスト環境",
      "role": "admin"
    }
  ]
}

  2020/01/12

Composer 公式のインストール

https://getcomposer.org/download/

$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php -r "if (hash_file('sha384', 'composer-setup.php') === 'baf1608c33254d00611ac1705c1d9958c817a1a33bce370c0595974b342601bd80b92a3f46067da89e3b06bff421f182') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"
$ sudo mv composer.phar /usr/local/bin/composer

getcomposer.org のPHPインストーラを利用する

ComposerインストールようのPHPファイル https://getcomposer.org/installer を利用して /usr/local/bin/ にcomposer をインストール

$ curl -s https://getcomposer.org/installer | php && sudo mv -v composer.phar /usr/local/bin/composer

Composer バージョン確認

$ composer --version
Composer version 1.9.1 2019-11-01 17:20:17

Composer アップデート

$ composer self-update

  2019/12/30

DIとは

DI(Dependency injection) は依存性の注入の意味です。

ここで言う「依存性」は、オブジェクト思考でいうと大まかに「クラスファイル」と考えて良いかと。

そしてそのクラスが特定の定数、変数、インスタンスに依存しまい、単体テストに支障がでている状態です。

class Dog {
    public function isBow() {
        $person = new Person();
        return ($person->action() ==  'walk');
    }
}
class TestDog {
    public function testBow() {
        $dog = new Dog();
        $this->assertTrue($dog->isBow());
    }
}

上記だと、Dogクラス内にPersonクラスに依存してしまってます。 「$person->action() == 'walk'」の実装が変わってしまうと、assertTrue() した結果は、Personクラスが変更があった場合に変わってしまいます。

解決方法としては、Dogクラスの動作させるメソッドでインスタンスを作成せずに、コンストラクタやセッターに、Personを入れて(注入)して解決します。

class Dog {
    protected $person;
   
    public function __construct(Person $person) {
        $this->person = $person;
    }

    public function isBow() {
        return ($this->person->action() == 'walk');
    }
}
class TestDog {
    public function testBow() {
        $person = new Person();
        $person->expects($this->any())
            ->method('action')
            ->will($this->returnValue('walk'));
        $dog = new Dog($person);
        $this->assertTrue($dog->isBow());
    }
}

  2019/05/15

UFJ が API を虎視眈々と開発していた。

カブドットコムのAPIも使えたりと結構楽しそう、というか近々実用化されそうな予感がします。

カブドットコムのAPI(kabu.com API)は本番環境で利用できるとのことだが、
法人契約が必要なのと当然ながら審査が必要です。

開発用API登録

UFJ API

API種別

2019/05/15現在、個人口座、法人口座、振込申請、総合振込申請、給与賞与振込申請、特別徴収地方税のAPIが用意されている。

UFJ API

API Client Secretの発行

当然ながらAPIを利用するには、Client Secret の発行が必要となる。

UFJ API

APIリファレンス

各サービス毎にリファレンスは用意されている。

cURL,Ruby,Python,PHP,Java,Node,Go,Swift のサンプルが記載されており、
結構本気度が伺えられる。 また、レスポンスは基本 json のようだ。

UFJ API

ただ本番利用の場合は、金融業界なので審査が厳しいと予想される。

ライブラリ(PHP)

使いやすいように、Github にクラスライブラリを作成してました。

https://github.com/yoo16/ufj_api (2019/05/15現在アカウント情報取得のみ)

また、検証用データが用意されていて、Account ID一覧は以下の通り


001001110001 002001110002 325001110003 135011110005 118011110008 
329011110009 002021110013 002022220003 325022220004 909022220013 
002022220014 002023330003 325023330004 480023330005 777023330008 
118023330009 427383330012 909383330013 002383330014 002283330016

実行結果


$ php get_account.php 002023330003 

{"branchNo":"002","branchName":"丸の内","accountTypeCode":"02",
"accountTypeDetailCode":"00099",
"accountTypeName":"定期","accountNo":"3330003",
"accountName":null,"accountNameKana":null,
"balance":100000,"withdrawableAmount":null,
"currencyCode":"JPY"
,"foreignCurrencyBalance":null,
"yenEquivalent":null,"exchangeRate":null,
"totalMarketValue":null,
"totalUnrealizedProfitAndLoss":null,
"mutualFundAccountType":null,"fundBaseDate":null}

  2019/04/29
PHP7.3 で break と continue の取り扱いが変更になった影響で、composer install がエラーになる場合、
  • PHP7.2にさげる
  • composer のバージョンをあげる
    $ composer global require "laravel/installer"
    Changed current directory to /home/yoo/.config/composer
    Using version ^2.0 for laravel/installer
    ./composer.json has been created
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    
    Installation failed, deleting ./composer.json.
                                                                                               
      [ErrorException]                                                                         
      "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?  
                                                                                               
    require [--dev] [--prefer-source] [--prefer-dist] [--no-progress] [--no-update] [--no-scripts] [--update-no-dev] [--update-with-dependencies] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [--sort-packages] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--] [<packages>]...
    
    特に初期設定で composer のバージョンが低い場合は注意が必要 (composer self-udpate がないなど) composer installができなくなった時の解決法(PHP7.3)

    PHP7.2 に変更

    $ sudo update-alternatives --config php
      選択肢    パス           優先度  状態
    ------------------------------------------------------------
    *0            /usr/bin/php7.3   73        自動モード
      1            /usr/bin/php5     50        手動モード
      2            /usr/bin/php7.0   70        手動モード
      3            /usr/bin/php7.2   72        手動モード
      4            /usr/bin/php7.3   73        手動モード
    

    composerの再インストール(self-udpateなど利用できない場合)

    composer-setup.php をダウンロード・実行する
    $ curl -sS https://getcomposer.org/installer | php
    $ sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
    $ composer -V
    Composer version 1.8.5 2019-04-09 17:46:47
    
    2019/12/09追記 一発でインストールする
    $ curl -s https://getcomposer.org/installer | php && sudo mv -v composer.phar /usr/local/bin/composer
    

  2019/04/25
PHPの配列は他の言語と比べて若干癖がある。 インデックスが 型が整数か文字列とか連番でなくてもよいとかゆるいので、ある意味柔軟なデータを生成する事もできる。 (ここら辺は言語思想) PHP配列の結合は「array_merge() 」が一般的かも知れないが、演算子でも計算できる。 ただし、インデックスによって結果が異なるので注意が必要。
  • インデックスが同じ、異なる
  • 値が同じ、異なる
の組み合わせで考察してみる。 事前に結合するサンプルデータを作成しておく(例では10個ずつ)。
    function generateValues($count, $prefix = 'test', $from_index = 1)
    {
        for ($i = $from_index; $i <= $count + $from_index; $i++) $values[$i] = "{$prefix}{$i}";
        return $values;
    }
$values1 = 
array (
  0 => 'test0',
  1 => 'test1',
  2 => 'test2',
  3 => 'test3',
  4 => 'test4',
  5 => 'test5',
  6 => 'test6',
  7 => 'test7',
  8 => 'test8',
  9 => 'test9',
)
$values2 = 
array (
  0 => 'test0',
  1 => 'test1',
  2 => 'test2',
  3 => 'test3',
  4 => 'test4',
  5 => 'test5',
  6 => 'test6',
  7 => 'test7',
  8 => 'test8',
  9 => 'test9',
)

$values1 + $values2 の結合(インデックス同じ、値同じ)

$values1 + $values2 を演算子「+」で結合してみる。
//values1 + values2
$values1 = $array_merge->generateValues(10);
$values2 = $array_merge->generateValues(10);
$values = $values1 + $values2;
$values1 + $values2 = 
array (
  0 => 'test0',
  1 => 'test1',
  2 => 'test2',
  3 => 'test3',
  4 => 'test4',
  5 => 'test5',
  6 => 'test6',
  7 => 'test7',
  8 => 'test8',
  9 => 'test9',
)
インデックスが同じだと結合できない。 またどちらの配列が採用されているかわからないので、値の違う配列を作成して調べる。

$values1 + $values2 の結合(インデックス同じ、値異なる)

//values1 + values2
$values1 = $array_merge->generateValues(10, 'red');
$values2 = $array_merge->generateValues(10, 'blue');
$values = $values1 + $values2;
$values1 = 
array (
  0 => 'red0',
  1 => 'red1',
  2 => 'red2',
  3 => 'red3',
  4 => 'red4',
  5 => 'red5',
  6 => 'red6',
  7 => 'red7',
  8 => 'red8',
  9 => 'red9',
)
$values2 = 
array (
  0 => 'blue0',
  1 => 'blue1',
  2 => 'blue2',
  3 => 'blue3',
  4 => 'blue4',
  5 => 'blue5',
  6 => 'blue6',
  7 => 'blue7',
  8 => 'blue8',
  9 => 'blue9',
)
$values1 + $values2 = 
array (
  0 => 'red0',
  1 => 'red1',
  2 => 'red2',
  3 => 'red3',
  4 => 'red4',
  5 => 'red5',
  6 => 'red6',
  7 => 'red7',
  8 => 'red8',
  9 => 'red9',
)
上書きされずに最初の配列が採用されていることがわかる。

array_merge($values1, $values2)での結合(インデックス同じ、値同じ)

同じ内容の配列を array_merge() するとインデックスが振り直された配列を返す。
$values = array_merge($values1, $values2);
array (
  0 => 'test0',
  1 => 'test1',
  2 => 'test2',
  3 => 'test3',
  4 => 'test4',
  5 => 'test5',
  6 => 'test6',
  7 => 'test7',
  8 => 'test8',
  9 => 'test9',
  10 => 'test0',
  11 => 'test1',
  12 => 'test2',
  13 => 'test3',
  14 => 'test4',
  15 => 'test5',
  16 => 'test6',
  17 => 'test7',
  18 => 'test8',
  19 => 'test9',
)
今度は、インデックスの異なる配列で試してみる。 配列の作成は以下で作成
    function generateValuesWithIndex($count, $prefix = 'test')
    {
        for ($i = 0; $i < $count; $i++) {
            $values[$this->index++] = "{$prefix}{$i}";
        }
        return $values;
    }
$values1 = 
array (
  0 => 'test0',
  1 => 'test1',
  2 => 'test2',
  3 => 'test3',
  4 => 'test4',
  5 => 'test5',
  6 => 'test6',
  7 => 'test7',
  8 => 'test8',
  9 => 'test9',
)
$values2 = 
array (
  20 => 'test0',
  21 => 'test1',
  22 => 'test2',
  23 => 'test3',
  24 => 'test4',
  25 => 'test5',
  26 => 'test6',
  27 => 'test7',
  28 => 'test8',
  29 => 'test9',
)

$values1 + $values2 の結合(インデックス異なる、値同じ)

$values = $values1 + $values2;
$values1 + $values2 = 
array (
  0 => 'test0',
  1 => 'test1',
  2 => 'test2',
  3 => 'test3',
  4 => 'test4',
  5 => 'test5',
  6 => 'test6',
  7 => 'test7',
  8 => 'test8',
  9 => 'test9',
  20 => 'test0',
  21 => 'test1',
  22 => 'test2',
  23 => 'test3',
  24 => 'test4',
  25 => 'test5',
  26 => 'test6',
  27 => 'test7',
  28 => 'test8',
  29 => 'test9',
)
インデックスを保持したまま結合できる。

array_merge($values1, $values2)での結合(インデックス異なる、値同じ)

$values = array_merge($values1, $values2);
array (
  0 => 'test0',
  1 => 'test1',
  2 => 'test2',
  3 => 'test3',
  4 => 'test4',
  5 => 'test5',
  6 => 'test6',
  7 => 'test7',
  8 => 'test8',
  9 => 'test9',
  10 => 'test0',
  11 => 'test1',
  12 => 'test2',
  13 => 'test3',
  14 => 'test4',
  15 => 'test5',
  16 => 'test6',
  17 => 'test7',
  18 => 'test8',
  19 => 'test9',
)
インデックスが振り直されて結合される。

  2018/03/07
PHP7.1 で JpGraph4.2.0 を利用すると gd_image.inc.php でエラーになる。
function SetAntiAliasing($aFlg=true) {
        $this->use_anti_aliasing = $aFlg;
        if( function_exists('imageantialias') ) {
            imageantialias($this->img,$aFlg);
        }
        else {
            JpGraphError::RaiseL(25128);//('The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.')
        }
    }
imageantialias() が利用できないのが原因 PHP : imageantialias()
7.2.0 imageantialias() が常に使えるようになりました。 これまでのバージョンでは、PHP にバンドルされている GD ライブラリでコンパイルした場合にしか使えませんでした。
Debian のPHP7.1パッケージではダメで、PHP7.2 では動作した。

  2017/06/08
get_defined_constants() そのままだと全ての define値を取得される。 引数に「true」指定すると、連想配列の「user」にユーザ指定した define値を取得できる。
        $defined_constants = get_defined_constants(true);
        $this->defined_constants = $defined_constants['user'];
<< Top < Prev Next > Last >>