雑多なブログ

音楽や語学、プログラム関連の話題について書いています

PHP: コンストラクタのプロモーション

PHP8.0以降コンストラクターの引数を、オブジェクトのプロパティに設定することができるようになった。

例えば、$valueというプロパティにコンストラクタで値を代入する場面を考えてみる。

class Hoge {
    public string $vlaue;
    public int $num;

    public function __construct(string $value, int $num) {
        $this->value = $value;
        $this->num = $num;
    }
}

var_dump(new Hoge('Hello', 1));

実行結果

object(Hoge)#1 (2) {
  ["vlaue"]=>
  uninitialized(string)
  ["num"]=>
  int(1)
  ["value"]=>
  string(5) "Hello"
}

これと同じ事を、下記のようにコンストラクタの宣言だけで実現できる。

class Hoge {
    public function __construct(public string $value, public int $num) {
    }
}

var_dump(new Hoge('Hello!', 2));

実行結果

object(Hoge)#1 (2) {
  ["value"]=>
  string(6) "Hello!"
  ["num"]=>
  int(2)
}

ちなみに、普通の引数と混在させることができる。

class Hoge {
    public int $num;

    public function __construct(public string $value, int $num, public bool $flg) {
        $this->num = $num;
    }
}

var_dump(new Hoge('Hello!', 3, false));

実行結果

object(Hoge)#1 (3) {
  ["num"]=>
  int(3)
  ["value"]=>
  string(6) "Hello!"
  ["flg"]=>
  bool(false)
}

通常の引数と、プロパティになる引数が混在するのは可読性が損なわれるように思うので、どちらか一方で統一した方が良いと思う。
バリューオブジェクトのコンストラクタに適用すると良さそう。

https://www.php.net/manual/ja/language.oop5.decon.php#language.oop5.decon.constructor.promotion

PHP - テキストに数行おきに空行を挿入する

テキストに数行おきに改行を挿入する方法を調べた。
処理のイメージは次の通り。

入力テキスト

あああああああああああ
いいいいいいいいいいいいい
うううううううううううう
ええええええええええええ
おおおおおおおおお
かかかかかかかかか

出力テキスト

あああああああああああ
いいいいいいいいいいいいい

うううううううううううう
ええええええええええええ

おおおおおおおおお
かかかかかかかかか

実装例は下記の通り。

<?php

$text=<<<EOS
あああああああああああ
いいいいいいいいいいいいい
うううううううううううう
ええええええええええええ
おおおおおおおおお
かかかかかかかかか
EOS;

echo preg_replace('/(.*\n){2}/', "$0\n", $text), PHP_EOL;

改行コードで終わる任意の文字列の2個目の末尾に改行を挿入している。

twitterの広告を消すブックマークレット

広告部分のhtmlには data-testid="placementTracking" という属性が設定されているので、その属性を持つDOM要素を非表示にすれば広告を消せる。

javascript:(() => {
    const e = document.createElement('style');
    e.innerText = '[data-testid="placementTracking"]{display:none;}';
    document.head.appendChild(e);
})();

スタイルタグを動的に生成して、そこに以下のCSSを書き込む。

[data-testid="placementTracking"]{display:none;}

で、そのCSSを書き込んだスタイルタグをheadタグ内に追記する。そうすると、タイムライン上の広告部分が非表示となる、仕組み。

xpathの記述方法を調べる(途中)

記述 内容
.. コンテキストノードの親を選択する
. コンテキストノードを選択する
* コンテキストノードの全ての子要素を選択する
/ ルートノードを選択する。
//hoge ルートノードの子孫全体から、要素 hoge を全て選択する。
hoge 要素 hoge を選択する
hoge[fuge] 要素 hoge のうち、子要素 fuge を1つ以上持つ要素を選択する。
hoge[fuge="moge"] 要素 hoge のうち、子要素 fuge の文字列が moge である要素を選択する。
hoge[@attr] 要素 hoge のうち、属性 attr を持つものを選択する。

html - datalistでお手軽コンボボックス

webでコンボボックスを実装するのは面倒だけれども、 実はhtmlには <datalist> というタグがあって、これを使うと手軽にコンボボックスを実現できる。

コード例)

<input list="languages">
<datalist id="languages">
    <option value="COBOL">
    <option value="Go">
    <option value="Haskell">
    <option value="Java">
    <option value="JavaScript">
    <option value="Kotlin">
    <option value="Perl">
    <option value="Python">
    <option value="PHP">
    <option value="Ruby">
    <option value="Rust">
    <option value="Swift">
</datalist>

上記のhtmlを記述するだけで次のようなコンボボックスが実現できる。

IEは非対応だがEdge以降は対応しているので、これからどんどん使っていきたい。

@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js to a dynamic import() which is available in all CommonJS modules.

next.js 12 のチュートリアル進めている。
theme-ui を追加したところで、下記のエラーが発生してビルドできなくなった。

Error: require() of ES Module /Users/h.hashimoto/Documents/src/projects/nextjs/next-blog/node_modules/@mdx-js/react/index.js from /Users/h.hashimoto/Documents/src/projects/nextjs/next-blog/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js not supported.
Instead change the require of index.js in /Users/h.hashimoto/Documents/src/projects/nextjs/next-blog/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js to a dynamic import() which is available in all CommonJS modules.

theme-uiが依存している mds-js というライブラリのバージョンの問題のようだ。
現時点(2022年6月11日)で yarn add すると、 mds-s の2系がインストールされるが、1系しか動かない。

次のようにバージョンを指定してインストールする。

yarn add -D  @mdx-js/react@1

Laravel Fortifyでマルチログインを実装する時のポイント

ネットに転がっているチュートリアルやドキュメントは断片的な情報が多かったので、自分が実現したい要件に沿った実装はどうすれば良いのか、というところがわかるまで随分時間がかかった。

細かい事はそのうちサンプルの実装を作ってみようと思うけど、ポイントは下記点。

  • ちゃんとFortifyの設定を理解する
  • URLで切り分ける
  • リダイレクト先のURLが直書きの箇所をカスタマイズする
  • セッションの分離(guard設定しただけじゃ不十分)
  • チュートリアルやサンプル実装に頼るのをやめて、頑張ってFortifyの実装を読む

ちゃんとFortifyの設定を理解する

自分はこの事を軽くみていたので、当初カスタマイズしなくても良い部分までカスタマイズしてしまっていた。
注意深くみると、Fortifyの設定変更などで十分対応できる部分もあるので、そのあたり気づけると余計なコードの変更をせず実装をシンプルに保つ事ができると思う。

URLで切り分ける

自分の場合はユーザーサイトと、管理サイトを分たかったので、シンプルにURLを /user, /admin のような形で切り分けて、アクセスされるパスによってFortifyなどの設定を切り分ける形で対応した。

リダイレクト先のURLが直書きの箇所をカスタマイズする

一部の実装でリダイレクトURLが固定なので、そのあたりはFortifyのソースをカスタマイズした。

セッションの分離(guard設定しただけじゃ不十分)

認証に使用するセッション変数は、guardの指定に関わらず同じ。なので、ちゃんとセッションを分離する場合はセッションCookieを別にして別々にセッションを管理できるようにする必要があった。

config/session.php の 'cookie' という項目をAppServiceProviderやFortifyServiceProviderなどで切り替えると良い。

チュートリアルやサンプル実装に頼るのをやめて、頑張ってFortifyの実装を読む

ネット上のサンプルや解説は、情報が断片的だったり、自分が必要としている要件からずれていて参考にならない事も多々ある。 ということで、ある程度情報を調べても問題が解決しなかった場合は、腹を括って認証周りの実装のコードを読み解いていくしかないと思う。