Meta-object Protocol¶
A Meta-object Protocol (MOP) is an API that exposes a language’s own object system as a first-class, programmable layer. Through a MOP, user code can redefine how classes are created, how methods are looked up and dispatched, how instances are allocated, and how inheritance is resolved: extending or replacing the object model itself from within the language. The canonical MOP is CLOS (Common Lisp Object System), which exposes generic functions such as make-instance, compute-applicable-methods, and slot-value as overridable entry points.
Python’s data model, with __new__, __init_subclass__, __class_getitem__, metaclasses, and Ruby’s BasicObject and method_missing give partial MOP-like access. Smalltalk’s entire class hierarchy is itself a set of Smalltalk objects, making it fully reflective by design.
PHP does not have a Meta-object Protocol. PHP’s object system is implemented in C (the Zend Engine) and is not programmable from userland. PHP does provide several approximations:
The Reflection API,
ReflectionClass,ReflectionMethod,ReflectionProperty, exposes read access to the object model at runtime, but cannot modify it.Magic methods, (
__get,__set,__call,__callStatic,__isset,__unset, intercept individual property and method access operations, giving hook points that resemble parts of a MOP.class_alias()lets user code create alternative names for classes, but cannot alter dispatch behaviour.Closure::bind()andClosure::bindTo()allow closures to be rebound to a different object scope, approximating dynamic method injection.Libraries such as
ocramius/proxy-managerimplement lazy-loading and interception proxies on top of these primitives, simulating part of what a MOP would provide natively.
<?php
// PHP Reflection: read-only introspection of the object model.
// A true MOP would also allow redefining dispatch and instantiation.
$rc = new ReflectionClass(ArrayObject::class);
foreach ($rc->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
echo $method->getName() . "\n";
}
// Magic methods: intercept property/method access — limited MOP hooks.
class DynamicEntity {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __call(string $name, array $args): mixed {
// intercept unknown method calls — not full method-dispatch override
throw new \BadMethodCallException("No method: $name");
}
}
// Rebind a closure to a different object scope (approximates method injection)
$greet = Closure::bind(
static function (string $suffix): string { return self::class . $suffix; },
null,
DynamicEntity::class
);
?>
See also The Art of the Metaobject Protocol (Kiczales et al.), PHP Reflection API and ocramius/proxy-manager.
Related : Reflection, Magic Methods, Metaprogramming, Homoiconicity, Proxy, Closure, __get() Method, __call() Method, Metaclass
Related packages : ocramius/proxy-manager