php+sqliteをdockerで動かすメモ

dockerの練習用にphp+sqliteなサーバを作ってみたのでメモ

Dockerfile

FROM php:5.6-apache
RUN apt-get update && apt-get install sqlite3 libsqlite3-dev -y

build

docker build ./ -t php5_sqlite

run

docker run -d -p 80:80 -v /Users/fujitanao/git/htmlonly/html:/var/www/html --name php5_sqlite_container php5_sqlite

stop

docker stop php5_sqlite_container

start

docker start

container remove

docker rm php5_sqlite_container

markdownで書いたテーブル仕様書からsql文を生成する

テーブル仕様書をmarkdownで管理したいって要望があったので作ってみた
まだ開発中。markdownから階層構造作るところで多分バグがある

サンプルのテーブル仕様書はこんな感じ

contract: 契約

contract_state: 契約状態テーブル

カラム名 NOT NULL 補足 index 説明
contract_id VARCHAR(13) o AUTO_INCREMENT PRIMARY KEY 契約ID
state VARCHAR(10) o contract_state 契約状態

extra: その他

term

extra_start_e: その他開始イベント

カラム名 NOT NULL 補足 index 説明
contract_id VARCHAR(13) o PRIMARY KEY 契約ID
start date o extra_start 開始日

extra_end_e: その他終了イベント

カラム名 NOT NULL 補足 index 説明
contract_id VARCHAR(13) o PRIMARY KEY 契約ID
end date o extra_end 終了日

extra_state: その他状態テーブル

カラム名 NOT NULL 補足 index 説明
contract_id VARCHAR(13) o AUTO_INCREMENT PRIMARY KEY 契約ID
state VARCHAR(10) o extra_state 契約状態

ここからCreateTable文を生成する
以下、動作確認
RUNボタンを押してね

See the Pen WyNgdx by なおしむ (@naosim) on CodePen.

集中したい

最近全然時間がありません
打ち合わせや割り込みがない時間が1日のうちで連続3時間ほしい...

今日の作業

10:00-10:30 ★FREE
10:30-11:30 MTG
13:00-14:00 MTG
14:00-15:00 ★FREE
15:00-16:00 ペア作業
16:00-17:00 MTG
17:00-18:00 ★FREE

こんなんじゃ集中して作業できねぇよ

TRY: 打ち合わせを15時までにする

15時以降をフリーにする

jsのクラスってコンストラクタに全部書いた方がよくね?

jsのクラスはこんな感じで書きます

class Position {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  getX() {
    return this.x;
  }

  getY() {
    return this.y;
  }

  getDistance() {
    return Math.sqrt(this.x * this.x + this.y * this.y);
  }
}

この書き方の辛いところ

  • フィールドをprivateにできないからxとyが外から丸見え。セッター呼び放題
  • フィールドが増えるたびにthis.v = v;をコンストラクタに書く必要がある

それならこっちの方がよくね?

class Position {
  constructor(x, y) {
    this.getX = () => x;
    this.getY = () => y;
    this.getDistance = () => Math.sqrt(x * x + y * y);
  }
}

辛いところは全部解消されてる

しかもコンストラクタ引数をconstな変数に入れたらimmutableにもできる

class ImmutablePosition {
  constructor(_x, _y) {
    const x = _x, y = _y;
    this.getX = () => x;
    this.getY = () => y;
    this.getDistance = () => Math.sqrt(x * x + y * y);
  }
}

どや

マルっとサクッとパラメータを受け取る

最近PHP+slimでAPIをたくさん作ってますがAPIの実装が面倒になってきた
たとえばアクセストークンを使って認証的なことをやろうとした場合、IF仕様はこうなる

アクセストークンは、リクエストヘッダー、または、GETの場合はクエリーパラメータ、または、POSTの場合はbodyに入れること

いろんなところから取得しなきゃでめんどくせーー

欲しいのはパラメータ

で、欲しいのはそのパラメータであって、それがヘッダーだろうとなんだろうと別にどうでもいい
なのでパラメータの取得方法を考えなくてもよくするミドルウェアを作った

$app->add(function ($request, $response, $next) {
  $params = [];
  forEach($request->getHeaders() as $key => $value) {
    $params[$key] = $value;
  }
  if($request->getQueryParams() != null) {
    forEach($request->getQueryParams() as $key => $value) {
      $params[$key] = $value;
    }
  }
  if($request->getParsedBody() != null) {
    forEach($request->getParsedBody() as $key => $value) {
      $params[$key] = $value;
    }
  }
  
  $request = $request->withAttribute('params', $params);
  return $next($request, $response);
});

取得するときはこんな感じ

$params = $request->getAttribute('params');

APIの実装が楽になった
めでたし、めでたし

データを保存できるWebAPIを作ったら楽になった

最近は無料で使えるナントカ as a serviceが増えてきて、サービスを簡単に作れるようになって楽しい
例えばロジックはheroku + javaで堅牢に作れるし、定期実行はgoogle apps script(以下、GAS)でできる
あと足りないのはデータストア

てことで自分の身の回りでデータストアとして使えそうなものを探したら、サクラのレンタルサーバがあった!
プランがライトプランなのでsqliteしか使えないけど、なんとかなるはず!
てことで、データストア的なwebサービスを作ってみた

仕様

要するにwebAPI経由でデータの追加・更新・参照ができるサービスです
詳細はこんな感じ

  • IDと状態を保存できる
  • 状態を更新できる
  • ID指定で状態を取得できる
  • 過去の状態遷移履歴も取れる
  • データは投入から1ヶ月で消える
  • 認証はリクエストに固定のトークンを入れることで行う
  • 環境: PHP + slim + SQLite

データが1ヶ月で消える仕様がミソ
sqliteだから大量データを保持したくないって理由もあるけど、実際1ヶ月くらい保持してくれるだけで十分なサービスがたくさんあるのでこの仕様で問題なし

利用例:ブログ更新通知サービス

せっかくなのでデータストアを使ったブログ更新通知サービスを作ってみた
使うのはGAS

基本的に定期的にRSSをクロールしてチャットに通知すればイイだけですが、すでに通知済みの記事は通知して欲しくない
そうなると通知したものを貯めるデータストアが必要になる
そこで今回作ったデータストアを使う
通知した記事のIDをデータストアに保存して、次回クロール時はデータストアにすでにあるかを確認してなかったら通知する
1ヶ月でデータが消える仕様があるので、翌月に同じ記事を通知してしまう可能性はあるけど、そこは日付見て「1ヶ月以上たった記事は通知しない」て処理いれれば問題なし

ロジックをまとめるとこんな感じ

  • 定期的にRSSを取得する
  • 記事の投稿日時が1ヶ月以内のものを抽出する
  • 記事IDでデータストアに問い合わせてチャットに通知済みかどうかをチェックする
  • 未通知だったら
    • 記事をチャットに通知する
    • データストアに通知済みとして保存

作った

GASで簡単に作れた
このデータストアは汎用的に使えて良さそう
APIのインターフェースとか認証周りとかをもう少し整理して公開できる状態まで持っていきたい
認証サービスを作ればいいのか?
結局AWSみたいにマイクロサービスがたくさん作られそうな予感

まとめ

データストアサービスを作ったら新たなサービス作りが簡単になった
この他にもマイクロサービスのアイデアがいくつか浮かんで楽しくなってきた

PHPで1970年からのミリ秒を取得する

サーバサイドをPHP + SQLiteにしてフロントをjavascriptで作るなら、日時はlong型で1970年からのミリ秒にしておいた方が良さそう でもPHPの標準関数でその値を取得する方法がなかったのでメモ 使えそうなものが2つ見つかった

現在日時から取得

$t = (int)floor(microtime(true) * 1000);

リクエスト日時から取得

$t2 = (int)floor($_SERVER['REQUEST_TIME_FLOAT'] * 1000);