8月分の内容を残し忘れていたのでまとめて・・
OSS
ペチコンの資料を作っていて、PHPマニュアルのちょっとした修正漏れに気付いたのでパッチを投げました。
@phpに貢献してみたいなぁ〜って思っていたので、嬉しいですね
github.com
勉強会・LT
他社との合同クローズド勉強会
その他
会社のブログ。
あのアカセさんにお誘いを受けて、またお邪魔してきましたの回 🙌
8月分の内容を残し忘れていたのでまとめて・・
ペチコンの資料を作っていて、PHPマニュアルのちょっとした修正漏れに気付いたのでパッチを投げました。
@phpに貢献してみたいなぁ〜って思っていたので、嬉しいですね
github.com
他社との合同クローズド勉強会
会社のブログ。
あのアカセさんにお誘いを受けて、またお邪魔してきましたの回 🙌
streamWrapperが〜みたいな記事をzennに書いたんですけども。 zenn.dev
記事中でも「多分こんな感じで動いてるけど、実装を見てないからわからないよ」と書いているのが、stream_readとファイル読み込みサイズの関係。
例えば、「いつも決まった文字列(PHPスクリプトとして解釈可能)を返す」というstreamWrapperを用意する。
返すのは "<?php echo time() . PHP_EOL; ?>\n";
とし、これは読み取り文字数*1を無視して、いつも返すようにする。
<?php class InvalidStreamWrapper { private $content = "<?php echo time() . PHP_EOL; ?>\n"; public function stream_read($count) { return $this->content;; } }
毎回固定文字列を返すと、ファイル終端のハンドリングに失敗して無限ループが発生するので、「3回stream_read()を読んだら空データを返す」ようにする
<?php class InvalidStreamWrapper { private $counter = 0; public function stream_read($count) { if ($this->counter > 2) { return ''; } $this->counter++; return $this->content;; }
その他、動作に最低限必要な stream_open()
、 stream_eof()
、stream_set_option()
をダミーで定義して、 return true;
させておく。
また、stream_stat()
も一旦 return true;
で済ませる。
<?php class InvalidStreamWrapper { public function stream_stat() { return true; } public function stream_open($path, $mode, $options, &$opened_path): bool { return true; } public function stream_eof(): bool { return true; } public function stream_set_option($option, $arg1, $arg2) { return true; } }
これを利用するための実行部分は以下
<?php stream_wrapper_unregister('file'); stream_wrapper_register('file', InvalidStreamWrapper::class); echo '========file_get_contents' . PHP_EOL; echo file_get_contents('non-exists-file'); echo '========require' . PHP_EOL; require 'non-exists-file';
で、実行するとこうなる
========file_get_contents <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> ========require 1695457515 1695457515 1695457515
sizeの指定がない限り、file_get_content()
もrequire
も同様に「終端が来るまでファイルを読み込む」ように見える。
また、stream_eof()
の結果も変わらない。
stream_stat()
がsize情報を返すように改変する。
挙動をわかりやすくするために、ついでに実行部分もいじる。
<?php echo 'fstat.size = ' . (fstat(fopen('non-exists-file', 'r'))['size']) . PHP_EOL; class InvalidStreamWrapper { private $size = 32; public function stream_stat() { return ['size' => $this->size]; } }
まずはsize=32で。これは、 strlen(IngalidStreamWrapper::$content)
と一致する。
実行結果
fstat.size = 32 ========file_get_contents <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> ========require 1695458370
「requireだと1回しか$contentが出力されていない」という形に。
sizeを増やしてみる
<?php private $size = 32 * 2;
すると、次の結果に
fstat.size = 64 ========file_get_contents <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> ========require 1695458351 1695458351
sizeが0の場合は、予想していた挙動と変わった。これは無指定時と同じになる
<?php private $size = 32 * 0;
fstat.size = 0 ========file_get_contents <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> ========require 1695458321 1695458321 1695458321
では、contenの長さと一致しないsizeにしてみるとどうなるか。
例えばsize=4の場合、PHPスクリプトファイルとして読み取られて評価されたが、開始タグがない(壊れている)ので、テキストファイルを読み込まれたのと同じ状態。
<?php private $size = 4;
fstat.size = 4 ========file_get_contents <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> ========require <?ph
PHPスクリプトとして中途半端な文字数にすると、構文エラーとなる
fstat.size = 25 ========file_get_contents <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> ========require Parse error: syntax error, unexpected end of file, expecting "," or ";" in non-exists-file on line 1 Process exited with code 255.
受信できるサイズより大きい場合はどうなるだろうか?
これは問題ないっぽい。ストリームのブロックサイズやstream_eof()
の内容とも関係してくるのかな、というのも気になる。
fstat.size = 320 ========file_get_contents <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> <?php echo time() . PHP_EOL; ?> ========require 1695458524 1695458524 1695458524
php_stream_read_to_str
とか _php_stream_read
の辺りを読んでいけば良いのかなーって思った。
お腹が空いたのでここまで、また気が向いたらやろうかなー。未定。
*1:stream_read()に渡されるデータサイズ。$count。
これのPHP版が欲しいhttps://t.co/vP8dXWbeBc
— 今日も誰かのにちようび(おいしい鮭親子丼) (@o0h_) 2023年8月11日
Google先生が0.43 秒で見つけてくれましたhttps://t.co/TsSGEJqwxs
— 今日も誰かのにちようび(おいしい鮭親子丼) (@o0h_) 2023年8月11日
ってことで、試し書き程度にやってみたのでした。
(ちゃんと動くのかな・・・?そんなにしっかり確かめてない。なんとなく行けるのかな、って所まで作ったので晒す)
(ちなみに、関数のPHPDocは全部AI Assistantさんがやってくれました)
人に説明や証明する事が面倒くさくてぇ、受け取った側も億劫でぇ・・・みたいなものが世の中にあると、
「説明や証明をしなくて済めばいいのに!あるいは、どっかの誰かが代わりにやってくれれば良いのに!」って思いますよね。
いちいち、そういう”くだらなさ”で仕事の場面やらでストレス溜めたくないなぁ〜って思いつつ、
でも「ガガッと気になったところをぶち潰して行きたい衝動に駆られることはある」のも自分にとっては真なので、
サボるための道具を作って遊んでみるか?というアレです。
モノタロウさんの記事、初めて見た時にメチャクチャ衝撃を受けて。「いいなぁ!あれ、俺も欲しい!!」という感じで。
「コメントとかインデントとか改行とかを変えましたよ!!」みたいな、PHP-CS-Fixerなどでガガーっとやるような変更について、どうでもいいからLGTMくれよーーーって交渉や説得・説明が面倒くさすぎます。
で、「何かASTとかそういうの触れてみたい、遊んでみたい!」とも思っていたので再発明でございます。
といっても、ツイートで触れている記事で紹介されている actionsを見ながら、写経したようなもんです。 github.com
変えたところとしては
とかとかやりました。
比較したいブランチ名やコミットハッシュを2つ渡してあげる〜みたいな使い方をします。
2つ目は、省略したらHEAD
を利用します。
$ php prototype.php main tmp # Check diff between main...tmp | main | tmp | | ---- | ---- | | 48261f6f838b529b003fa3a26eb770ea2b7bf06c wip | 6c0c3b15f07051277993e24b7ce876e0a5baa3c4 Create README | ## Diff ### non-PHP Files | filename | status | | ---- | ---- | | README | A | ### PHP Files | filename | status | BASE | HEAD | ast-changed | | ---- | ---- | ---- | ---- | ---- | | hello.php | M | b9b45a8d7d4608bce4541443e0db1ec7 | b9b45a8d7d4608bce4541443e0db1ec7 | NO CHANGE | | prototype.php | M | 39bfc6a9f6632f1723bc13d5b234c396 | 3278e5a8d39c10c4cb30b3232af507d7 | | | src/Command/EchoHashCommand.php | D | f5612c756ba27d3be6a479387ee97dcd | | | | src/Parser/Parser.php | D | db232594d101bc1a7e4f40e67e6dc54c | | | | src/Parser/Validation.php | D | 69850a9556020ed7d4234cc13f1d1c57 | | |
PHPカンファレンス福岡2023に参加しました & 登壇しました #phpconfuk / @自分の登壇まわり - 大好き!にちようび
会社でテックブログを(仮)始動させたので、Zennにいくつか記事を出しました。
会社のアカウントからも出しています
6月24日に開催された、PHPカンファレンス福岡2023に参加しました
ここ最近は、カンファレンスに参加する度(たび)に段々と楽しんだ度(ど)が増してるな〜〜という気持ちがあるのですが、 今回もまた、それはもう楽しかったです。
参加した感想やセッションを聴いての感想などは、別途で記事を書きたいと思いますので、ここでは自分の発表内容についての諸々を残しておきたいと思います。
よく聴いているpodcastに呼んでいただいて、雑談をしてきました。楽しかったw
#ツナギメエフエム 第45回を公開しました。(w/@gennei @o0h_)https://t.co/KJIW8XZOTG
— tsunagimefm (@tsunagimefm) 2023年5月25日