doctrine/instantiator
Lightweight PHP library to instantiate objects without calling their constructors. Useful for hydrators, serializers, proxies, and testing/mocking. Part of the Doctrine ecosystem; creates instances via reflection while avoiding side effects and required constructor args.
Install via Composer: composer require doctrine/instantiator. The core usage is straightforward—Instantiator::instantiate(). Start by testing it on a class with a private constructor or one that requires complex dependencies you don’t want to instantiate in tests. For example:
use Doctrine\Instantiator\Instantiator;
$instantiator = new Instantiator();
// Works even if the class has a private constructor
$instance = $instantiator->instantiate(MyClass::class);
First real-world use case: bootstrapping a mock object for unit testing without invoking side effects (e.g., database connections, file I/O) from the constructor. Check the src/Instantiator.php source for minimal internal logic—it’s only ~250 lines and heavily commented.
Testing & Mocking: Create unconstructed stubs for dependency injection scenarios (e.g., mocking Doctrine entities or objects with strict constructor contracts). Especially useful in PHPUnit or Mockery where you need real object instances but can’t/won’t run constructors.
ORM / Hydration: After fetching raw data from the DB, populate hydrated objects via reflection without triggering lazy-loading traps or validation logic in constructors. Popular in Doctrine DBAL/ORM internals.
Proxy Generation: Tools like Proxy Manager or your own AOP setup use Instantiator to create proxy objects that delegate to a wrapped subject without constructing the proxy subject prematurely.
Custom Serialization/Deserialization: When implementing custom __unserialize() or deserializing from non-standard formats (e.g., Redis hashes), instantiate first, hydrate later.
Typical workflow:
$object = $instantiator->instantiate(MyEntity::class);
// Now use reflection or manual property assignment to hydrate
foreach ($data as $field => $value) {
$refl = new ReflectionClass($object);
$prop = $refl->getProperty($field);
$prop->setValue($object, $value);
}
ReflectionProperty to set them.Closure, Generator) may fail or behave unexpectedly—always wrap calls in try/catch (Throwable).ReflectionClass::newInstanceWithoutConstructor() under the hood), but for hot paths with thousands of objects, batch instantiation or caching the Instantiator instance.instantiate(), instantiateMultiple()), it’s not designed for extension. Prefer composition: write your own hydrator wrapper that uses Instantiator internally.var_dump(get_class($instance)) to confirm the class is actually instantiated correctly—sometimes autoloading errors cause surprises.How can I help you explore Laravel packages today?