ProxyManager: generating PHP proxy objects from a factory closure
🎩✨🌈 OOP Proxy wrappers/utilities - generates and manages proxies of your objects
At a glance
- What is it?
- ProxyManager is a small MIT licensed PHP library whose job is to build proxy objects at runtime, so a closure decides when the real object gets created. Here is what its single README example actually shows, what the examples directory implies about the rest, and where the release list has drifted away from the branch.
- Who is it for?
- Use it if you want lazily initialised or intercepted objects without writing proxy classes yourself, and if you are willing to read the docs folder rather than the README, which demonstrates a single proxy type. Do not expect the README to settle version questions: the newest tags are 2.12.1, 2.13.1, and 2.14.1 from 2022-03-05, while the default branch is 2.15.x with a push on 2026-10-27, so check what your composer constraint resolves to and read UPGRADE.md before jumping.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- Ocramius/ProxyManager4,935 ★ · -7
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| Ocramius/ProxyManager | 4.9k | 4.9k |
-7 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Composer is the only install route the README names
The suggested installation method is composer, and it takes one line.
php composer.phar require ocramius/proxy-managerNothing more is spelled out. There is no PHP version requirement in that section, no extension list, and no advice on which version constraint to write, even though the default branch is named 2.15.x and the tags in the release list stop at 2.14.1. Choosing the constraint is therefore left to you. The composer.lock in the repository root pins what the library builds against during development, not what your application resolves. The package is distributed through Packagist, which is where the badge at the top of the README points.
LazyLoadingValueHolderFactory generates the wrapper, not you
The single piece of code in the README builds a lazy loadable object, and the factory does the generating. You hand LazyLoadingValueHolderFactory a class name and a closure, and it returns something you can call methods on.
$factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory();
$proxy = $factory->createProxy(
\MyApp\HeavyComplexObject::class,
function (& $wrappedObject, $proxy, $method, $parameters, & $initializer) {
$wrappedObject = new \MyApp\HeavyComplexObject(); // instantiation logic here
$initializer = null; // turning off further lazy initialization
return true; // report success
}
);
$proxy->doFoo();No proxy class is written by hand, and the closure is where instantiation logic goes. What you hold afterwards is the proxy, so the doFoo() line at the end is the first call that forces the real object into existence. The README calls this a Virtual Proxy and then sends you to the docs for the other types, so this snippet is one entry point rather than a survey of the library.
The examples directory is the only offline catalogue
The rest of the library is visible through the file names in examples, one script per flavour: virtual-proxy.php, ghost-object.php, ghost-object-skipped-properties.php, remote-proxy.php, smart-reference.php, and access-interceptor-scope-localizer.php. The listing also shows a remote-proxy/ directory sitting next to remote-proxy.php, so that example is not one self contained file. Two things follow for a reader. The README demonstrates only the virtual proxy, so every other type has to be learned from the docs folder or by reading those scripts. And because the README does not enumerate the supported proxy types, the examples directory is the place to find out what exists at all before you design around one.
Five initializer parameters, two of them by reference
The initializer closure is the part of the contract that matters, and the snippet states it through two comments. It receives five values: $wrappedObject and $initializer by reference, plus $proxy, $method, and $parameters. You assign the real object to $wrappedObject, set $initializer to null to turn off further lazy initialization, and return true to report success. Passing those two by reference is what lets one closure hand back both the object and the decision about whether initialising again is still allowed. What is not stated anywhere is the failure path. The README does not say what happens when the closure returns false, throws, or leaves $initializer set, so that is the first thing to exercise in your own code before assuming a proxy will ever materialise.
Tags stop at 2.14.1 while the branch is 2.15.x
Version numbers here need care, because the branch and the tags disagree about the calendar. The three releases listed are 2.14.1, 2.13.1, and 2.12.1, and all three carry the same date, 2022-03-05. The default branch is 2.15.x, and the last push on it is dated 2026-10-27. The repository is not archived, so the code keeps moving, yet the published tags a composer user can pin predate that push by more than four years. The consequence is concrete: a constraint of 2.14.x gives you code from before everything currently on the branch, with none of the later commits. UPGRADE.md and STABILITY.md sit in the root for exactly this question, and the README summarises neither.
The quality gates are visible in the root file list
Contributor tooling shows up in the root file listing rather than in the README. There is phpunit.xml.dist for the test suite, psalm.xml for static analysis, phpcs.xml.dist and phpmd.xml.dist for style and mess checks, phpbench.json for benchmarks, and infection.json.dist for mutation testing. renovate.json handles dependency updates and composer.lock pins the versions the project builds against. .phpstorm.meta.php and .gitattributes cover IDE resolution and file attributes. For someone installing the package none of that changes the runtime behaviour, and none of it is explained in the README. For a contributor it matters that CONTRIBUTING.md is not linked from the README either, so the commands behind those config files have to be found in the files themselves.
Two of the four README sections are not technical
Set the extras aside and the documentation is short: a Purpose paragraph, a Documentation pointer into docs, an Installation section, and one example. Two further README sections are not about code. The README opens with a notice aimed at people living in Russia, pointing them at ToRussianPeople.md, which is carried in the root. It also has a section about the Tidelift Subscription for commercial support and maintenance of open source dependencies, plus an email address, [email protected], for questions about the package in private projects. Neither changes the MIT licensed code you install, and the badge links at the top point at a Stryker mutation report, shepherd.dev, and Packagist. So the fair summary of the docs is one install command and one code sample.
Editorial conclusion
Use it if you want lazily initialised or intercepted objects without writing proxy classes yourself, and if you are willing to read the docs folder rather than the README, which demonstrates a single proxy type. Do not expect the README to settle version questions: the newest tags are 2.12.1, 2.13.1, and 2.14.1 from 2022-03-05, while the default branch is 2.15.x with a push on 2026-10-27, so check what your composer constraint resolves to and read UPGRADE.md before jumping. The one sample also leaves the failure path undefined, which is the first thing to exercise in your own initializer closure.
Frequently asked questions
How do I install ProxyManager in a PHP project?
Composer is the suggested method: php composer.phar require ocramius/proxy-manager. The package is published on Packagist as ocramius/proxy-manager.
Which proxy types does ProxyManager support?
The README demonstrates a Virtual Proxy built with LazyLoadingValueHolderFactory and points at the docs for the rest. The examples directory lists virtual-proxy.php, ghost-object.php, ghost-object-skipped-properties.php, remote-proxy.php, smart-reference.php, and access-interceptor-scope-localizer.php.
What must the initializer closure passed to createProxy return?
The sample assigns the real object to $wrappedObject, sets $initializer to null to turn off further lazy initialization, and returns true to report success. The README does not say what happens when the closure returns false.
Is ProxyManager still being worked on?
The repository is not archived, and its last push is dated 2026-10-27 on a default branch named 2.15.x. The three listed releases, 2.12.1, 2.13.1, and 2.14.1, are all dated 2022-03-05.
Can I get commercial support for ProxyManager?
The README says the package is available as part of the Tidelift Subscription for commercial support and maintenance, and it lists [email protected] for questions about the package in private projects.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ocramius-proxymanager)Star history chart for your README
[](https://hysenlabs.com/projects/ocramius-proxymanager)Was this useful?