ミヤギの外付けハードディスク

アウトプットの練習の場です。ミヤギの思ったことをつらつらと書きます。

PHP 8.5 が出たので、パイプライン演算子を使ってログ整形ツールを書いてみた

※ この記事は PHP Advent Calendar 2025 の 15 日目の記事です。

はじめに

今回は新しい取り組みとして、はてなブログでエンジニアっぽいことを書きます。
ソースコードとか書かれていて、エンジニアじゃない方にはよくわからない内容になってるかと思うのでご了承くださいください。。🙇‍♂️
( 今までずっとポエムを書いていたので、違和感すごいと思います )

ということで、本題です。

PHP 8.5 が出ましたね!

実はわたし、一応 PHPer です。

今回のアップグレードの目玉機能である パイプライン演算子に興味があったので、使ってみることにします。
本ブログでは、文字列操作が必要な "ログ整形 CLI ツール" を作ります。

ログの準備

今回は NDJSON 形式で用意します。

{"ts":"2025-12-14T09:10:11Z","level":"info","msg":"request ok"}
{"ts":"2025-12-14T09:10:12Z","level":"warning","msg":"slow query"}
{"ts":"2025-12-14T09:10:13Z","level":"error","msg":"failed to connect"}

小さい関数を用意する

PHP 8.5 の パイプライン演算子は「関数の出力をそのまま次へ渡す」構文です。 まずは処理を小さな関数に分けてみます。

$readAll = fn(?string $path): string =>
    ($path && $path !== '-') ? (file_get_contents($path) ?: '') : stream_get_contents(STDIN);

$toLines = fn(string $s): array => array_filter(explode("\n", $s));

$decode = fn(array $lines): array =>
    array_map(fn($l) => json_decode($l, true), $lines);

$format = fn(array $rows): array =>
    array_map(fn($r) => sprintf("[%s] %-8s %s",
        $r['ts'], strtoupper($r['level']), $r['msg']
    ), $rows);

$join = fn(array $lines): string => implode(PHP_EOL, $lines) . PHP_EOL;

どれも短い処理です。 「 1 つの関数が 1 つの役割だけ持つ」というルールで書くと、後でつなぎやすくなります。

パイプでつなぐ

あとはこれらをパイプでつなぐだけです。

$path = $argv[1] ?? null;

$path
    |> $readAll
    |> $toLines
    |> $decode
    |> $format
    |> $join
    |> print(...);

ファイルを読む → 行に分ける → JSON に変換 → 整形 → 出力 という処理の流れがそのまま見えます。

ネストも中間変数もなし。 見た目がすっきりして、頭の中で流れをトレースしやすいですね。

少し発展:--last オプションで最後のエラーだけ出す

せっかくなので、PHP 8.5 で追加された array_last() を使って、「 最後のエラーだけ出す」機能も足してみました。 仕様は以下の通りです。

  • 通常時:error 以上のログを すべて出す
  • --last を付けたときだけ:最後の 1 件だけ出す

エラーログを絞る関数

$filterErrors = fn(array $rows): array =>
    array_filter($rows, fn($r) =>
        in_array($r['level'], ['error', 'critical'], true)
    );

--last があるときだけ array_last() を使う

$opts = getopt('', ['last']);

$maybeLast = fn(array $rows): array =>
    isset($opts['last'])
        ? [array_last($rows)]
        : $rows;

パイプラインに組み込む

$path
    |> $readAll
    |> $toLines
    |> $decode
    |> $filterErrors
    |> $maybeLast
    |> $format
    |> $join
    |> print(...);

実行結果

php logfmt.php access.ndjson

[2025-12-14T09:10:13Z] ERROR    failed to connect

php logfmt.php access.ndjson --last

[2025-12-14T09:10:13Z] ERROR    failed to connect

小さな関数をちょい足しして、パイプの中に挿し込むだけです。

触ってみた感想

ざっくり書くとこんな感じです。

  • 小さい関数をつなげるだけで流れが見える
  • ネストもif文も減って、処理の意図がわかりやすい
  • CLIツールとの相性がいい(標準入力→標準出力が自然)

個人的には使いやすかったです。 CLI でも Web でも、「変換 → 整形 → 出力」みたいな処理を書くときに良さそうです。

感想

初めてはてなブログでテック系の記事を書きましたが、コードブロックのコレジャナイ感すごい。。 エンジニア向けのテーマがないか探してみよう。

久々にサメ映画を見ました

お久しぶりです。

ブログ執筆が 10 日くらい空いてしまいました。

仕事もプライベートも忙しかったんです(という言い訳)。

また執筆を再開していきます。

 

Amazon Prime で流れてきた「 MEG ザ・モンスター 」という映画を見ました。

eiga.com

 

しかも 2 部作両方とも。

eiga.com

 

久々にサメ映画を見ました。

結構面白かったです。

 

サメ映画といえば、「それはないでしょ」とツッコミたくなるようなシーンが多いのですが、私はそれを楽しむ派です。

今回も同じツッコミどころは多かったですが、ストーリーや映像の出来が良かった気がします。

※ 個人の感想です。映画評論できるほど詳しくありません。

 

あと、主演のジェイソン・ステイサムがとにかくかっこいい。

それに尽きるかもしれない。

 

 

サメ映画には色んな種類があり、中でもよく覚えているのは「 ディープ・ブルー 」という作品です。

eiga.com

 

子どもの頃に見た記憶が強く残っていて、なぜか私の中でサメ映画トップです。

理由はわかりません。

 

それ以外だと、サメが空を飛んでるシーンに笑った記憶があります(映画のタイトルは忘れました)。

なんでもありな設定の上に、映像もかなり雑で、これはこれで面白いなと思って観てました。

また探してみようかな〜。

 

そういえば「JAWS 」は見たことないかも。。

沖縄の海といえば

 BBQ ですね。※ 個人の意見です

 

GW ということで、 BBQ してきました。

渡具知ビーチ

沖縄県民って、あまり海には入らないんですよね。

海に入ることなく、BBQ だけを楽しんで帰りました。

 

私も子どもの時は海で遊ぶのが好きでした。

その時のことを思い出すと、親が入ってるイメージは全くないです。

それが今では、海に入るのは子ども達だけ、もしくは子ども達と一緒に、くらいです。

私も年をとったな〜としみじみ思いました。

 

GW 全然ブログ書けなかった!やばい!

抽象度の大切さ

突然ですが、マニュアルを読むのが嫌いです。

昔からずっと嫌いで、携帯電話のマニュアルなんて読んだことないし、家電のマニュアルも問題が発生して初めて開きます。

仕事でマニュアル作業が発生すると、ほぼ必ず「うっ」となります。

 

最近もあったので理由を考えてみたところ、一つの理由がわかりました。

マニュアルは具体的な手順が多すぎて、情報量過多に辟易するんだと思います。

 

マニュアルは、誰でも同じ手順をふむことができるようにするための資料です。

「日本語が読める」といった最低ラインはありますが、知識がなくても理解できるように具体的な説明が書かれています。

そのため、マニュアルの情報量が過多になるのは必然です。

ただ、それでもなお、この情報量にはうんざりします。

 

ではどうするべきなのか。

鍵になるのが抽象度に応じた 見出し だと思います。

見出し単位でこのセクションが何の説明をする場なのかを明示することで、具体部分を読むか判断できます。

 

人によって、必要な情報の抽象度は異なります。

具体的な情報が必要な人もいれば、抽象的な情報だけで事足りる人もいます。

そのため、読み手が読むか否かを判断できるのがベストだろうと考えているわけです。

 

これはマニュアルに限った話ではありません。

どんな資料作りにおいても、抽象度を意識した構成にするべきだと思っています。

読み手は、自身にあった抽象度の高い情報で概ね理解し、それぞれの理解を具体的な情報で補強していく、という流れで理解します(だと思います、少なくとも私は)。

 

とはいえ、マニュアル作るの大変なんですけどね〜。

私も何度も経験しているので作る側の気持ちは理解しているつもりです。

そのうえで、やっぱり読むのは苦手ですという話でした。

 

でも、最近は AI に学習させて情報を抽出してもらうことができるので、もうマニュアルは読まないかもな〜。

ゆるアニメかと思ったら超シリアスなアニメでした

王様ランキングというアニメです。

まどマギではありません。

osama-ranking.com

 

このアニメは、一見、絵本かと思うほどのゆるい絵柄です。

可愛い主人公のほっこり話が見れそうな、素敵な雰囲気があります。

 

しかし、内容は驚くほどシリアスです。

  • 主人公の不遇な生い立ち
  • 周囲に蠢く陰謀
  • 世界の不条理さ

と大作レベルの設定が盛り込まれており、めちゃくちゃ面白いです。

すでにアニメは一周したのですが、理解が浅いので二周目を始めました。

設定自体に難しさはあるものの、内容に引き込まれます。

 

具体的な話を書くとネタバレになってしまうので避けますが。。

一点だけ紹介すると、ヒリングという王女が良いキャラしてます。

ツンデレで人に誤解されるタイプなのですが、ところどころ人が良くてその人柄に惹き込まれます。

あと、名前の通り、ヒーリング(回復)が得意です。

 

興味を持った方はぜひ見てみてください。

今日は絵本を買う日です

息子は絵本が大好きで、たまにまとめて買い与えます。

今日は 5 冊買いました。

ということで紹介します。

 

www.iwasakishoten.co.jp

 

最近、息子はミャクミャクに大ハマりです。

この本を見つけた瞬間、購入を即決していました。

ミャクミャクが楽しく散歩していて、ほっこりする絵本です。

 

www.ehonnavi.net

 

あの有名な『ピタゴラスイッチ』の制作に携わるクリエイティブグループが作った絵本シリーズ第 1 弾です。

旅するキャラクターの行先を読み手が選ぶことのできる、参加型の絵本です。

何度も読めて面白いです。

 

www.ehonnavi.net

 

いきなり第 4 弾です。

もちろん間を飛ばしています。

息子曰く「忍者だから」とのことです。

 

www.ehonnavi.net

妻の趣味です。

全冊欲しいと言っています。

もちろん息子も趣味が合うようで、すぐに好きになりました。

 

www.ehonnavi.net

 

私の趣味です。

一目惚れしてめっちゃ推しました。

楽しんで読んでくれてるので多分大丈夫です。

 

以上です。

絵本は頭を使うし大人も楽しめるし、いいもんですね〜。

沖縄には"城"のつく苗字が多い

アカウントの通り、私も宮城です。

思い返すと、これまで色んな苗字の人に会ってきました。

ということで、思いつく限り、会ったことのある"城"のつく苗字を洗い出してみます。

 

  • めっちゃいる
    • 宮城(みやぎ)
    • 大城(おおしろ)
    • 金城(きんじょう、かねしろ)
    • 新城(あらしろ、しんじょう)
    • 玉城(たましろ、たまき)
    • 山城(やましろ
    • 城間(しろま)
    • 城田(しろた)
    • 兼城(かねしろ)
  • 接頭辞タイプ
    • 池宮城(いけみやぎ)
    • 高宮城(たかみやぎ)
  • 大阪で出会った
    • 高城(たかしろ)
  • ほとんど見ない
    • 慶田城(けだしろ)

思ったより出てこないな。。

 

ちなみに地名にも多いです。

  • 宮城(みやぎ)
  • 金城(かなぐすく)
  • 玉城(たまぐすく)
  • 豊見城(とみぐすく、とみしろ)
  • 兼城(かねぐすく)

 

以上、思いつきコーナーでした。