0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

behavior メソッドの table 直呼び廃止 理由と移行 - CakePHP 5.3 Deprecation

0
Posted at

CakePHP 5.3 で Table から Behavior のメソッドの呼び出しが deprecated になりました。

Since 5.3.0: Calling behavior methods on the table instance is deprecated.
Use `$table->getBehavior('YourBehavior')->slugify()` instead.

5.x では従来どおり動きますが 6.0 で削除予定です。

なぜ廃止されたか・移行(getBehavior('BehaviorName') または trait 利用)方法について調べてみたのでメモとして残します。


サマリ

  • table に attach した behavior のメソッドを $table->method() で直接呼ぶ(__call によるマジック委譲)が 5.3.0 で deprecated になりました。
  • 移行は $table->getBehavior('BehaviorName')->method()。または Behavior による振る舞いを定義しているのではなく、単なるメソッド提供なら trait を利用する形へ。
  • 5.3 でdeprecated、6.0 で削除予定

deprecationメッセージから見る移行

// Before(5.3 deprecated)
$slug = $articles->slugify($value);

// After
$slug = $articles->getBehavior('Sluggable')->slugify($value);

なぜ廃止されたか(RFC #18288)

提案者 ADmad が挙げた理由は次の通り:

  1. trait があるので冗長$table->foo() で behavior メソッドを呼べる便利機能は、PHP に trait がある今は重複機能。単にメソッドを足したいだけなら trait で十分。
  2. プロキシのオーバーヘッド。table インスタンスで呼ぶたびに behavior へ委譲する余計なコード/チェックが走る。
  3. 静的解析を妨げる。ツールはこの「マジックメソッド」を認識できず、スタブや専用プラグインが無いと「method doesn't exist」になる。
  4. リフレクション/重複メソッド問題。メソッド引数のリフレクションが壊れる。また LocatorAwareTrait を 2 つの behavior で使い同一 table に load すると「duplicate method」で LogicException になる(behavior registry の重複チェック)。proxying をやめれば解消する。

移行の選択肢

getBehavior('Xxx')->method()(deprecation メッセージ・マイグレーションガイド通り)

getBehavior('BehaviorName') を通じて呼び出す。

$articles->getBehavior('Sluggable')->slug($value);

複数 table で共有している Behavior で定義した「振る舞い」は、Behavior のまま getBehavior() 経由で呼ぶ形が適切かと思います。

trait に移行

ライフサイクルや設定を持たない、ユーティリティメソッドなら trait 化して table で use する方がよい場合もありそうです。

参考記事:Behaviorを使うか、Traitにするか
(CakePHP 3.x 時代の記事ですが、判断基準として有用だと思います。)

  • Trait 向き: メソッド提供のみ、カスタム finder
  • Behavior 向き: ライフサイクルイベント購読、設定値管理、複数クラス共有

CakePHP RFC #18288 の趣旨(純粋なユーティリティは trait、振る舞いの共有は behavior 継続)とも一致します。


PHPStan 対応(@var が要る)

getBehavior('Xxx') の戻り型は基底 Cake\ORM\Behavior なので、そのままだと PHPStan は Call to an undefined method を出します。いまのところは、typed なローカル変数に受けて型を伝える必要があります。

/** @var \App\Model\Behavior\SluggableBehavior $sluggable */
$sluggable = $articles->getBehavior('Sluggable');
$slug = $sluggable->slug($value);

cakedc/cakephp-phpstangetBehavior() の具象型解決に対応すれば、この @var は将来不要になる可能性がありそうです。(fetchTable() では既に具象 table 型を返すよう対応済みで、コア開発者も getBehavior() の同様対応に言及しています)。


まとめ

  • $table->method()$table->getBehavior('Xxx')->method()(or trait 化)。
  • PHPStan は @var で behavior の型を明示。
  • 6.0 で削除。5.x のうちに対応しておくことを推奨。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?