Skip to content

Instantly share code, notes, and snippets.

@pbowyer
Created July 19, 2022 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pbowyer/0622c4906d08afbe7a5c88caca37a82f to your computer and use it in GitHub Desktop.
Save pbowyer/0622c4906d08afbe7a5c88caca37a82f to your computer and use it in GitHub Desktop.
How does PHP internally represent objects? Profilers such as Tideways, Datadog PHP APM etc allow you to watch methods. They are limited to exact string matches and I want to understand why the PHP internals make this the way it's done.
<?php
interface I { function i(); }
class A implements I {
function a() {}
function i() {}
}
class B extends A {
function b() {}
function i() {}
}
# Tideways used as an example as I know it best
\Tideways\Profiler::watchCallback('A::a', function(){}); // Works!
\Tideways\Profiler::watchCallback('B::b', function(){}); // Works!
\Tideways\Profiler::watchCallback('B::a', function(){}); // Fails. This one surprised me. You have to use A::a instead
\Tideways\Profiler::watchCallback('I::a', function(){}); // Fails.
# I wanted this one to work like type hinting in PHP, so I could watch the interface and not have to add an entry for every implementation
\Tideways\Profiler::watchCallback('A::i', function(){});
\Tideways\Profiler::watchCallback('B::i', function(){});
# Apparently it works this way due to overhead concerns in instrumentation.
# I imagined that PHP kept a struct for every class, keeping track of relationships between classes/interfaces so
# there wouldn't be too much work involved in resolving them.
#
# Alternatively that PHP compiles classes down and removes inheritance (so B::a would work because B contains A's methods inside it)
# That doesn't work either.
#
# So how does PHP internally represent objects?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment