Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Symfonyの特性(設計思想)を手軽に活かす特性(trait)

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for ICKX ICKX
March 21, 2026

 Symfonyの特性(設計思想)を手軽に活かす特性(trait)

Avatar for ICKX

ICKX

March 21, 2026

More Decks by ICKX

Other Decks in Programming

Transcript

  1. 自己紹介 • 若葉 章(わかば あきら) • 2010年~ 同人ソフトサークル Project ICKX

    • プロデューサー / 営業 / インフラ / サーバサイド... / ゲームの実開発以外全部 • 本職はスタッフエンジニアっぽいこともするphpエンジニア • PHP続けて26年 PHP3の頃からお世話になっています • 最近の趣味は自転車とコーヒーとアマチュア無線 • Tyrell iveで京阪や徳島から高松まで走ったり、icom ic-705やID-52で移動運用試したり • ボトルゲージ用のアルミステーやドリッパーホルダの自作を始めましたもうだめだ • Nintendo Switch で『VERTICAL STRIKE ENDLESS CHALLENGE』販売中 • Qiitaで『phpで高速に・省メモリ・確実に日本語csvを扱う方法』公開中 https://qiita.com/wakabadou/items/84b48ca12f25fb2fb69c 「composer require fw3/streams」をよろしくね。 「composer require tacddd/tacddd」もよろしくね。 「composer require bypassflow/crypt」もよろしくね。
  2. • 2012年リリースのPHP5.4から導入された機能 • 単一継承言語でコードを再利用する仕組みの一つ • 単にいくつかの機能をまとめるためだけのもの • プロパティやメソッド、定数(8.2以降)を定義できる • インスタンスは作れない

    • 縦軸の再利用が継承、横軸の再利用が特性として整理できる • 適用できる先はクラス、特性、列挙型(Enum) • 疑似的に多重継承っぽいことができる • 継承が許されないEnumに対して共通処理を持ち込める
  3. class A extends AC use TraitA use TraitB class C

    extends B use TraitB class D extends B trait TraitB abstract class AC class B extends AC use TraitA trait TraitA 継承と特性で実現する再利用
  4. abstract class AC class A extends AC use TraitA use

    TraitB class B extends AC use TraitA class C extends B use TraitB class D extends B 旧来の継承で実現する再利用範囲
  5. abstract class AC class A extends AC use TraitA use

    TraitB class B extends AC use TraitA class C extends B use TraitB class D extends B trait TraitA 特性Aで実現する再利用範囲
  6. abstract class AC class A extends AC use TraitA use

    TraitB class B extends AC use TraitA class C extends B use TraitB class D extends B trait TraitB 特性Bで実現する再利用範囲
  7. traitからの静的プロパティ 直呼び出し 21 Deprecated: Accessing static trait property SampleTrait::$fuga is

    deprecated, it should only be accessed on a class using the trait Fatal error: Cannot redeclare trait SampleTrait
  8. traitで定義した定数を クラスで上書き 24 Fatal error: SampleClass and SampleTrait define the

    same constant (HOGE) in the composition of SampleClass. However, the definition differs and is considered incompatible. Class was composed
  9. 抽象プロパティ 28 Fatal error: SampleClass and SampleTrait define the same

    hooked property ($public) in the composition of SampleClass. Conflict resolution between hooked properties is currently not supported. Class was composed
  10. 抽象プロパティフック 29 Fatal error: SampleClass and SampleTrait define the same

    hooked property ($public) in the composition of SampleClass. Conflict resolution between hooked properties is currently not supported. Class was composed
  11. プロパティフック 30 Fatal error: SampleClass and SampleTrait define the same

    hooked property ($public) in the composition of SampleClass. Conflict resolution between hooked properties is currently not supported. Class was composed
  12. 複数のtraitで定義した(略 53 object(class@anonymous)#3 (2) { ["instance"]=> object(SampleClass)#8 (1) { ["id"]=>

    int(1) } ["attributes"]=> array(2) { [0]=> object(Id)#5 (0) { } [1]=> object(Validate)#6 (1) { ["rule"]=> enum(ValidateRuleEnum::PositiveIntA) } } }
  13. 58 カードマ~ン 決済代行会社 • 対応決済方法 • クレジットカード • IC払い •

    QR払い • 銀行払い • 後払い ビューン 決済代行会社 • 対応決済方法 • クレジットカード • IC払い • QR払い
  14. • DIコンテナを中心にHTTP処理をイベントで組み立てる フレームワーク • Laravelのようなフルスタック一体ではなく HTTP / CLI / DI

    / Event / Config を束ねる 実行環境がコアとしてふるまう • フレームワークを使うではなく、 DIコンテナ上にアプリを構築するイメージ • パフォーマンスの担保をruntimeではなく buildタイミングで最適化
  15. 73 オプションも合成できる • [ ‘title_root’ => ‘サンプル’, ‘title_section’ => ‘売り上げ’,

    ‘title_page’ => ‘一覧’, ] • title:サンプル – 売り上げ – 一覧
  16. Symfony¥Bundle¥FrameworkBundle¥Controller¥ AbstractController ※必須:これを継承しないと何もできない class SalesLogController extends AbstractController ※ここで余計なものを挟み込めない Symfony Controllerの継承制約

    abstract class AbstractAppController extends AbstractController ※一見共通化できたように見える abstract class SalesLogControllerr extends AbstractAppController ※特化共通基盤が必要になったら 特化ごとにAbstractが必要になる 特化が入れ子になったら…?
  17. • {{ config.current_path }}で現在のページのパスを得られます • つまり{{ path(config.current_path) }}で終わる もうこれでいちいちページごとにnameを書き換えることはない… •

    同様に{{ path(config.getTemplatePathByAction(‘index’) }} • 更には{{ path( config.getPathByAction(‘update‘), param.from(entity).criteria ) }}などもできます Configの恩恵
  18. • config.current_path => sample_sales_log • config.getTemplatePathByAction(‘read’) => sample_sales_log_read • config.getTemplatePath(‘payment_log’)

    => sample_payment_log_read • path( config.getPathByAction(‘update‘), param.from(entity).criteria ) => /sample/sales-log/1 /sample/sales-log(sample_sales_log) の場合