‹#› 
PHP de 
フィールドインジェクション 
第84回 PHP勉強会 
! 
竹澤 有貴 
The title of the presentation can go here, and it can span nearly the width of the page Company Proprietary and Confidential
profile 
ytake 
• php, node.js, RDBMS, NoSQL 
• Laravel ユーザーグループ 
• NewSQL 
• React.js がんばり中 
https://www.facebook.com/ 
yuuki.takezawa 
https://twitter.com/ex_takezawa 
竹澤 有貴 
yuuki takezawa “
PHPでフィールドインジェクションって 
要るの? 
ytake
たぶん 要らない 
ytake
まずは前提知識から 
ytake
DI / Service Locater 
ytake 
• 明確な違い、わかりますか? 
• 似ているけど少し違う 
• PHP-DI 
• Aura.DI 
• Ray.DI 
• OrnoDi 
• ZendDi 
• Symfony/DependencyInjection 
• Pimple 
• illuminate/container 
“違いは?
コンテナから、 
ある名前をキーに登録されたオブジェクト 
を取り出す 
ytake
$container['db'] = function() { 
ytake 
return new PDO( 
'mysql:dbname=tests;host=localhost', 
'root', 
‘root' 
); 
}; 
var_dump($container[‘db’]());
インスタンス生成時に 
必要なものをコンテナが渡してくれる 
ytake
interface SomethingInterface 
{ 
ytake 
public function perform(); 
} 
class Something implements SomethingInterface 
{ 
public function perform() 
{ 
return 'hello'; 
} 
}
class Perform 
{ 
ytake 
public function __construct( 
SomethingInterface $something 
) { 
$this->something = $something; 
} 
public function something() 
{ 
return $this->something->perform(); 
} 
} 
new Perform(new Something);
ytake 
$container->make("Perform"); 
全部コンテナがやってくれる
interfaceじゃなきゃだめなのか? 
ytake 
• コンテナが解決してくれるもの 
なら何でも 
• コンストラクタに文字列だった 
り配列だったり、なんでも良い 
• それぞれのライブラリはそこら 
辺を上手くカバーしてくれます 
• 所謂コンストラクタインジェク 
ション 
N“o!
フィールドインジェクションって 
なんだ? 
ytake
public class FrogMan 
{ 
ytake 
@Inject private Vehicle vehicle; 
} 
!
フィールドインジェクション 
ytake 
• プロパティに注入 
• アノテーション(JSR-330 etc) 
• 単純で分かり易いが、 
状況によってはテストし辛くな 
るのであまりお勧めされない 
• PHPでもDIライブラリで実装して 
るものも結構ある 
• javaは標準で使える (Guiceとか 
SpringFrameworkのとかあるけど) 
j“ava etc..
Compiler! 
ytake
PHPにはそんなものは無い 
(インタープリタ型) 
ytake
そこまでして使いたいのか? 
ytake
javaに寄せたライブラリは多い 
だがSpringに寄せたものはあまりない 
とりあえずやってみよう! 
PHPのコンテナ、アノテーションライブ 
ラリを使おう! 
ytake
フィールドインジェクションをどう再現するか 
ytake 
• doctrine/annotation 
• リフレクション 
• コンパイラがないので作る 
(nick/PHP-Parser) 
• Laravelユーザーなので 
illuminate/container 
(利用者が少ないものを選んだ) 
• Spring Framework! 
• オートスキャン @Componentだ 
考“えた
illuminate/Container 
ytake 
• DIとしての機能はある 
• もちろんサービスロケーターも 
• バインディングのbindに慣れている 
• 5のコンテナで@Qualifierに近い事が 
• @Scopeの実装が楽 
簡“単
Laravelコンテナはこういう感じ 
ytake
binding1 
$this->bind("hoge", "HogeContainerRepository"); 
hogeって名前を呼んだら 
HogeContainerRepository くれ 
ytake
binding2 
ytake 
$this->bind("AcmeInterface", "Acme"); 
このインターフェースが 
コンストラクタにあったら 
このクラスを注入せよ
binding3 
AppClassにはこれを注入せよ 
*次期バージョンから(develop only) 
ytake 
$container->when(‘AppClass) 
->needs(‘HogeInterface) 
->give(‘Hoge);
newInstance 
ytake 
$container->make(‘AppClass); 
依存を解決して 
インスタンスを生成せよ! 
シングルトンもあり
@Component 
ytake 
• SpringのBeanと同じ様に 
• Symfony/Finder 優秀 
• andrewsville/php-token-reflection 
tokenizerとリフレクションを使った 
ライブラリ 
• ClassのみでComponent(“name”) 
• インターフェイス, クラスの関連 
コンテナに 
登録“
@Autowired 
class Perform 
{ 
ytake 
/** 
* @Autowired("Interface") 
*/ 
protected $repository; 
}
だがしかし、 
そもそも 
フィールドインジェクションの 
仕組みは無い 
ytake
コンストラクタに突っ込めば 
やりたい事が解決できる 
コンパイラとして継承したクラスを 
吐き出して実行すれば良い 
ytake
final class CompiledPerform extends Perform 
{ 
ytake 
public function __construct( 
Interface $repository 
){ 
$this->repository = $repository; 
} 
}
こんな感じで継承クラスを 
実行させる様にした 
ytake
速度が遅い! 
ytake 
• 元のライブラリの10倍くらい遅い 
• コンパイルしたクラスを吐き出して 
移行はそれを使う様にする 
(3倍遅いくらい) 
• xhprofで見たらdoctrine/annotationが 
一番ボトルネックだった 
(キャッシュ忘れてた) 
• フィールドインジェクションを 
毎回読むのも遅いので、 
全部吐き出す様にした 
キ“ャッシュ
結果 
object(CompiledPerform)#20 (1) { 
["repository":protected]=> 
object(Repository)#21 (0) { 
} 
} 
できた 
ytake
ボトルネックがautoloaderになった 
ytake
待てよ 
コンストラクタに突っ込むなら 
要らないんじゃ・・・?? 
ytake
無駄な産物が出来てしまった・・ 
https://github.com/ytake/Iono.Container 
ytake
ytake
ご清聴ありがとうございました 
ytake

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