PHP5.4Žž‘ã‚Ìprivateƒƒ\ƒbƒhƒeƒXƒgŽè–@ #php5_4

Posted by Hiraku on 2011-12-07

PHP5.4 Advent Calendar 2011‚Ì7“ú–Ú‚Å‚·Bð“ú‚Í@madapaja‚³‚ñ‚́uPHP5.4+ ‚ÅŠJ”­‚ªs‚í‚ê‚Ä‚¢‚é BEAR.Sunday ƒtƒŒ[ƒ€ƒ[ƒN‚ð“®‚©‚µ‚Ä‚Ý‚év‚Å‚µ‚½B

‚³‚Ä‚³‚ÄŠF‚³‚ñAƒ†ƒjƒbƒgƒeƒXƒg‚µ‚Ä‚Ü‚·‚©H PHP‚àƒeƒXƒg‚̃‰ƒCƒuƒ‰ƒŠ‚ª[ŽÀ‚µ‚Ä‚«‚Ä‚¨‚èAƒJƒoƒŒƒbƒW100%‚ɏî”M‚ð”R‚₵‚Ä‚¢‚é•û‚à‘½‚¢‚±‚Æ‚Å‚µ‚傤B

ƒ†ƒjƒbƒgƒeƒXƒg‚ō¢‚é‚Ì‚ªAprivate/protectedƒƒ\ƒbƒh‚Å‚·BŠO‚©‚çŒÄ‚ׂȂ¢‚̂ŁA•’Ê‚Ì•û–@‚ł̓eƒXƒg‚Å‚«‚Ü‚¹‚ñB(protected‚Í“K“–‚ȃ_ƒ~[‚̃TƒuƒNƒ‰ƒX‚ðì‚Á‚Ä‚»‚±‚©‚çƒeƒXƒg‚Å‚«‚Ü‚·‚ªA‚¿‚å‚Á‚Æ–Ê“|‚Å‚·B)

‚Ü‚ “–‘R‚Å‚·BŠO‚©‚çŒÄ‚ׂȂ¢‚悤‚Éprivate‚É‚µ‚Ä‚¢‚é‚̂ŁAŠÈ’P‚ɌĂׂ½‚ç‹t‚ɍ¢‚é‚킯‚Å‚·B‚µ‚©‚µ‚È‚ª‚çAprivateƒƒ\ƒbƒh‚àŠO‚©‚çŒÄ‚ñ‚ŃeƒXƒg‚Å‚«‚½•û‚ªŠJ”­‚Í‚Í‚©‚Ç‚é‚Å‚µ‚傤B‚±‚Ì‹LŽ–‚Å‚ÍPHP‚Åprivate‚ðƒeƒXƒg‚·‚é•û–@‚ɂ‚¢‚Ä‚Ü‚Æ‚ß‚Ä‚¢‚«‚Ü‚·B

¡‚Ü‚Å

Œãq‚·‚éReflectionMethod::setAccessible‚ª“oê‚·‚éPHP5.3.2ˆÈ‘O‚ł́Aprivate‚Ì•Ç‚ð“Ë”j‚·‚é•û–@‚Í"ŒöŽ®‚É‚Í"‚ ‚è‚Ü‚¹‚ñ‚Å‚µ‚½B

Ì‚Írunkit‚Æ‚¢‚¤•Ï‘Ôextension‚ðŽg‚¤‚±‚ƂŃeƒXƒg‚Å‚«‚½‚»‚¤‚Å‚·‚ªA‚±‚Ìrunkit‚³‚ñAÅ‹ß‚ÌPHPƒo[ƒWƒ‡ƒ“‚ɒǐ‚µ‚Ä‚¨‚炸A”÷–­‚ÉŽg‚¢‚É‚­‚¢ˆóÛ‚ðŽó‚¯‚Ü‚·(PHP4‚Á‚Û‚¢•µˆÍ‹C)Bƒƒ\ƒbƒh‚̃AƒNƒZƒXŒ ŒÀ‚𒼐ڕύX‚·‚é‚悤‚È‹@”\‚Í‚È‚¢‚̂ŁA“K“–‚ȃ_ƒ~[ƒNƒ‰ƒX‚Ƀƒ\ƒbƒh‚ðƒRƒs[‚µ‚ăeƒXƒg‚·‚銴‚¶‚Å‚µ‚傤‚©H

‘¼‚ÌprivateƒeƒXƒg•û–@‚Æ‚µ‚ẮA—Ⴆ‚ÎC++‚Ì‹Ö’f‚ÌŽô•¶A#define private public‚ð^Ž—‚·‚é•û–@‚ª‚ ‚è‚Ü‚·Brequire‚Ì‘ã‚í‚è‚Éeval‚ðŽg‚¢Aƒ\[ƒXƒR[ƒh‚ð‘‚«Š·‚¦‚Ä‚µ‚Ü‚¦‚΂¢‚¢B

<?php
//require_once 'Klass.php'; //require‚Ì‘ã‚í‚è‚É

eval('?'.'>'
  .str_replace(
    array('private','protected'),
    'public',
    file_get_contents('Klass.php')));

$obj = new Klass();
$obj->methodA(); //private‚¾‚Á‚½‚Æ‚µ‚Ä‚àŒÄ‚ׂé‚Í‚¸

eval‚È‚çprivate‚ðpublic‚É’u‚«Š·‚¦‚Ä‚©‚çƒR[ƒh‚ð•]‰¿‚³‚¹‚邱‚Æ‚ª‚Å‚«‚Ü‚·B‚ ‚Æ‚Í•’Ê‚Épublicƒƒ\ƒbƒh‚ðƒeƒXƒg‚·‚銴Šo‚ŃeƒXƒgƒR[ƒh‚ð‘‚¯‚Ü‚·B

‚½‚¾A‚±‚Ì•û–@‚Í–³—‚â‚è‚È‚Ì‚Å‚¢‚­‚‚©–â‘肪‚ ‚è‚Ü‚·B

  • ƒNƒ‰ƒX’è‹`‚ƃeƒXƒgƒR[ƒh‚ª•Êƒtƒ@ƒCƒ‹‚É‚È‚Á‚Ä‚¢‚é•K—v‚ª‚ ‚é
  • \•¶‰ðÍ‚µ‚È‚¢’Pƒ‚È’uŠ·‚Ȃ̂ŁAeval()‚ŃNƒ‰ƒX‚ð’è‹`‚µ‚Ä‚¢‚é‚悤‚ȃgƒŠƒbƒL[‚ȃR[ƒh‚É‚Í“K—p‚Å‚«‚È‚¢B
  • ƒR[ƒh‚É–„‚ߍž‚܂ꂽ•¶Žš—ñ’†‚Ì"private"‚à’u‚«Š·‚í‚Á‚Ä‚µ‚Ü‚¤
  • require‚µ‚½æ‚ōX‚Érequire‚µ‚Ä‚¢‚½ê‡A’uŠ·‚³‚ê‚È‚¢BeƒNƒ‰ƒX‚ªprotected‚Ì‚Ü‚Ü‚È‚Ì‚Épublic‚ŃI[ƒo[ƒ‰ƒCƒh‚µ‚悤‚Æ‚·‚é‚ƃGƒ‰[‚É‚È‚Á‚ÄŽÀs‚Å‚«‚È‚¢B

Œ‹‹ÇA“K—p‚Å‚«‚éƒR[ƒh‚ÍŒÀ‚ç‚ê‚Ä‚µ‚Ü‚¢‚Ü‚·B‚»‚ñ‚Ȃ킯‚ŁAprivateƒƒ\ƒbƒh‚̃eƒXƒg‚Í’ú‚ß‚él‚à‘½‚©‚Á‚½‚Ì‚Å‚Í‚È‚¢‚Å‚µ‚傤‚©H@‚±‚̏󋵂ÍPHP5.3‚ªƒŠƒŠ[ƒX‚³‚ê‚Ä‚©‚ç‚à‚µ‚΂炭‚Í•Ï‚í‚è‚Ü‚¹‚ñ‚Å‚µ‚½B

ReflectionMethod::setAccessible(PHP5.3.2ˆÈ~)

‚»‚µ‚āA5.3.2‚Å‚â‚Á‚ƁAprivate‚ÌŒöŽ®‚È“Ë”j•û–@‚ª‚Å‚«‚Ü‚µ‚½BReflectionMethod::setAccessible‚ðŽg‚¤‚Æprivateƒƒ\ƒbƒh‚ÉŠO‚©‚çƒAƒNƒZƒX‚Å‚«‚é‚悤‚É‚È‚è‚Ü‚·B

<?php
class Klass {
  private function methodA(){
    echo 'private methodA!',PHP_EOL;
  }
}

$obj = new Klass();

$methodA = new ReflectionMethod($obj, 'methodA');
$methodA->setAccessible(true);
$methodA->invoke(); //private‚È‚Í‚¸‚ÌmethodA‚ªŒÄ‚ׂéII

’€ˆêAnew ReflectionMethod‚µ‚ÄsetAccessible(true)‚µ‚Ä‚ÆŽèŠÔ‚Í‚©‚©‚è‚Ü‚·‚ªA‚±‚¿‚ç‚ÍŒöŽ®Žè’i‚Ȃ̂Őæ‚Ù‚Ç‚Ìeval()‚É‚æ‚é•û–@‚̃fƒƒŠƒbƒg‚Í‘S‚ĉðÁ‚³‚ê‚Ä‚¢‚Ü‚·B

‚±‚ê‚Åprivateƒƒ\ƒbƒh‚̃eƒXƒg–â‘è‚́Aˆê‰ž‚Ì‰ðŒˆ‚ð‚Ý‚Ü‚µ‚½B

PHP5.4‚ÌClosure::bind()

‚³‚āA‚±‚±‚Řb‚͏I‚í‚è‚Ü‚¹‚ñB‚â‚Á‚ÆPHP5.4‚̘b‚Å‚·BK‚©•sK‚©A5.4‚Å‚à‚¤ˆê‚Âprivate‚ð“Ë”j‚·‚é•û–@‚ª’ljÁ‚³‚ê‚Ä‚¢‚Ü‚·B‚»‚ꂪClosure::bind‚Å‚·B

ƒTƒ‰‚Á‚Æ—¬‚³‚ê‚Ä‚¢‚é‚悤‚È‹C‚à‚µ‚Ü‚·‚ªAu–³–¼ŠÖ”‚ÉŒÀ‚èŽÀsŽžƒRƒ“ƒeƒLƒXƒg‚ð“®“I‚ɕύX‚Å‚«‚év‚Æ‚¢‚¤¦‚Ü‚¶‚¢‹@”\‚Å‚·Bu‚¦‚ÁH ‚±‚êA‚Å‚«‚¿‚á‚Á‚Ä‚¢‚¢‚́Hv‚Æ•·‚«•Ô‚µ‚½‚­‚Ȃ郌ƒxƒ‹B

Closure::bind‚ðŽg‚¤‚Æ‚±‚ñ‚ȃR[ƒh‚ªŽÀs‚Å‚«‚Ü‚·B

<?php
class Klass {
  private function methodA(){
    echo 'private methodA!';
  }
}

Closure::bind(function(){

  var_dump($this);
  $obj = new Klass();
  $obj->methodA();

}, null, 'Klass')->__invoke();

//-----------------
//NULL
//private methodA!
//‚Əo—Í‚³‚ê‚é

ƒNƒ‰ƒX‚Ì’†‚Å‚È‚¢‚̂ɁAmethodA()‚ªŒÄ‚ׂĂ¢‚邱‚Æ‚ª‚í‚©‚è‚Ü‚·B

Closure::bind‚́A‘æ2ˆø”‚É$this‚ɃZƒbƒg‚·‚éƒIƒuƒWƒFƒNƒgA‘æ3ˆø”‚ÉŽÀsŽžƒRƒ“ƒeƒLƒXƒg‚ðŽw’肵A‘æ1ˆø”‚Ì–³–¼ŠÖ”‚̃Rƒs[‚ð•Ô‚µ‚Ü‚·Bc‚¤[‚ñAà–¾‚ª“‚¢‚Å‚·‚ˁB

‚Í‚µ‚å‚Á‚Äà–¾‚·‚é‚ƁA‚±‚̃uƒƒbƒN‚ɏ‘‚©‚ꂽƒR[ƒh‚́A‘æ3ˆø”‚ÉŽw’肵‚½ƒNƒ‰ƒX‚Ì’†‚ÅŽÀs‚³‚ê‚é‚Á‚Ä‚Æ‚±‚ë‚Å‚µ‚傤‚©Bã‹L‚̃R[ƒh‚Å‚Í"Klass"‚Ì’†‚ÅŽÀs‚³‚ê‚Ä‚¢‚é(‚ÆŒ©‚È‚³‚ê‚é)‚½‚߁AKlass‚Ìprivate‚ȃƒ\ƒbƒhAƒvƒƒpƒeƒB‚ɃAƒNƒZƒX‚Å‚«‚Ä‚¢‚é‚Ì‚Å‚·B

‚³‚Á‚«‚ÌReflectionMethod‚Æ”ä‚ׂĂ݂é‚ƁAƒŠƒtƒŒƒNƒVƒ‡ƒ“‚̓ƒ\ƒbƒh‚²‚ƁEƒvƒƒpƒeƒB‚²‚Æ‚Énew‚µ‚ÄsetAccessible(true)‚µ‚È‚¯‚ê‚΂¢‚¯‚Ü‚¹‚ñ‚Å‚µ‚½‚ªAClosure::bind‚ðŽg‚¤ê‡‚̓uƒƒbƒN‚ð‘‚­‚¾‚¯‚Å‚¢‚¢‚̂ŁA‚Æ‚Ä‚à“Ç‚Ý‚â‚·‚¢‚Ì‚Å‚Í‚È‚¢‚Å‚µ‚傤‚©B

ƒeƒXƒgƒR[ƒh‚Í"“Ç‚Ý‚â‚·‚³"‚ª‘å•ÏdŽ‹‚³‚ê‚镪–ì‚Å‚·BDSL‚Å•¶–@‚ðWrap‚µ‚½‚¾‚¯‚ŕʂ̃‰ƒCƒuƒ‰ƒŠ‚𖼏æ‚Á‚Ä‚¢‚é‚à‚Ì‚ª‚ ‚é‚®‚ç‚¢‚Å‚·B‚Ü‚ A‚»‚ꂾ‚¯ƒeƒXƒgƒR[ƒh‚Æ‚¢‚¤‚͉̂˜‚ê‚â‚·‚­A“Ç‚Ý‚É‚­‚­‚È‚è‚â‚·‚¢‚Æ‚¢‚¤‚±‚Æ‚Å‚µ‚傤B

‚à‚¤‚¿‚å‚Á‚Æ‹ï‘Ì“I‚ɁAPHPUnit“I‚ȃeƒXƒgƒ‰ƒCƒuƒ‰ƒŠ‚ðŽg‚¤ê‡‚¾‚Æ‚±‚ñ‚ȃCƒ[ƒW‚É‚È‚è‚Ü‚·B$this‚Á‚ď‘‚¢‚Ä‚¢‚é‚Ì‚É$this‚Å‚Í‚È‚­$obj‚̃Rƒ“ƒeƒLƒXƒg‚ÅŽÀs‚³‚ê‚Ä‚¢‚é‚Æ‚¢‚¤A•sŽv‹c‚ȏ󋵂ł·B

<?php
class Klass {
  private function methodA(){
    return 'private methodA!';
  }
}

class KlassTest {
  public function testMethodA() {
    Closure::bind(function(){

      $obj = new Klass();
      $res = $obj->methodA();

      $this->assertTrue($res === 'private methodA!');

    }, $this, 'Klass')->__invoke();
  }

  public function assertTrue($bool) {
    echo ($bool) ? 'OK!' : 'NG!', PHP_EOL;
  }
}

$test = new KlassTest();
$test->testMethodA();

’ʏí‚Ìpublic‘ŠŽè‚̃eƒXƒgƒR[ƒh‚Æ”äŠr‚·‚é‚ƁAˆá‚¢‚ÍŠO‘¤‚𕢂Á‚Ä‚¢‚éƒuƒƒbƒN‚Ì‘¶Ý‚¾‚¯‚Å‚·B‚±‚ê‚È‚çAƒ‰ƒbƒp[‚Æ‚©‘‚©‚È‚­‚Ä‚à[•ª‚±‚ꂾ‚¯‚ÅŽg‚¦‚é‚ÆŽv‚¢‚Ü‚·B

Closure::bind‚Íeval‚âgoto‚Æ“¯‚¶ƒŒƒxƒ‹‚ōD‚«ŸŽè‚Å‚«‚éŠëŒ¯‚È‹@”\‚Å‚·‚ªAŠˆ—p‚·‚é‚Æ–Ê”’‚¢‚ÆŽv‚¢‚Ü‚·BPHP5.4‚ª‘Ò‚¿‰“‚µ‚¢‚Å‚·‚ˁB

–¾“ú‚Í@do_aki‚³‚ñ‚Å‚·B

keyword: PHP AdventCalendar

PHP‚̍ŐV‹LŽ–