[Mac]容量を減らす
DIコンテナはじめ
freee SDKを Laravel で使ってみる
freee API を使ってみる
Segueを利用しない画面遷移
Xcode11.3 で XVim2 を利用する
Codable で JSONを読み込み
Webpack入門
MacからLaradock PostgreSQLで接続エラー
Mac で Laradock の構築
Dockerで不要なイメージを削除
yarn インストール&プロジェクト作成
Laravel 6.x 構築(Homestead編)
Composer インストール
nvm インストール
npm install が Mac でエラー
HTMLタグでカーソルが同時処理(ミラーリング)されてしまう
DI(依存性注入)
[Ubuntu]Let's Encryptで無料の証明書を利用する
[Apache]Apache2.4のアクセス制限が変更
[Ubuntu]rootのログインとsudo権限追加
タミヤ マイコンロボット工作セットをMacに接続してみた
pgAdimn4 でブラウザで開けなくなる
Java8 を HomebrewとjEnvで構築
Android Studio環境構築 2019
ロケールの再構築
vagrant グループに Apacheを追加
Linux2 Apache2 + PHP7.3 + PostgreSQL10
Anadondaの削除
[Mac]初期設定メモ(CentOS)
[Mac]PostgreSQL起動
FormRequest を利用したバリデーション
try-catch で Exception検知
[Debian]Node.js安定板インストール
Middlewareを利用したルートグループ化
namespaceを利用したルートグループ化
名前付きルートによるリダイレクト
artisanコマンド
IE11以下でclosest() を利用する
Karma と Mochaインストール
コンポーネントを親に登録
[脱jQuery]LoadingOverlay をネイティブで実装
Targetを利用せずに新規ウィンドウを開く(rel,class)
[脱jQuery]ネイティブでDrag&Dropやtableソート
[脱jQuery]$(document).on() をネイティブでコーディング
[Git].gitignore が反映されない
[Git]不要ファイル履歴削除
[GAS]Gmail指定ラベルの不要メール削除
UFJ API(開発用)を利用してみる
RuntimeException No application encryption key has been specified
2020/02/14
icon [Mac]容量を減らす

MacBook Pro 256 で開発やクリエイティブ作業していくと容量が厳しくなってきた。

自分の場合

  • Xcode(iOSシミュレータ含む)
  • Homebrew
  • VirtualBox & Vagrant
  • Docker
  • Adobe Creative Cloud
  • DAW、音楽ライブラリ
  • 写真ライブラリ

がかなり容量を圧迫しています。

ファイルを検索

5G以上のファイル検索


$ sudo du -gxd 5 / | awk '$1 >= 5{print}'

1G以上のファイル検索(現在のディレクトリ)

$ sudo du -gxd 1| awk '$1 >= 1{print}'

これらをもとに、手動で削除

Xcode 端末シミュレータの削除

Xcodeの場合、ツールコマンドを利用する

端末リスト確認


$ xcrun simctl list devices
== Devices == 
-- iOS 13.3 
-- iPhone 8 (69D4A89A-704C-43E0-8C71-6437C551DEB6) (Shutdown) iPhone 11 (DC5B21DE-21CA-4624-8C1C-7CDC349B9DDA) (Shutdown) ... 
-- Unavailable: com.apple.CoreSimulator.SimRuntime.iOS-10-1 
-- iPhone 5 (CE4E79DC-CE71-47A9-B2C8-5F77EE73196F) (Shutdown) (unavailable, runtime profile not found) iPhone 5s (C94451DC-A342-46AE-8E69-52D6DF928E77) (Shutdown) (unavailable, runtime profile not found) 

不要端末削除


$ xcrun simctl delete unavailable

Docker

Dockerは不要なコンテナー、イメージが溜まりがち

イメージ一覧情報を表示


$ docker image ls

不要(none)の情報を表示


$ docker images -f dangling=true

不要(none)の情報を削除


$ docker image rm $(docker image ls  --filter "dangling=true" -aq)

イメージ・コンテナー・ボリュームの情報を表示


$ docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 85 0 18.97GB 18.97GB (100%) Containers 0 0 0B 0B Local Volumes 24 0 80.44MB 80.44MB (100%) Build Cache 0 0 0B 0B

停止中(exited)のイメージ・コンテナー・ボリュームを削除


$ docker system prune

全てのイメージ・コンテナー・ボリュームを削除


$ docker system prune -a

GrageBand 削除

別途DAWを入れているので、Garageband は削除


$ sudo rm -rf /Applications/GarageBand.app
$ sudo rm -rf /Library/Application\ Support/GarageBand
$ sudo rm -rf /Library/Application\ Support/Logic
$ sudo rm -rf /Library/Audio/Apple\ Loops
$ sudo rm -rf /Library/Audio/Apple\ Loops\ Index
2020/02/08
icon DIコンテナはじめ

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
icon freee SDKを Laravel で使ってみる

Freee SDK

ありそうでなかった会計向けSDK
freee が国内初なようで、2020/02時点の対応言語は「C#」「Java」「PHP」

freee API と統制をとるために「OpenApi generator」を利用して有志が開発しているとのこと

C#

https://github.com/freee/freee-accounting-sdk-csharp/

Java

https://github.com/freee/freee-accounting-sdk-java

PHP

https://github.com/freee/freee-accounting-sdk-php/

PHPの場合は、composer で用意されており、さらにサンプル用に Docker & Laravel が公開されている。

サンプルの動作例

freee API

freee API

Docker & Laravel でサンプルを動かす

コールバックURL

freee APIアプリの「コールバックURL」は以下を設定しておく
※デフォルト:urn:ietf:wg:oauth:2.0:oob
※Laravel dでも後に設定する


http://localhost:8000/auth-callback

サンプルダウンロード & 設定

サンプルは SDK の中に入っているので git clone


$ git clone https://github.com/freee/freee-accounting-sdk-php.git

.env を設定する


$ cd freee-accounting-sdk-php.git
$ cd samples/BasicWebApp
$ cp .env.example .env

freeeアプリ の Client ID、Secret ID を記述


FREEE_ACCOUNTING_CLIENT_ID=Client ID
FREEE_ACCOUNTING_CLIENT_SECRET=Secret ID

Dockerの起動

freee-accounting-sdk-php にあるサンプルを利用する

$ cd freee-accounting-sdk-php/samples/BasicWebApp
$ cd samples
$ docker-compose build
$ docker-compose up -d
$ docker exec -it samples_webapp_1 /bin/bash

docker-compose.yaml


version: "3.7"
services:
  console:
    build:
      context: .
      dockerfile: Dockerfile
    image: freee-accounting-sdk-php-console
    volumes:
      - "./BasicConsole:/usr/src/app"
    command: /bin/sh -c "while sleep 1000; do :; done"
  webapp:
    build:
      context: .
      dockerfile: Dockerfile
    image: freee-accounting-sdk-php-webapp
    ports:
      - "80:80"
      - "8000:8000"
    volumes:
      - "./BasicWebApp:/usr/src/app"
    command: /bin/sh -c "while sleep 1000; do :; done"

Dockerfile


FROM php:7.3-cli
RUN apt-get update; \
    curl -sL https://deb.nodesource.com/setup_12.x | bash -; \
    apt-get install -y --no-install-recommends \
        git \
        libzip-dev \
        nodejs \
        unzip \
        zlib1g-dev \
    ; \
    rm -rf /var/lib/apt/lists/*

RUN docker-php-ext-install zip
WORKDIR /tmp
RUN curl https://raw.githubusercontent.com/composer/getcomposer.org/76a7060ccb93902cd7576b67264ad91c8a2700e2/web/installer -o - -s | php -- --quiet; \
    mv composer.phar /usr/local/bin/composer
WORKDIR /usr/src/app
RUN composer global require laravel/installer
ENV PATH /root/.composer/vendor/bin:$PATH
EXPOSE 8000

Composer インストール

webpackが用意されているので、すぐインストールできる


# composer install

composer、Laravel を直にインストールする場合


$ composer require freee/freee-accounting-sdk
$ composer require socialiteproviders/generators
$ composer require socialiteproviders/manager

artisan で socialiteproviders/generators を実行


$ php artisan make:socialite FreeeAccounting --spec=oauth2 --authorize_url=https://accounts.secure.freee.co.jp/public_api/authorize --access_token_url=https://accounts.secure.freee.co.jp/public_api/token --user_details_url=https://api.freee.co.jp/api/1/users/me
$ composer dumpautoload

Laravel/UI を作成


$ composer require laravel/ui --dev
$ php artisan ui vue --auth
$ npm install && npm run dev

Laravel artisanサーバ起動


# php artisan key:generate
# php artisan serve
# php artisan serve --host 0.0.0.0

プロジェクトルートは「samples/BasicWebApp/」

認証処理

routes/web.php


Auth::routes([
    'register' => false,
    'reset' => false,
]);

Route::get('login', 'Auth\LoginController@redirectToProvider')->name('login');
Route::get('auth-callback', 'Auth\LoginController@handleProviderCallback')->name('authCallback');

config/service.php

「client_id」「client_secret」「redirect」をそれぞれ設定 (リダイレクトURLは、freeeのアプリ管理と合わせる)


 'freeeaccounting' => [
        'client_id' => env('FREEE_ACCOUNTING_CLIENT_ID'),
        'client_secret' => env('FREEE_ACCOUNTING_CLIENT_SECRET'),
        'redirect' => 'http://localhost:8000/auth-callback',
    ],

config/auth.php

freee用ドライバー、プロバイダー設定

    'defaults' => [
        'guard' => 'freee',
        'passwords' => 'users',
    ],
....
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
        'freee' => [
            'driver' => 'freee',
            'provider' => 'freee',
        ],
    ],
...
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'freee' => [
            'driver' => 'freee',
        ],
    ],

app\Http\Auth\LoginController.php

ログイン処理は、Laravel Socialite ドライバーを利用し、GenericUser で認証する


use App\Http\Controllers\Controller;
use Illuminate\Auth\GenericUser;
use Illuminate\Support\Facades\Auth;
use Socialite;

...

    public function redirectToProvider()
    {
        return Socialite::driver('freeeaccounting')->redirect();
    }

    public function handleProviderCallback()
    {
        $user = Socialite::driver('freeeaccounting')->user();

        $genericUser = $user->getRaw();
        $genericUser['token'] = $user->token;
        $genericUser['remember_token'] = '';
        Auth::login(new GenericUser($genericUser));

        return redirect()->intended($this->redirectTo);
    }

    public function logout()
    {
        Auth::logout();
        return redirect()->intended('/');
    }

認証用サービスプロバイダー

app/Providers/AuthServiceProvider.php


namespace App\Providers;

use App\Extensions\SampleSessionGuard;
use App\Extensions\FreeeUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
  protected $policies = [
    // 'App\Model' => 'App\Policies\ModelPolicy',
  ];
  public function boot()
  {
    $this->registerPolicies();

    Auth::extend('freee', function ($app, $name, array $config) {
      return new SampleSessionGuard(
        $name,
        Auth::createUserProvider($config['provider']),
        $app['session.store']
      );
    });

    Auth::provider('freee', function ($app, array $config) {
      return new FreeeUserProvider();
    });
  }
}

イベントサービスプロバイダー

app/Providers/EventServiceProvider.php


namespace App\Providers;

use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use SocialiteProviders\Manager\SocialiteWasCalled;
use SocialiteProviders\FreeeAccounting\FreeeAccountingExtendSocialite;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
        SocialiteWasCalled::class => [
            FreeeAccountingExtendSocialite::class,
        ],
    ];

    public function boot()
    {
        parent::boot();
    }
}

SocialiteProviders設定

SocialiteProviders/src/FreeeAccounting/Provider.php

https://api.freee.co.jp/api/1/users/me からユーザを返す関数を作成


    protected function getUserByToken($token)
    {
        $response = $this->getHttpClient()->get('https://api.freee.co.jp/api/1/users/me', [
            'headers' => [
                'Authorization' => 'Bearer '.$token,
            ],
        ]);

        $body = json_decode($response->getBody(), true);
        return $body['user'];
    }

User のマッピング


    protected function mapUserToObject(array $user)
    {
        $user['name'] = $user['last_name'] . ' ' . $user['first_name'];
        return (new User())->setRaw($user)->map([
            'id'       => $user['id'],
            'name'     => $user['name'],
            'email'    => $user['email'],
            'display_name' => $user['display_name'],
            'first_name' => $user['first_name'],
            'last_name' => $user['last_name'],
            'first_name_kana' => $user['first_name_kana'],
            'last_name_kana' => $user['last_name_kana'],
        ]);
    }

事業所と取引(収入/支出)一覧の取得

app/Http/AccountController.php

ログイン認証したユーザトークンを、Configuration クラスに設定


$user = Auth::user();
$config = Configuration::getDefaultConfiguration()->setAccessToken($user->token);

ちなみに、getAccessToken() でアクセストークンを確認できる。

$config->getAccessToken()

CompaniesApi で事業所IDを取得


$companiesApiInstance = new CompaniesApi(null, $config);
$companiesResponse = $companiesApiInstance->getCompanies();
$targetCompanyId = $companiesResponse->getCompanies()[0]->getId();

DealsApi で取引(収入/支出)一覧の取得


$limit = 5;
$dealsApiInstance = new DealsApi(null, $config);
$dealsResponse = $dealsApiInstance->getDeals(
            $targetCompanyId,
            null, null, null, null, null, null, null, null, null, null, null, null,
            $limit);
$deals = $dealsResponse->getDeals();

getDeals() の引数がちょっとどうなんだろ?

<< 最初 < 前ページ 次ページ > 最後 >>