Mirror, mirror on the wall (Nomad PHP US 2015)

46
Mirror, Mirror on the Wall James Titcumb NomadPHP December 2015

Transcript of Mirror, mirror on the wall (Nomad PHP US 2015)

Page 1: Mirror, mirror on the wall (Nomad PHP US 2015)

Mirror, Mirror on the WallJames Titcumb

NomadPHP December 2015

Page 3: Mirror, mirror on the wall (Nomad PHP US 2015)

Reflection

Page 4: Mirror, mirror on the wall (Nomad PHP US 2015)
Page 5: Mirror, mirror on the wall (Nomad PHP US 2015)

© 1937 Disney’s Snow White - disneyscreencaps.com

Page 6: Mirror, mirror on the wall (Nomad PHP US 2015)
Page 7: Mirror, mirror on the wall (Nomad PHP US 2015)

● Structure● Metadata● Values● Type introspection● Modification

Reflection

Page 8: Mirror, mirror on the wall (Nomad PHP US 2015)

How does it work?

Page 9: Mirror, mirror on the wall (Nomad PHP US 2015)

GET_REFLECTION_OBJECT_PTR(ce);

lc_name = zend_str_tolower_dup(name, name_len);

if ((ce == zend_ce_closure && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)

&& memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0)

|| zend_hash_str_exists(&ce->function_table, lc_name, name_len)) {

efree(lc_name);

RETURN_TRUE;

} else {

efree(lc_name);

RETURN_FALSE;

}

Page 10: Mirror, mirror on the wall (Nomad PHP US 2015)

Okay. What now?

Page 11: Mirror, mirror on the wall (Nomad PHP US 2015)

github.com/ /BetterReflection

Better Reflection!

Page 12: Mirror, mirror on the wall (Nomad PHP US 2015)
Page 13: Mirror, mirror on the wall (Nomad PHP US 2015)

What?

Page 14: Mirror, mirror on the wall (Nomad PHP US 2015)

Why?

Page 15: Mirror, mirror on the wall (Nomad PHP US 2015)

How?

Page 16: Mirror, mirror on the wall (Nomad PHP US 2015)

Magic of the AST

Page 17: Mirror, mirror on the wall (Nomad PHP US 2015)

source: http://goo.gl/HORwLQ

Page 18: Mirror, mirror on the wall (Nomad PHP US 2015)

WTF is AST?

Page 19: Mirror, mirror on the wall (Nomad PHP US 2015)

use PhpParser\ParserFactory;

$parser = (new ParserFactory)

->create(ParserFactory::PREFER_PHP7);

print_r($parser->parse(

file_get_contents('ast-demo-src.php')

));

Page 20: Mirror, mirror on the wall (Nomad PHP US 2015)

<?php

echo "Hello world";

Page 21: Mirror, mirror on the wall (Nomad PHP US 2015)

AST

`-- Echo statement

`-- String, value "Hello world"

Page 22: Mirror, mirror on the wall (Nomad PHP US 2015)

<?php

echo "Hello " . "world";

Page 23: Mirror, mirror on the wall (Nomad PHP US 2015)

AST

`-- Echo statement

`-- Concat

|-- Left

| `-- String, value "Hello "

`-- Right

`-- String, value "world"

Page 24: Mirror, mirror on the wall (Nomad PHP US 2015)

AST to Reflection

Page 25: Mirror, mirror on the wall (Nomad PHP US 2015)

Benefits?

Page 26: Mirror, mirror on the wall (Nomad PHP US 2015)

ReflectionProperty->getDocBlockTypes()

Types!

Page 27: Mirror, mirror on the wall (Nomad PHP US 2015)

Using Better Reflection

Page 28: Mirror, mirror on the wall (Nomad PHP US 2015)

$reflection = new ReflectionClass(

'BetterReflectionTest\Fixture\ExampleClass'

);

$this->assertSame(

'ExampleClass',

$reflection->getShortName()

);

Page 29: Mirror, mirror on the wall (Nomad PHP US 2015)

$reflection = ReflectionClass::createFromName(

'BetterReflectionTest\Fixture\ExampleClass'

);

$this->assertSame(

'ExampleClass',

$reflection->getShortName()

);

Page 30: Mirror, mirror on the wall (Nomad PHP US 2015)

// In ReflectionClass :

public static function createFromName($className)

{

return ClassReflector::buildDefaultReflector()->reflect($className);

}

// In ClassReflector :

public static function buildDefaultReflector()

{

return new self(new AggregateSourceLocator([

new PhpInternalSourceLocator(),

new EvaledCodeSourceLocator(),

new AutoloadSourceLocator(),

]));

}

Page 31: Mirror, mirror on the wall (Nomad PHP US 2015)

(don’t try this at home kids!)

Some voodoo...

Page 32: Mirror, mirror on the wall (Nomad PHP US 2015)
Page 33: Mirror, mirror on the wall (Nomad PHP US 2015)

class MyClass

{

public function foo()

{

return 5;

}

}

Page 34: Mirror, mirror on the wall (Nomad PHP US 2015)

// Create the reflection first

// ***BEFORE*** class is loaded

$classInfo = ReflectionClass::createFromName('MyClass');

Page 35: Mirror, mirror on the wall (Nomad PHP US 2015)

// Override the body...!

$methodInfo = $classInfo->getMethod('foo');

$methodInfo->setBody(function () {

return 4;

});

Page 36: Mirror, mirror on the wall (Nomad PHP US 2015)

// Save the class and require it

$classCode = (new CodePrinter())->prettyPrint([$classInfo->getAst()]);

$tmpFile = tempnam(sys_get_temp_dir(), 'br-monkey-patching');

file_put_contents($tmpFile, '<?php ' . $classCode);

require_once($tmpFile);

unlink($tmpFile);

Page 37: Mirror, mirror on the wall (Nomad PHP US 2015)

// Now create an instance, and call the function...

$c = new MyClass();

var_dump($c->foo()); // will be 4!!!

Page 38: Mirror, mirror on the wall (Nomad PHP US 2015)
Page 39: Mirror, mirror on the wall (Nomad PHP US 2015)

What’s in it for me?

Page 40: Mirror, mirror on the wall (Nomad PHP US 2015)

The future...

Page 41: Mirror, mirror on the wall (Nomad PHP US 2015)

● DONE Currently: rewriting the internals○ SourceLocators “might” return some code ?!

● DONE Returning AST/Code for method/fn

Ideas/plans - DONE

Page 42: Mirror, mirror on the wall (Nomad PHP US 2015)

● WIP More compatibility core reflection● WIP Reflect core fns with default params

○ This is not currently possible with core reflection● WIP Modification & exporting● WIP Reflecting on closures

Ideas/plans - WIP

Page 43: Mirror, mirror on the wall (Nomad PHP US 2015)

● Adding a getColumn() function● PHP 7 compatibility● @inheritDoc traversal (to inherit type hints)● Make it faster

Ideas/plans

Page 44: Mirror, mirror on the wall (Nomad PHP US 2015)

¯\_(ツ)_/¯

Page 45: Mirror, mirror on the wall (Nomad PHP US 2015)

github.com/ /BetterReflection

Better Reflection

Page 46: Mirror, mirror on the wall (Nomad PHP US 2015)

Any questions? :)

https://joind.in/16523James Titcumb @asgrim