Technote

by sizuhiko

BracketsにLSPがやってきた

やぁやぁやぁ、LSPがやってきたよ!

Brackets 1.14 has landed!というブログ記事にも書かれているように、今回のリリースの目玉はLSP(Language Server Protocol)のサポートです。

ついにBracketsにもLSP対応が入りましたね。これまでAtomとはVS Codeに遅れをとっていましたが、これで色々なプログラミング言語でも利用しやすくなるはずです。 詳しくはリリースノートにも書かれています。

対応したissueを見ると、 Move vscode-languageserver-protocol to Thirdparty と書いて有るので、vscodeの実装を参考にしたようです。

Language Server Protocol Support in Bracketsのページにアーキテクチャの解説や、LSP拡張を実装する場合の方法について解説があるので現時点 PHP, Python, TypeScript だけのサポートのようなので、それ以外の言語にも対応させようと思ったときに役立ちそうです。

私の手元のBracketsもさっそくアップデートしました。

さっそく使ってみよう

アップデートをインストールしたら、環境設定を開きます。 すると、2ペイン表示になるので、左側(defaultPreferences.json)から php で検索します。 以下のようなデフォルト設定になっているはずなので、コピーして右のペイン(brackets.json)に貼り付けます。

    // PHP ツールのデフォルト設定
    "php": {
        // デフォルト: true
        "enablePhpTooling": true,

        // デフォルト: php
        "executablePath": "php",

        // デフォルト: 4095M
        "memoryLimit": "4095M",

        // デフォルト: false
        "validateOnType": "false"
    },

右ペインにコピーしたらコメント行は削除してくださいね。忘れるとJSONのパースエラーになります。

ここで重要なのは executablePath の設定です。 もしシステム(OS)に入っているPHPが7以上であれば問題ないのですが、デフォルトが7以上でない場合は、ここを書き換える必要があります。

たとえば私はphpbrewで複数バージョン切り替えているので、たまにPHP5.5とかに変更しますので、以下のように固定パスを指定するように変更します。

    "php": {
        "enablePhpTooling": true,
        "executablePath": "/Users/sizuhiko/.phpbrew/php/php-7.3.1/bin/php",
        "memoryLimit": "4095M",
        "validateOnType": "false"
    }

これからは、Bracketsを使ったPHPアプリケーション開発も快適になりますね!

Polymer.co-edo day 2019 春を開催しました

2019年4回目となる Polymer.co-edo ミートアップ を開催しました。

edo-blogcardに最初のコードをアップしました。 developブランチにpushしています。

まだ何も動きはないのですが、LitLoader を使ってビルドするところまで実装しています。

ES Module import との戦い

Web Components はHTMLファイルからだと以下のように読み込みます。

<script type="module" src="node_modules/xx-element/xx-element.js"></script>

独自のカスタムエレメントから別のエレメントを利用する場合は、以下のように記述します。

import '@polymer/iron-ajax/iron-ajax.js';

ここでブラウザは @polymer/iron-ajax/iron-ajax.js のようなパスを解決できないため、webpackでコンパイルすることが必要になります。 この話は、以前の記事PHPer Kaigi 2019に参加しましたでも書いているとおり、import maps待ちな状況です。

2つのビルド結果

そこで、2つのビルド結果を保持するようにしました。

/dist/edo-blogcard.js

これは

import '@edo-elements/edo-blogcard/dist/edo-blogcard.js';

のように利用するためのビルド結果で、LitLoader形式で記述された .lit ファイルを .js にコンパイルしたものです。

/dist/edo-blogcard.bundle.js

これは

<script type="module" src="node_modules/@edo-elements/edo-blogcard/dist/edo-blogcard.bundle.js"></script>

のように利用するためのビルド結果で、HTMLからブログパーツとして利用したい(webpackなどを実行しないWebページで使いたい)場合のためにコンパイルしたものです。 LitLoaderとwebpackを使ってHTMLから利用可能な状態になっています。

工夫したところ

後者の bundle.js については、普通にLitLoaderとwebpackを使うやり方なので、特にはありません。 LitLoaderはwebpackのloaderとして実装されているので、configに設定を追加するだけです。

一方前者はwebpackのloaderようにできているLitLoaderを、webpack使わずにどうやって呼び出すか?というところを工夫しました。

それが build.js です。 そして loader-runner という webpack のモジュールを使っています。 このモジュールは Runs (webpack) loaders という説明のとおり、loaderを実行することに特化しています。

const fs = require("fs");
const path = require("path");
const { runLoaders } = require("loader-runner");

runLoaders(
  {
    resource: path.resolve(__dirname, "edo-blogcard.lit"),
    loaders: [require.resolve("lit-loader")]
  },
  function(err, result) {
    if (err) throw err;
    fs.writeFileSync("dist/edo-blogcard.js", result.result[0]);
  }
);

これだけで .lit ファイルを .js ファイルに(webpackなしで)コンパイルできます。

次回

通常どおりの、もくもく会として開催予定しています。 皆様の参加をお待ちしております。

Doorkeeperのコミュニティページ

PSR-17 HTTP Factories のライブラリ

令和最初の記事も、PHP。 この記事はPSR-15リクエストハンドラーのライブラリ比較の続編です。

前回のサンプルプログラムでは zendframework/zend-diactorosHTTP Message Factories を使って PSR-7のHTTPレスポンス(Psr\Http\Message\ResponseInterface)を作っていました。

今回は、他のライブラリを使っても大丈夫か考えてみたいと思います。

PHP-17 の HTTP Factories に対応したライブラリ

PackagistでPSR-17を検索してみました。 PSR-15ほどはないようです。ということで独断と偏見(ダウンロード数が多いもの)を選んで比較してみたいと思います。 なお「フレームワーク」と書いてあるものや、特定のPSR-7ライブラリ だけ に依存したもの(たとえばhttp-factory-guzzleなど)は除外しています。

それぞれのライブラリの説明を読んで気づくでしょう。

PSR-17 HTTP-Factory with auto-discovery support

そう先ほど「特定のPSR-7ライブラリ だけ に依存したもの」と書きましたが、実は特定のライブラリに依存します。 それはそうですよね。PSR-7のHTTPレスポンスインターフェースの実装インスタンスを 生成 しないといけないので、何かしらに依存します。

ただ、こういった auto-discovery してくれるライブラリを使っておくと、PSR-7のライブラリを変更したときも影響が少ないですね。 でもそれ、さっきのサンプルで DI してたから、それで良くない?というのは、まさにそのとおりです。

で、結局どうすると良いの?

  • PSR-7/PSR-11/PSR-15/PSR-17 を使うアーキテクチャにするなら、FactoryInterfaceをDIすれば影響範囲は設定箇所だけになります
  • PSR-7/PSR-15/PSR-17 を使う(PSR-11を使わない)アーキテクチャにするなら、上記のような PSR-7 を自動判定してくれるライブラリを使うと良い

ということになると思います。

それならPSR-7のライブラリも使い分けたサンプルが見たかった!とかあるかもしれませんが、それはまた今度!(機会があれば)

おまけ

さて、PSR-7/PSR-15/PSR-17 の話は面白かったですか? これに加えて、フロントエンドも含めてフレームワークに依存しないアプリケーションとは? みたいな話をPHPカンファレンス福岡2019でします。 午後一のセッション。また @soudai1025 の裏になりましたが、私の方がマニアックな話なのかな。

では6月に福岡でお会いしましょう!

PSR-15リクエストハンドラーのライブラリ比較

平成最後の記事は、PHP。 久々のPHP記事ですが、PSR-15に準拠したリクエストハンドラーライブラリの実装を比較してみようと思います。

PSR-15とは?

HTTPメッセージを使用するリクエストハンドラーと、ミドルウェアコンポーネントの共通インターフェースです。

それPSR-7なのでは?という鋭い人は、 @tanakahisateruさんのスライド PHP-FIGのHTTP処理標準の設計はなぜPSR-7/15/17になったのかを参照ください。

PSR-7については、だいぶ知れ渡っていると思うので、PSR-15のリクエストハンドラーに着目していきます。

PHP-15のリクエストハンドラーに対応したライブラリ

PackagistでPSR-15を検索してみました。 たくさんありますね。ということで独断と偏見(ダウンロード数が多いもの)を選んで比較してみたいと思います。 なお「フレームワーク」と書いてあるものは除外しています。 例えば zend-expressiveminimalist PSR-7 middleware framework for PHP と書いてあるとおりなので。 Slimなどのマイクロフレームワークも同様です。

の4つを使ってサンプルプログラム集を作ってみました。

sizuhiko/psr15-requesthandler-examples

PSR-7

まず前提事項として、PSR-7対応のライブラリが必要です。 本サンプルでは、主に zendframework/zend-diactoros を使っています。 sunrise/http-routerの例ついては、同系統にsunrise/http-messagesunrise-php/http-server-requestがあるので、それを利用しています。 PSR-7のライブラリが違うと、どのような記述の違いがあるのかわかりやすいでしょう。

サンプルの内容

サンプルプログラム集clone するか、ダウンロードして、READMEの手順に従ってください。

ドキュメントルート(/)にアクセスすると、Hello, World! 出すだけの簡単なものです。

サンプルコードの流れ

で、結局PSR-15とは?みたいな話になるわけですが、どの例も以下のような流れで動いています

  • PSR-7 でHTTPリクエスト(Psr\Http\Message\RequestInterface)を受け取る
  • PSR-15の Psr\Http\Server\MiddlewareInterfacePsr\Http\Server\RequestHandlerInterface でいい感じに PSR-7のHTTPレスポンス(Psr\Http\Message\ResponseInterface) を生成する。
  • PSR-7 のHTTPレスポンスをエミットする

つまり、真ん中の部分を処理することになります。

リクエストハンドラ

サンプルのsrcフォルダの下には

  • Middlewares
  • RequestHandlers

があり、それぞれ Psr\Http\Server\MiddlewareInterfacePsr\Http\Server\RequestHandlerInterface を実装したクラスが置いてあります。 で、それぞれのリクエストハンドラーからは、適したハンドラが呼び出されるようになっています。

このサンプルでは PSR-17 (HTTP Factories) を先行導入し、PSR-11 (Container Interface) に対応したライブラリでDIしてますが、 そのあたりは、次回以降で解説します。

ミドルウエアもリクエストハンドラも同じようにHello, World!をレスポンスボディに入れるだけです。

このサンプルをとおして言いたかったこと

このサンプルでは、ドキュメントルートだけの簡単な実装でしたが、ルーターの設定を追加するだけで、 実際のアプリケーションでも使えるようになることがわかると思います。

もちろん実際にはDBにアクセスする必要もあったりするわけですが、そこにはPHP Data Objects(PDO)があり、 実際のDBの差分を吸収してくれます。 そこで利用するSQLは標準であり、Webの標準よりも長い期間利用されています。

フレームワークを利用してアプリケーションを作ることは、速く簡単に構築できます。 しかしフレームワークに依存せずPHPの標準を使うことで、柔軟にライブラリを変えても、自分のビジネスロジックを流用することができるようになります。

もちろん今日のフレームワークの多くが PSR 対応を進めていますので、フレームワークを使っていても、より互換性が高いアプリケーションを作ることができるようになるかもしれません。

次回はPSR-17について、いくつかのライブラリを紹介します。

アスカン2019を開催しました

明日の開発カンファレンス2019の中の人として運営参加しました。

私はプログラム枠1つを決めたり、事前準備をお手伝いしたり、当日雑用したりと、まぁ大したことはしてません(汗

私の渾身のオススメ枠、ということで今回は弊社岡島から「総売り上げ:35,400円 ~ 受託エンジニアが自社サービスのPOをやって学んだこと。」という発表をしてもらいました。 直前のセッションが、ヴェルク株式会社 田向 祐介さまの「受託開発の会社が自社サービスを立ち上げて軌道に乗せるまでの取り組み」だったこともあり、受託開発会社のサービス開発成功事例からの、失敗事例ということで、プログラムの流れも良かったと思います。

また今回のアスカンでは、はじめての2トラックということで、たくさんの事例をご紹介することができたと思います。

当日の様子は、Togetterにまとまっています。

@akiko_pusuさん、@NEKOGETさんが、グラレコを投稿してくれていますので、よりトーク内容含めてふりかえってもらえると思います。

昨年は秋にも開催したアスカンですが、今年はどうなるでしょうか?

そうそう、最後にアンケートもありますので、参加したみなさま、スピーカーやスタッフのためにも回答をお願いしたします。