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

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勉強会 竹澤 有貴

Upload: yuuki-takezawa

Post on 13-Jul-2015

447 views

Category:

Technology


9 download

TRANSCRIPT

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

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