ログ日記

作業ログと日記とメモ

スタートアップがPHPを使っていると聞いた話

この前、外国のスタートアップをやっている人にサービスを見せてもらった。
Qiitaによく書かれているような新しめのフロントエンドの技術盛り沢山で、クラウドや聞いたことのないようなサービスからTrelloのような知っているサービスなど色々使いつつ、なんかセンサー集計っぽい感じのWebが今風の画面でデザインされていた。他にもいくつかプロジェクト?があった。
VPNで海外の拠点に繋いで、遅いなーとか言いつつ。日本語は片言だったのであまり詳しくは聞けてないんだけど。
そういやブロックチェーンもやっていると言っていた。
よくある日本の零細企業ベンチャーじゃなくてガチのスタートアップや…とか思いつつ。

それで位置情報を使うからPostgreSQLを使っているだとか聞いて、あ、ネットで見た話だ、とかも思いつつ。


サーバーサイドは何?って話になって、PHPSymfonyだって聞いてびっくりした。
あれ?人気ないの日本だけ?
PHPは日本で?あまり人気ない感じなんですよねーとか言って、そうなの?なんでだろうね?なんて。
いや、そりゃーWordPressがあるから使われてる数で言ったら多いんだろうけど、新しいことやってる人にPHPは選択肢に上がってこないイメージだった。


まあ実際は驚きつつも、WebならPHPが一番手っ取り早いし、LaravelとかじゃなくてもSymfonyで十分というか、DBに近い部分で変に新しいものを選んだらメリットよりデメリットの方が大きいとか、PostGIS使うなら主流のORMの恩恵あまり無いよねとか、ロジックはどんどんフロントエンドに行くからPHPで複雑なプログラミングはしないよねとか、色々思いつつ。

そんな話を聞いたあとに
https://qiita.com/dossari-book-archive/items/ad4f7bcaaebca6281154 こことか
https://qiita.com/charmston/items/df31a419a4e57ebe86ba こことか読んで、ちょっともやもやした。


ただPHPは言語自体を勉強するという感じのものではないのは確かだし、たぶんそのスタートアップの人もPHPでこんな面白いプログラムを作った!とは言わないと思う。知らんけど。


自分も毎日PHP書いてるけど、特に記事に書くようなこともなく。
PHPで関数の末尾呼び出しを最適化する - Qiita 書いてもネタみたいになっちゃう。
本当はネタじゃなくて真面目にHTML解析タイプのテンプレートエンジンを作りたいんだけども。今は使いどころがないんよね。10ページ程度のサイトをいくつも作るような会社に居るなら完成まで作ったのかもしれない。

あ、DIコンテナ https://github.com/nishimura/simple-container とか https://github.com/nishimura/db-migration DBバージョン管理ツールは最近作ったんだった。作ったというか、作っていたものを小さく整理した。
最近はとにかくシンプルにしようと思っていて、たかだかコンテナやDBツールで何ファイルも何千行もあるライブラリを読み込むのは無駄じゃん?と思って必要な機能だけ切り出した感じ。なので特に書くことが無い。


そういうわけで、PHPは新しい環境でも普通に使われているけど使われ方が普通すぎて特にアピールすることもないので不人気に見えるのでは?とか思った。
ぐだぐだ書いておいてn=1だけどね。


最近のPHPは、スカラー型からnullableな型、そしてついにTyped Properties とか、かなり大きな変更の流れですごいことだと思ってるんだけど、便利な新機能!ってことじゃなくてじわじわくる感じだからなあ。
LaravelでURLルーティングからの引数に直接DB Entityを差し込むやつ、あれのプロパティ版がはかどるんじゃない?と思ってるんだけど。
そのDB Entityも型があったらDBのnullableをそのままマッピングできて、JavaっぽいのにJavaよりすごくない?とか。


オレオレフレームワークばかりだった頃からLaravelとかCakePHPとかSymfonyとかに統一されてきて(それでも数が多いけど)、何かPHPの記事を見かけてもライブラリの使い方の説明だけなのが寂しい感じはある。

うーん、なんだかまとまらないままポスト。

php-modeとyasnippetを更新した

最近の無名関数が綺麗にインデントされるようにemacsphp-modeを更新した。


https://github.com/ejmr/php-mode.git
これをcloneして使っていたのでpullしただけ。


Emacs23だとうまくいかなかったのでEmacs24に更新。

apt-get install -t wheezy-backports emacs24

cd /etc/pkcs11/modules/
mv gnome-keyring-module gnome-keyring.module

下のコマンドは、一緒にアップグレードされるパッケージにミスがあるようなので。


yasnippethttps://github.com/capitaomorte/yasnippet ここからcloneしてmasterで使ってる。
yasnippetphp-modeは https://github.com/nishimura/minimal-yasnippet-php-mode 自分で書いたやつ。バックスラッシュのエスケープが多重に要らなくなったようなので修正した。
nameと書いてタブ押すぐらいしか使ってないけど。

Composerの検索をローカルにする

いつも忘れるのでメモ。


あらかじめ外部ライブラリはローカルにgit cloneしておく。



composer.json

    "repositories": [
      {"type": "vcs", "url": "/home/user/repo/my-framework"},
      {"type": "vcs", "url": "/home/user/repo/my-lib"},
      {"type": "vcs", "url": "/home/user/repo/Aura.Session"},
      {"type": "vcs", "url": "/home/user/repo/zend-diactoros"},
      {"type": "vcs", "url": "/home/user/repo/http-message"},
      {"packagist": false}
    ],

packagist: false で指定。


そうすると、ちょっとしたライブラリを自分で作ってるときに、それを更新してもいちいちネットワークを検索せずにすむ。
また、普通に使うときにも、あらかじめローカルにcloneしておけば全パッケージを探さなくて良いので更新が早い。依存関係が増えた場合などは自力で一つずつcloneしていかないとダメだが、そっちの方が早い気がする。

今更PHPでモナド的なものを書く

http://blog.dakatsuka.jp/2013/09/03/php-maybe-monad.html
この辺とか
http://d.hatena.ne.jp/kazu-yamamoto/20110413/1302683869
この辺とか見てたらちょっとやってみたくなったので。


○○言語でMonad実装って結構あるけど、MonadPlus使えないとあまり意味ないよね?的なところもある。


上記URLのTree探索するやつの

msearch :: MonadPlus m => (Int -> Bool) -> Tree -> m Int

これ、型推論、テンプレート、ジェネリクス、戻り値の型がないPHPでは無理目なので、コンテキスト(MonadPlus m)を引数として渡すことにする。
traitがあればreturnやmzeroを共通化できるので多少マシじゃないかな?と思いつつ。

<?php
    private function searchTree(Context $m, callable $f, Tree $tree)
    {
        if ($tree instanceof EmptyTree)
            return $m->mzero();
        if ($f($tree->value))
            return $this->searchTree($m, $f, $tree->left)
                        ->mplus($m->ret($tree->value))
                        ->mplus($this->searchTree($m, $f, $tree->right));
        else
            return $this->searchTree($m, $f, $tree->left)
                        ->mplus($this->searchTree($m, $f, $tree->right));
    }

    private function getTree()
    {
        $empty = new EmptyTree();
        return new Tree(3,
                        new Tree(2, $empty, $empty),
                        new Tree(1, $empty, $empty));
    }

    public function testTreeDataList()
    {
        $c = new DataListContext();
        $f = function($a){ return $a % 2 == 1; };
        $t = $this->getTree();
        $ret = $this->searchTree($c, $f, $t);
        $this->assertEquals(Cons::fromArray([3,1]), $ret);
    }
    public function testTreeMaybe()
    {
        $c = new MaybeContext();
        $f = function($a){ return $a % 2 == 1; };
        $t = $this->getTree();
        $ret = $this->searchTree($c, $f, $t);
        $this->assertEquals(new Just(3), $ret);
    }
https://github.com/nishimura/laiz-monad/blob/master/test/src/Laiz/Test/Monad/ContextTest.php

タイプ量が多い…。
traitってこういう使い方で良かったんだっけ?ファイルの置き場所とかセオリーが分からん。
composer.json置いてるけど未登録。

ぼんやり振り返り

顧客は本当に欲しいものは知らない、と言うけれど同じような症状だ。
かゆいところに手が届かない。



自作フレームワークがつぎはぎになってきたのでカッとなって作ったやつ。
PHPの小規模用テンプレートエンジンを作った - より良い環境を求めて


なんかアノテーションがマイブームだったっぽい。
PHPのフレームワークを作った - より良い環境を求めて
ただ利用しているZendのアノテーション解析が、あるバージョンでとても遅くなったので、アノテーションを使うことに不安を覚える。
言語レベルでやることをPHPで頑張ってやるべきじゃないな、などと思い直す。
@varアノテーションによるリクエスト変数のcastは結構便利だったんだけど。



ふと、Haskellっぽく書きたいよなー、前にそういうこと書いたよなーと思い出す。
バリデーターあれこれ - より良い環境を求めて
やっぱり書いてた。
ロジックの中の方でDBを呼び出すのは良くないよね、という話。


バリデーター繋がりで、Scalaでも何か書いてたなーと思い出す。
LiftでWebアプリ(4): フォーム用共通処理を作る 1 - より良い環境を求めて
この投稿の最後の方のコード、今見てもこんな風に書きたいなーと思える。
演算子が定義できないとどうしようもない…かな?


例えば、こんなの。

<?php
class SomePage{
  public function somePost(Request $req, Db $db){
    $form = $req->fragment('form1');
    $form->key('mail')->name('メールアドレス')
      ->trim()->required('{name}を入力してください')
      ->email('{name}の形式{input}が正しくありません');
    $form->key('body')->required('本文を入力してください')
      ->maxLength(1000, '{param0}文字以上は送信できません');
    $form->key('zip1')->key('zip2')->name('郵便番号')
      ->toHalf()->required('{name}を入力してください')
      ->length([3, 4])->numeric('{name}の形式が正しくありません');

    try {
      $values = $form->get();
      $account = $db->from('Account')->eq(['mail' => $values->mail])->getOne();
      ....
    }catch (IoException $e){
      $errors = $e->getErrors();
      ....
    }
  }
}

万能RequestクラスをTraitの寄せ集めで作って、Eitherの変わりに例外にして…。うーん…。
やっぱり演算子や結合がないとタイプ量が多い。


で、PSR-7もあるのでどうしようとか。



アプリは、Input => App => Output っていうのは確定で、これは
Request => App => Response に置き換えるとちょっとまずい。Outputがそのまま次のInputになった方がシンプルになりそう。
正確には Context & Request => App => Request | Response かなあ。
アプリがRequestを返したらリダイレクトなどをして、Responseを返したら終了。
いや、でもテンプレートエンジンを使うだろうしやっぱりResponseを返すのは特殊な場合だけになるのか。





まとまらないけど眠いので一旦投稿。

流れるようなインターフェースをtraitで

ぼんやり思ったことのメモ。


たとえばDB接続なら

<?php
$item = Item::select()
              ->from('item')
              ->join('category')
                ->on()->over(['category.status' => 'item.status'])
              ->like(['name' => 'my item'])
              ->order('code')
              ->offset(100)
              ->limit(10)
              ->get();

とかやりたい。
今までさくっと実装しようとすると、メソッド全部入りのDBクラスを作れば良かったんだけども、traitを使うと各メソッドを細切れで作っておいてtraitで

<?php
class CalledSelect
{
  use Join;
  use Where;
  use Order;
  use Get;
  use Offset;
}
class CalledFrom
{
  use Join;
  use On;
  use Where;
  use Order;
  use Get;
  use Offset;
}
class CalledWhere
{
  use Order;
  use Get;
  use Offset;
}

のようにすると、選べるメソッドが制限されて書きやすいんじゃないかと。PHP7では戻り値も書けるようだし。( https://wiki.php.net/rfc/return_types )
まあ今はIDE使ってないし恩恵ないんだけども。

Debian wheezyにphpenvでPHP複数バージョンの共存

かなりハマったのでメモ。


基本は
http://qiita.com/uchiko/items/5f1843d3d848de619fdf
こちらを参考に、一般ユーザー権限で操作する。

git clone https://github.com/CHH/phpenv.git
phpenv/bin/phpenv-install.sh 

mkdir ~/.phpenv/plugins
cd ~/.phpenv/plugins
git clone https://github.com/CHH/php-build.git

# rcファイルを編集後、読み込み

http://tkuchiki.hatenablog.com/entry/2014/04/08/210022
こちらを見ながら、該当個所の apxsをapxs2に変更しつつ修正。


ちなみにapxs2コマンドは apache2-threaded-dev にある。


で、root権限がないと設定ファイルのコピーでパーミッションエラーが出る。

phpenv install 5.5.14

# エラー終了

cd ~/.phpenv/versions/5.5.14/
mkdir libexec
cd /tmp/php-build/source/5.5.14
make
make install

# エラー終了

make install-modules install-binaries install-build install-headers install-programs install-pharcmd

これで一応libphp5.soは出来るので、 /etc/apache2/mods-available/php5.load を変更すればバージョンを変えられる。
パーミッションエラー以外にも何かエラーがある気がする。もやもやしたまま一旦終了。