Laravelでinput:checkboxのデフォルトでのチェックを実装する

ご存知の通りHTMLの仕様バグによりinput:checkboxは未チェック時、nameも送ってくれない。通常なら以下のようにして、フォームエラー時の再チェックを実装する。

<input type="checkbox" name="example" value="1" {!! old('example') == 1 ? 'checked="checked" : '' !!}>

デフォルトが未チェックであればこれで問題ないが、デフォルトでチェック状態にしたい場合はこれでは駄目だ。以下のように、引数なしのold()で、通常のフォーム表示なのか、フォームエラー時にリダイレクトされたのかを判断する。

<input type="checkbox" name="example" value="1" {!! empty(old()) || old('example') == 1 ? 'checked="checked"' : '' !!}>

もちろんこのチェックボックス以外のデータがない場合もempty(old())が真になるが、最低でもCSRFチェック用のフィールドは存在するため問題にはならないはず。

引数なしのold()がなにを返すかについてはドキュメントにはないので、以下のようにソースコードを辿る。

  1. old()Illuminate/Foundation/helpers.php::old().
  2. そこから、Illuminate\Http\Request::old()が呼び出されていて、その実体はIlluminate\Http\Concerns\InteractsWithFlashData::old()
  3. InteractsWithFlashData::old()からIlluminate\Session\Store::getOldInput()が呼び出されている。
  4. getOldInput()ではArr::get()されている。
  5. Arr::get()$keyが空の場合は$arrayをそのまま返している。

意外と道のりが長くてびっくりした。

Laravel Mixというかwebpackのコンパイルが、productionで重い件メモ

前提として、CSSはデフォルトにプラスα程度でデフォルトで入ってるBootstrapが重いく らい、JavaScriptが、Bootstrap入ってるファイルが別々に2つあってこっちが割と重い。

初回で13秒程度、変更検知でのコンパイルが6秒ほど。

一応developmentだと4秒未満、100ms未満。つまりproductionの場合に動いてるあた りが重いと。

いろいろ関係ありそうな部分をググったりソースコード読んで調べて試した結果、

  • processCssUrlsはほぼ関係なかった。
  • mix.sourceMaps()もおそらく。
  • mix.extract()もさっぱり。
  • UglifyJSはかなり重かった。が、これ外すのも……。
  • UglifyJSでunusedオプションを試したがこれも関係なかった。

UglifyJSをぜんぶなしにするのはアレなんで悩んでる。けど、外そうかな。

mix
  .options({ uglify: false })
  // ...

なおそもそも開発環境でもdevelopmentにしてるのは、単純にコンパイル済みをリポジ トリに突っ込む形にしてるから。これでdevelopmentでやってると、コミットの度に注 意しないとで面倒。

LaravelのViewのキャッシュの仕様

前の記事Blade::setEchoFormat()の挙動を確認していたときに、思うように反映されず、キャッシュかなあと思ったらキャッシュが原因だったということがあったので、Viewのキャッシュ周りの仕様を簡単に調べてみた。

結論から書くと、Viewのキャッシュは設定などによらず常に行われ、またキャッシュとテンプレートの最終更新日時のみ見て、キャッシュの方が古い場合のみ更新されるようだ。

なのでproductionじゃなくてもキャッシュされるし、Viewのコンパイル周りの設定が変わっても、テンプレート自体に更新がない場合はキャッシュが使われてしまう。

ついでに言うと、artisan cache:clearではクリアされない。

ちょっと扱いが面倒臭いな。

LaravelのBladeで{{ csrf_field() }}が通る理由

なにかの間違えで、{{ csrf_field() }}と書いていたんだけどそれが通るということがあって、{{ ... }}の仕様どうなってるのかなと思い確認した。

{{ ... }}は紆余曲折を経て、<?php echo e(...) ?>に変換されていた。e()はPHPerなら予想がつくだろう通りhtmlspecialchars()のラッパで、かつHtmlableインターフェイスを実装したクラスのインスタンスエスケープせずに通す、という仕様だった。まあ、よくあるやつだ。

なお調査ルートは以下の通り。

  1. {{, }}$BladeCompiler::contentTagsで定義されている。
  2. $BladeCompiler::contentTagsCompilesEchos::compileRegularEchos()で使用されている。
  3. compileRegularEchos(){{ ... }}から<?php echo e(...) ?>への変換が実装されている。
  4. ただし1, 2の関係が多少ややこしくて、$BladeCompiler::compilersBladeCompiler::parseToken()経由でCompilesEchos::compileEchos()が呼び出されて、そこからさらにcompileRegularEchos()が、という流れになっている。

CompilesEchosなどはBladeCompilerから5.4で分割されたようだが、もうちょっとリファクタリングして欲しい感じある。

あと、Htmlable周りはドキュメントに書かれていないが、これを知らないことにより{{ ... }}の使い方を間違えた場合に(多分)XSSしうるので、ドキュメントにちゃんと書いて欲しいなあ。{{ ... }}は常にエスケープするわけではないあたりを。

エスケープしない可能性があるのはHtmlableに関してだけではない。調査の中でBlade::setEchoFormat()という危ないメソッドの存在も知った。これを適当に書き変えちゃうと、変換先がe(...)に限らなくなってしまうので、最悪エスケープをなかったことにできたりもして危ない。まあ普通書き換えないだろうけど、もうちょっとなんとかならなかったのか。

また関連して{{{ ... }}}というのを見つけた。元々はこれと、{!! ... !!}だけだったのが、5から{{ ... }}が追加されたようだ。setEchoFormat()は見ないので安定しているかと思いきやe()を使ってるのでHtmlableは通すし、そもそもドキュメントからも消えているので多分使わない方がいい。

なお当初の疑問であった{{ csrf_field() }}についてだが、とりあえずいろいろ考えると{!! csrf_field() !!}などするのではなく{{ csrf_field() }}にするのが妥当そうである。が、そもそも5.6以降は@csrf, @methodなんてのができており、こちらを使うのがより妥当そうである。

ブギーポップ新アニメ2話まで見ての雑な感想

わざわざ書くまでもないかと思ってたけど原作好きだった人どころか原作読んだことある人の感想もろくにないので、雑に書く。

いろいろ思うところはあるけど、今更でもやってくれただけでもよかったかな。ジョジョみたいに、原作から十年二十年経ってフルサイズでやってもらえるような話でもないので、原作をちゃんとわかってる人が原作ベースで作ってくれただけで、もう。

心理描写思い切ってぜんぶ削ってやるのは、まあ妥当な妥協だと思うけど、にしてももうちょっと補足しないとやっぱり初見じゃなにもわからんよなあ、とは。だからって1クールぜんぶで1巻だけやるのもそれはそれで博打だし。

細かいところだと、画風がいまいち好みじゃないが、元の絵でやるのは無茶だし、話にまったく合ってないわけではないしという感じ。ブギーポップの声・喋り方は違和感あるけど、解釈的にはありだし、割とうまいっぽいしこっちもまあありかなと。

後はどこまでやってくれるか。ほぼ確実に1クール13話だとは思う。で、1巻分を3話でやる(んだよね?)みたいなので、4巻分? キャスト見ると「笑わない」の次はVSイマジネーターでまあ決まりっぽいと。

問題はそこからもう1巻分がどうなるか。

  1. 順当にパンドラをやる。問題はこの話(に限らないが)ブギーポップろくに出てこないこと。以外にも話の主軸とそれほど関わってこないこと。ラストにやる話としてはかなり微妙。好きだから見たくはあるけど。
  2. パンドラを飛ばして歪曲王をやる。一応最後の話にはしやすい話なので。とはいえパンドラすらなしでやると逆に終わるの早過ぎ感出そう。
  3. 夜明けのブギーポップをやる。さらに無茶。
  4. 残りぜんぶでVSイマジネーターをやる。多分ないが、もしこれ行くなら英断かも。個人的には期待したいのはこれ。

多少は見てくれる人がいて、万が一にも2期3期とやってくれて、エンブリオくらいまでやってくれたらもう言うことないんだけど。

つーかせっかくアニメにするなら、エンブリオだよね……。いちばん見たいのはペパーミントの魔術師だけど。

とりあえず今の時点でも、原作は1巻1話までしか読んでくれなかった奥さんが(混乱しながらも)楽しんでくれてるので、それだけでも個人的にはよかった。

PHP 7.3.0をCentOS 7でビルドする

phpenv経由でphp-buildで。すると、

configure: error: Please reinstall the libzip distribution

と言われるのでsudo yum install libzip. だが入れても言ってくるので、libzip-develも入れてみる。すると今度は、

configure: error: system libzip must be upgraded to version >= 0.11

なぜ最初から言わない。CentOS 7のlibzipは0.10系なんで、入れられません。

というのもアレなんで調べると、--without-libzipしておけば--enable-zipでも大丈夫とのこと。

https://bugs.php.net/bug.php?id=76483#1529077184

UPGRADINGにも書いてあった。

https://github.com/php/php-src/commit/c5df679ca8b1373e3f2a47aeba5b37da74f993de#diff-7748eb3bfdd3bf962553f6f9f2723c45

しかしPHPは割とビルドでトラブりやすい気がする。ほかにこんなに頻繁にビルドしてるのそもそもないけど。

2018年後半に読んだ本

これ前半後半で分ける必要あった?

後半の方が多かったかな。行動経済学やそれに近い心理学系のや、まあなんかその辺が中心。

割とよい本多くてどれをおすすめするか難しいが、学習に関して「Learn Better」や、風邪に関して「かぜの科学」、睡眠に関して「よく眠るための科学が教える10の秘密」あたりは詳しくなければ一般教養として読んどいた方がいいような本。

とはいえいちばんのおすすめは「漫画の仕事」かも。「ニュー・オーダージョイ・ディヴィジョン、そしてぼく」も捨てがたい。音楽関係の本は今年もいろいろ発掘していきたい。

あとなぜかメモってなかった「逆転交渉術 まずは「ノー」を引き出せ」、これもかなり面白い本だった。おすすめ。