40
‹#› The title of the presentation can go here, and it can span nearly the width of the page Company Proprietary and Confidential PHP de フィールドインジェクション 84PHP勉強会 竹澤 有貴

PHP フィールドインジェクションに挑戦する PHP勉強会2014

Embed Size (px)

Citation preview

Page 1: PHP フィールドインジェクションに挑戦する PHP勉強会2014

‹#›

The title of the presentation can go here, and it can span nearly the width of the page Company Proprietary and Confidential

PHP de フィールドインジェクション第84回 PHP勉強会 !竹澤 有貴

Page 2: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

profile

• php, node.js, RDBMS, NoSQL • Laravel ユーザーグループ

• NewSQL • React.js がんばり中

https://www.facebook.com/yuuki.takezawahttps://twitter.com/ex_takezawa

竹澤 有貴 yuuki takezawa“

Page 3: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

PHPでフィールドインジェクションって 要るの?

Page 4: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

たぶん 要らない

Page 5: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

まずは前提知識から

Page 6: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

DI / Service Locater

• 明確な違い、わかりますか? • 似ているけど少し違う • PHP-DI • Aura.DI • Ray.DI • Orno\Di • Zend\Di • Symfony/DependencyInjection • Pimple • illuminate/container

違いは?“

Page 7: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

コンテナから、 ある名前をキーに登録されたオブジェクトを取り出す

Page 8: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

$container['db'] = function() { return new \PDO( 'mysql:dbname=tests;host=localhost', 'root', ‘root' ); }; var_dump($container[‘db’]());

Page 9: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

インスタンス生成時に 必要なものをコンテナが渡してくれる

Page 10: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

interface SomethingInterface{ public function perform();} class Something implements SomethingInterface{ public function perform() { return 'hello'; }}

Page 11: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

class Perform{ public function __construct( SomethingInterface $something ) { $this->something = $something; } public function something() { return $this->something->perform(); }} new Perform(new Something);

Page 12: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

$container->make("Perform");

全部コンテナがやってくれる

Page 13: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

interfaceじゃなきゃだめなのか?

• コンテナが解決してくれるものなら何でも

• コンストラクタに文字列だったり配列だったり、なんでも良い

• それぞれのライブラリはそこら辺を上手くカバーしてくれます

• 所謂コンストラクタインジェクション

No!“

Page 14: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

フィールドインジェクションって なんだ?

Page 15: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

public class FrogMan { @Inject private Vehicle vehicle; } !

Page 16: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

フィールドインジェクション

• プロパティに注入 • アノテーション(JSR-330 etc)

• 単純で分かり易いが、状況によってはテストし辛くなるのであまりお勧めされない

• PHPでもDIライブラリで実装してるものも結構ある

• javaは標準で使える (GuiceとかSpringFrameworkのとかあるけど)

java etc..“

Page 17: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

Compiler!

Page 18: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

PHPにはそんなものは無い (インタープリタ型)

Page 19: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

そこまでして使いたいのか?

Page 20: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

javaに寄せたライブラリは多い だがSpringに寄せたものはあまりない とりあえずやってみよう! PHPのコンテナ、アノテーションライブラリを使おう!

Page 21: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

フィールドインジェクションをどう再現するか

• doctrine/annotation • リフレクション • コンパイラがないので作る

(nick/PHP-Parser) • Laravelユーザーなので

illuminate/container (利用者が少ないものを選んだ)

• Spring Framework! • オートスキャン @Componentだ

考えた“

Page 22: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

illuminate/Container

• DIとしての機能はある • もちろんサービスロケーターも • バインディングのbindに慣れている

• 5のコンテナで@Qualifierに近い事が

• @Scopeの実装が楽

簡単“

Page 23: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

Laravelコンテナはこういう感じ

Page 24: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

$this->bind("hoge", "Hoge\Container\Repository");

hogeって名前を呼んだらHoge\Container\Repository くれ

binding1

Page 25: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

$this->bind("AcmeInterface", "Acme");

このインターフェースが コンストラクタにあったらこのクラスを注入せよ

binding2

Page 26: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

AppClassにはこれを注入せよ*次期バージョンから(develop only)

binding3

$container->when(‘AppClass) ->needs(‘HogeInterface) ->give(‘Hoge);

Page 27: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

依存を解決して インスタンスを生成せよ! シングルトンもあり

newInstance

$container->make(‘AppClass);

Page 28: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

@Component

• SpringのBeanと同じ様に

• Symfony/Finder 優秀

• andrewsville/php-token-reflectiontokenizerとリフレクションを使ったライブラリ

• ClassのみでComponent(“name”)

• インターフェイス, クラスの関連

コンテナに登録“

Page 29: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

@Autowired

class Perform{ /** * @Autowired("Interface") */ protected $repository; }

Page 30: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

だがしかし、 そもそも フィールドインジェクションの 仕組みは無い

Page 31: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

コンストラクタに突っ込めば やりたい事が解決できる コンパイラとして継承したクラスを 吐き出して実行すれば良い

Page 32: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

final class \CompiledPerform extends \Perform{ public function __construct( \Interface $repository ){ $this->repository = $repository; }}

Page 33: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

こんな感じで継承クラスを 実行させる様にした

Page 34: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

速度が遅い!

• 元のライブラリの10倍くらい遅い

• コンパイルしたクラスを吐き出して移行はそれを使う様にする(3倍遅いくらい)

• xhprofで見たらdoctrine/annotationが一番ボトルネックだった (キャッシュ忘れてた)

• フィールドインジェクションを毎回読むのも遅いので、 全部吐き出す様にした

キャッシュ“

Page 35: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

結果

object(CompiledPerform)#20 (1) { ["repository":protected]=> object(Repository)#21 (0) { } }

できた

Page 36: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

ボトルネックがautoloaderになった

Page 37: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

待てよコンストラクタに突っ込むなら 要らないんじゃ・・・??

Page 38: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

無駄な産物が出来てしまった・・ https://github.com/ytake/Iono.Container

Page 39: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

Page 40: PHP フィールドインジェクションに挑戦する PHP勉強会2014

ytake

ご清聴ありがとうございました