$30 off During Our Annual Pro Sale. View Details »

School of PHP Magic

School of PHP Magic

"The closer you are, the less you see"

How often do you think you know a lot about PHP magic? And what if I tell you that you just did not look carefully? After all, the more you think that you know everything, the easier it is to deceive you. Look carefully, because the closer you are, the less you see.

The school of PHP magic opens its doors. Let's run beyond the established boundaries of OOP rules and make the impossible possible. And who knows, maybe you will love this magic: magic methods, non-standard ways of accessing properties, changing contexts, aspect-oriented programming, streaming filters, and more.

Alexander Lisachenko

May 17, 2019
Tweet

More Decks by Alexander Lisachenko

Other Decks in Programming

Transcript

  1. School of PHP Magic
    Alexander Lisachenko

    View Slide

  2. ‣ Head of Web Development at Alpari
    (RU) Forex Broker
    ‣ Have worked with computers since
    7 years old
    ‣ Clean code advocate, guru in
    enterprise architecture
    ‣ Author of the aspect-oriented
    framework Go! AOP 

    http://go.aopphp.com
    About me:
    2
    lisachenko
    lisachenko

    View Slide

  3. Moscow PHP User Group
    3

    View Slide

  4. Moscow PHP User Group
    3

    View Slide

  5. 4
    «The closer you think you are,
    the less you'll actually see.»

    View Slide

  6. The Trick
    5

    View Slide

  7. The Trick
    5

    View Slide

  8. The Trick
    6
    …an action that is intended to
    deceive, either as a way of cheating
    someone, or as a joke or form of
    entertainment

    View Slide

  9. 7
    One of the trickiest programming language.

    View Slide

  10. 8
    Magic equipment

    View Slide

  11. 9
    Magic equipment

    View Slide

  12. 9
    Magic equipment
    __construct(), __destruct(), __clone(),

    View Slide

  13. 9
    Magic equipment
    __construct(), __destruct(), __clone(),
    __call(), __callStatic(),

    View Slide

  14. 9
    Magic equipment
    __construct(), __destruct(), __clone(),
    __call(), __callStatic(),
    __get(), __set(), __isset(), __unset(),

    View Slide

  15. 9
    Magic equipment
    __construct(), __destruct(), __clone(),
    __call(), __callStatic(),
    __get(), __set(), __isset(), __unset(),
    __sleep(), __wakeup(),

    View Slide

  16. 9
    Magic equipment
    __construct(), __destruct(), __clone(),
    __call(), __callStatic(),
    __get(), __set(), __isset(), __unset(),
    __sleep(), __wakeup(),
    __toString(), __invoke(), __set_state(),

    View Slide

  17. 9
    Magic equipment
    __construct(), __destruct(), __clone(),
    __call(), __callStatic(),
    __get(), __set(), __isset(), __unset(),
    __sleep(), __wakeup(),
    __toString(), __invoke(), __set_state(),
    __debugInfo()

    View Slide

  18. 10
    Magic equipment

    View Slide

  19. 10
    Magic equipment
    declare(ticks=1)

    View Slide

  20. 10
    Magic equipment
    declare(ticks=1)
    debug_backtrace()

    View Slide

  21. 10
    Magic equipment
    declare(ticks=1)
    debug_backtrace()
    unset(), isset()

    View Slide

  22. 10
    Magic equipment
    declare(ticks=1)
    debug_backtrace()
    unset(), isset()
    by-reference passing

    View Slide

  23. 10
    Magic equipment
    declare(ticks=1)
    debug_backtrace()
    unset(), isset()
    by-reference passing
    bound closures

    View Slide

  24. 10
    Magic equipment
    declare(ticks=1)
    debug_backtrace()
    unset(), isset()
    by-reference passing
    bound closures
    Reflection API

    View Slide

  25. 10
    Magic equipment
    declare(ticks=1)
    debug_backtrace()
    unset(), isset()
    by-reference passing
    bound closures
    Reflection API
    StreamWrapper API

    View Slide

  26. 11
    So, let’s start our magic!

    View Slide

  27. 11

    View Slide

  28. 12
    Rule #1 of magic…

    View Slide

  29. 12
    Rule #1 of magic…

    View Slide

  30. 12

    View Slide

  31. 13
    …always be the smartest guy in the room.

    View Slide

  32. 13
    …always be the smartest guy in the room.

    View Slide

  33. 13

    View Slide

  34. 14
    Trick #1: Impossible comparison

    View Slide

  35. 14
    Trick #1: Impossible comparison

    View Slide

  36. 14
    Trick #1: Impossible comparison

    View Slide

  37. 15
    Trick #1.1: Not-a-number

    View Slide

  38. 15
    Trick #1.1: Not-a-number

    View Slide

  39. 16
    Trick #1.2: Constant redefinition

    View Slide

  40. 16
    Trick #1.2: Constant redefinition

    View Slide

  41. 17
    Trick #1.3: Tick handler

    View Slide

  42. 17
    Trick #1.3: Tick handler

    View Slide

  43. 18
    Trick #2.1: Magic expressions

    View Slide

  44. 18
    Trick #2.1: Magic expressions

    View Slide

  45. 18
    Trick #2.1: Magic expressions

    View Slide

  46. 19
    True?

    View Slide

  47. 20
    False?

    View Slide

  48. 21

    View Slide

  49. 22
    Trick #2.1: Operator precedence

    View Slide

  50. 22
    Trick #2.1: Operator precedence
    Top priority

    View Slide

  51. 23
    Trick #2.2: Magic expressions

    View Slide

  52. 23
    Trick #2.2: Magic expressions

    View Slide

  53. 23
    Trick #2.2: Magic expressions

    View Slide

  54. 23
    Trick #2.2: Magic expressions

    View Slide

  55. 24
    Trick #2.2: Magic expressions

    View Slide

  56. 24
    Trick #2.2: Magic expressions
    1) $factory will be used as a class name for «new»

    View Slide

  57. 24
    Trick #2.2: Magic expressions
    1) $factory will be used as a class name for «new»
    2) Parse error will be thrown

    View Slide

  58. 24
    Trick #2.2: Magic expressions
    1) $factory will be used as a class name for «new»
    2) Parse error will be thrown
    3) Result of method $factory->build() will be used

    View Slide

  59. 24
    Trick #2.2: Magic expressions
    1) $factory will be used as a class name for «new»
    2) Parse error will be thrown
    3) Result of method $factory->build() will be used
    4) Value of property $factory->build will be used

    View Slide

  60. 25
    Trick #2.2: Magic expressions

    View Slide

  61. 25
    Trick #2.2: Magic expressions

    View Slide

  62. 26
    Trick #2.2: Operator precedence

    View Slide

  63. 26
    Trick #2.2: Operator precedence

    View Slide

  64. 27
    Trick #2.3: Magic expressions

    View Slide

  65. 27
    Trick #2.3: Magic expressions

    View Slide

  66. 27
    Trick #2.3: Magic expressions

    View Slide

  67. 28
    Trick #2.3: Loophole in parser

    View Slide

  68. 29

    View Slide

  69. 29
    What is magic?

    View Slide

  70. 29
    What is magic?
    Focused deception.

    View Slide

  71. 29
    What is magic?
    Focused deception.
    But deception meant to entertain.

    View Slide

  72. 29
    What is magic?
    Focused deception.
    But deception meant to entertain.
    Try to remember next one card…

    View Slide

  73. 29

    View Slide

  74. 30

    View Slide

  75. 30

    View Slide

  76. 31
    I am bad magician :) But let me try…

    View Slide

  77. 31
    I am bad magician :) But let me try…

    View Slide

  78. 32
    Trick #3: Breaking the rules

    View Slide

  79. 32
    Trick #3: Breaking the rules

    View Slide

  80. 32
    Trick #3: Breaking the rules

    View Slide

  81. 33

    View Slide

  82. 33
    Who knows how to do this?

    View Slide

  83. 33
    Who knows how to do this?
    Who knows two solutions?

    View Slide

  84. 33
    Who knows how to do this?
    Who knows two solutions?
    Who knows three solutions?

    View Slide

  85. 33
    Who knows how to do this?
    Who knows two solutions?
    Who knows three solutions?
    Who knows more than three?

    View Slide

  86. 34
    Trick #3.1: Reflection way

    View Slide

  87. 34
    Trick #3.1: Reflection way

    View Slide

  88. Trick #3.2: Bound closure
    35

    View Slide

  89. Trick #3.2: Bound closure
    35

    View Slide

  90. Trick #3.2: Bound closure
    35

    View Slide

  91. Trick #3.3: Unserialisation trick
    36

    View Slide

  92. Trick #3.3: Unserialisation trick
    36

    View Slide

  93. Trick #3.3: Unserialisation trick
    36

    View Slide

  94. Trick #3.3: Unserialisation trick
    36

    View Slide

  95. Trick #3.4: Can you find it?
    37

    View Slide

  96. Trick #3: doctrine/instantiator package
    38
    composer show doctrine/instantiator --all
    name : doctrine/instantiator
    descrip. : A small, lightweight utility to instantiate
    objects in PHP without invoking their constructors
    keywords : constructor, instantiate
    type : library
    license : MIT License (MIT)

    View Slide

  97. Trick #4: Intercepting property access
    39

    View Slide

  98. Trick #4: Intercepting property access
    39

    View Slide

  99. Trick #4: Intercepting property access
    39

    View Slide

  100. Trick #4: Intercepting property access
    39

    View Slide

  101. Trick #4.1: Add magic… getter!
    40

    View Slide

  102. Trick #4.1: Add magic… getter!
    40

    View Slide

  103. Trick #4.2: Use previous trick!
    41

    View Slide

  104. Trick #4.2: Use previous trick!
    41

    View Slide

  105. Trick #4.3: Unset this private field
    42

    View Slide

  106. Trick #4.3: Unset this private field
    42

    View Slide

  107. Trick #4.4: Call private constructor
    43

    View Slide

  108. Trick #4.4: Call private constructor
    43

    View Slide

  109. Trick #4: Result
    44

    View Slide

  110. Trick #4: leedavis/altr-ego package
    45
    composer show leedavis81/altr-ego --all
    name : leedavis81/altr-ego
    descrip. : Access an objects protected / private properties
    and methods
    keywords : php, break scope
    versions : dev-master, v1.0.2, v1.0.1, v1.0.0
    type : library
    license : MIT License (MIT)

    View Slide

  111. Trick #5: Immutable objects in PHP?
    46

    View Slide

  112. Trick #5: Immutable objects in PHP?
    46

    View Slide

  113. Trick #5: Immutable objects in PHP?
    46

    View Slide

  114. 47
    True?

    View Slide

  115. 48
    False?

    View Slide

  116. 49
    Trick #5.1: Immutable object in PHP

    View Slide

  117. 50
    Trick #5.1: Immutable object in PHP

    View Slide

  118. 50
    Trick #5.1: Immutable object in PHP
    Unfortunately, you can’t even read it!

    View Slide

  119. 51
    Trick #5.2: Immutable object in PHP

    View Slide

  120. 51
    Trick #5.2: Immutable object in PHP

    View Slide

  121. 52

    View Slide

  122. 52
    What if we use previous tricks?

    View Slide

  123. 52
    What if we use previous tricks?
    Intercept properties.

    View Slide

  124. 52
    What if we use previous tricks?
    Intercept properties.
    Securely store values of properties.

    View Slide

  125. 52
    What if we use previous tricks?
    Intercept properties.
    Securely store values of properties.
    Provide read-only API.

    View Slide

  126. 52
    What if we use previous tricks?
    Intercept properties.
    Securely store values of properties.
    Provide read-only API.

    View Slide

  127. 52
    What if we use previous tricks?
    Intercept properties.
    Securely store values of properties.
    Provide read-only API.

    View Slide

  128. 52
    What if we use previous tricks?
    Intercept properties.
    Securely store values of properties.
    Provide read-only API.

    View Slide

  129. 53

    View Slide

  130. 53
    Secure place for values:

    View Slide

  131. 53
    Secure place for values:
    Global variables

    View Slide

  132. 53
    Secure place for values:
    Global variables
    Public properties

    View Slide

  133. 53
    Secure place for values:
    Global variables
    Public properties
    Protected properties

    View Slide

  134. 53
    Secure place for values:
    Global variables
    Public properties
    Protected properties
    Private properties

    View Slide

  135. 53
    Secure place for values:
    Global variables
    Public properties
    Protected properties
    Private properties
    Private static properties

    View Slide

  136. 53
    Secure place for values:
    Global variables
    Public properties
    Protected properties
    Private properties
    Private static properties
    Static variables in functions

    View Slide

  137. 53
    Secure place for values:
    Global variables
    Public properties
    Protected properties
    Private properties
    Private static properties
    Static variables in functions

    View Slide

  138. 54
    Trick #5.2: Secure value storage

    View Slide

  139. 54
    Trick #5.2: Secure value storage

    View Slide

  140. 55
    Trick #5.2: Use it by-reference

    View Slide

  141. 55
    Trick #5.2: Use it by-reference

    View Slide

  142. 56
    Trick #5.2: Set state implementation

    View Slide

  143. 56
    Trick #5.2: Set state implementation

    View Slide

  144. Trick #5.2: Applying object state
    57

    View Slide

  145. Trick #5.2: Get state implementation
    58

    View Slide

  146. Trick #5.2: Get state implementation

    View Slide

  147. Trick #5.2: And a little bit magic :)
    60

    View Slide

  148. Trick #5.2: And a little bit magic :)
    60

    View Slide

  149. Trick #5: lisachenko/immutable-object
    61
    composer show lisachenko/immutable-object --all
    name : lisachenko/immutable-object
    descrip. : Immutable object library
    keywords :
    versions : * dev-master
    type : library
    license : MIT License (MIT)

    View Slide

  150. Trick #5: Usage example
    62

    View Slide

  151. Trick #5: Usage example
    63

    View Slide

  152. Trick #5: Try to change it…
    64

    View Slide

  153. Trick #5: Try to change it…
    64

    View Slide

  154. Trick #5: Try to change it…
    65

    View Slide

  155. Trick #5: Try to change it…
    65
    Maybe you can hack it?

    View Slide

  156. Trick #6: It contains anti-XDebug code!
    66

    View Slide

  157. Trick #7: Stream processing

    View Slide

  158. Trick #7: Stream processing

    View Slide

  159. Trick #7: Stream processing

    View Slide

  160. Trick #7: Stream processing

    View Slide

  161. Trick #7: Stream processing

    View Slide

  162. Trick #7: Stream processing

    View Slide

  163. Trick #8: Aspect-oriented programming

    View Slide

  164. Trick #8: Aspect-oriented programming

    View Slide

  165. Is this code good or bad?
    72

    View Slide

  166. Is this code good or bad?
    72

    View Slide

  167. Is this code good or bad?
    72

    View Slide

  168. Is this code good or bad?
    72

    View Slide

  169. Same code without secondary concerns
    73

    View Slide

  170. Same code without secondary concerns
    73

    View Slide

  171. Authorization control…
    74

    View Slide

  172. Authorization control…
    74

    View Slide

  173. Logging and audit…
    75

    View Slide

  174. Logging and audit…
    75

    View Slide

  175. Error handling…
    76

    View Slide

  176. Error handling…
    76

    View Slide

  177. 77

    View Slide

  178. 77

    View Slide

  179. Aspect glossary
    78

    View Slide

  180. Aspect glossary
    78

    View Slide

  181. Aspect glossary
    Pointcut - describes list of
    interesting events
    78

    View Slide

  182. Aspect glossary
    Pointcut - describes list of
    interesting events
    78
    Joinpoint - defines an event
    object

    View Slide

  183. Aspect glossary
    Pointcut - describes list of
    interesting events
    Advice - event handler
    78
    Joinpoint - defines an event
    object

    View Slide

  184. Aspect VS Event Listener
    79

    View Slide

  185. Aspect VS Event Listener
    79

    View Slide

  186. Aspect VS Event Listener
    79

    View Slide

  187. Aspect VS Event Listener
    79

    View Slide

  188. 80
    All aspects (or advisors) are registered in the aspect kernel

    View Slide

  189. 80
    All aspects (or advisors) are registered in the aspect kernel

    View Slide

  190. 81
    The special php://filter stream filter is registered via
    stream_filter_register()

    View Slide

  191. 82
    The composer class loader is replaced with a weaving
    proxy

    View Slide

  192. 83
    Lexical analysis and parsing of source code into the AST is
    performed
    (nikic/PHP-Parser)

    View Slide

  193. 84
    Static reflection is created from the AST
    (goaop/parser-reflection)

    View Slide

  194. 84
    Static reflection is created from the AST
    (goaop/parser-reflection)

    View Slide

  195. 84
    Static reflection is created from the AST
    (goaop/parser-reflection)

    View Slide

  196. 84
    Static reflection is created from the AST
    (goaop/parser-reflection)

    View Slide

  197. 85
    The original class is renamed and replaced with a new class
    with additional behavior; stored in the cache

    View Slide

  198. 85
    The original class is renamed and replaced with a new class
    with additional behavior; stored in the cache

    View Slide

  199. 85
    The original class is renamed and replaced with a new class
    with additional behavior; stored in the cache
    Same class name!

    View Slide

  200. 85
    The original class is renamed and replaced with a new class
    with additional behavior; stored in the cache
    Original class renamed
    Same class name!

    View Slide

  201. 85
    The original class is renamed and replaced with a new class
    with additional behavior; stored in the cache
    Original class renamed
    Overridden method
    Same class name!

    View Slide

  202. 86
    What to expect in future:

    View Slide

  203. 86
    What to expect in future:
    Opcache preloading for AOP core

    View Slide

  204. 86
    What to expect in future:
    Opcache preloading for AOP core
    FFI integration to modify binary opcodes

    View Slide

  205. 86
    What to expect in future:
    Opcache preloading for AOP core
    FFI integration to modify binary opcodes
    Modifying PHP engine internal callbacks

    View Slide

  206. 86
    What to expect in future:
    Opcache preloading for AOP core
    FFI integration to modify binary opcodes
    Modifying PHP engine internal callbacks
    Some more magic?

    View Slide

  207. Trick #8: goaop/framework
    87
    composer show goaop/framework --all
    name : goaop/framework
    descrip. : Framework for aspect-oriented programming in
    PHP.
    keywords : php, aop, library, aspect
    versions : dev-master, 3.0.x-dev, 2.x-dev, 2.3.1, …
    type : library
    license : MIT License

    View Slide

  208. If it is too magic for you, just use PhpStorm plugin for that!
    88

    View Slide

  209. If it is too magic for you, just use PhpStorm plugin for that!
    88

    View Slide

  210. Pointcut syntax highlighting, completion
    and analysis
    89

    View Slide

  211. Pointcut syntax highlighting, completion
    and analysis
    89

    View Slide

  212. Navigate to advice/advised elements
    90

    View Slide

  213. Navigate to advice/advised elements
    90

    View Slide

  214. Текст
    Trick #9: Deferred methods

    View Slide

  215. 92
    Trick: prevent execution of methods
    wrapping them into promises and run
    after the fastcgi_finish_request.

    View Slide

  216. Trick 9.1. Define an annotation
    93

    View Slide

  217. Trick 9.2. Define an aspect
    94

    View Slide

  218. Trick 9.2. Define an aspect
    94

    View Slide

  219. Trick 9.2. Define an aspect
    94
    All methods with «Async» annotation

    View Slide

  220. Trick 9.2. Define an aspect
    94
    Record each call with arguments

    View Slide

  221. Trick 9.2. Define an aspect
    94
    Prevent execution of original method

    View Slide

  222. Trick 9.2. Define an aspect
    94
    Return «our» value

    View Slide

  223. Trick 9.2. Define an aspect
    95

    View Slide

  224. Trick 9.2. Define an aspect
    95

    View Slide

  225. Trick 9.2. Define an aspect
    95

    View Slide

  226. Trick 9.2. Define an aspect
    95

    View Slide

  227. Trick 9.2. Define an aspect
    95
    Finish FASTCGI Request

    View Slide

  228. Trick 9.2. Define an aspect
    95
    Execute delayed methods

    View Slide

  229. Trick 9.3. Let’s use services
    96

    View Slide

  230. Trick 9.3. Let’s use services
    96
    Some long service call

    View Slide

  231. Trick 9.3. Let’s use services
    96

    View Slide

  232. Trick 9.4. Declare deferred
    97

    View Slide

  233. Trick 9.4. Declare deferred
    97
    Now it will be deferred

    View Slide

  234. Trick 9.4. Declare deferred
    97

    View Slide

  235. 98
    The End

    View Slide

  236. 98
    The End

    View Slide

  237. Thank you!
    Please, leave your feedback!
    99
    https://joind.in/event/php-russia-2019/school-of-php-magic---php

    View Slide