PHPackages                             vedavith/pops-fork - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. vedavith/pops-fork

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

vedavith/pops-fork
==================

Maintained fork of eloquent/pops, a PHP object proxy system.

v6.0.0(3mo ago)11.7k↓20%1MITPHPPHP ^8.2CI failing

Since Feb 8Pushed 3mo agoCompare

[ Source](https://github.com/vedavith/pops-fork)[ Packagist](https://packagist.org/packages/vedavith/pops-fork)[ Docs](https://github.com/vedavith/pops-fork)[ RSS](/packages/vedavith-pops-fork/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (5)Versions (3)Used By (1)

Pops
====

[](#pops)

*PHP Object Proxy System.*

This is a maintained fork of [eloquent/pops](https://packagist.org/packages/eloquent/pops) originally created by Erin Millard.

Installation and documentation
------------------------------

[](#installation-and-documentation)

- Available as [Composer](http://getcomposer.org/) package `vedavith/pops-fork` (maintained fork of `eloquent/pops`).
- Requires PHP 8.2 or later.

What is *Pops*?
---------------

[](#what-is-pops)

*Pops* is a system for wrapping PHP objects in other objects to modify their behaviour. A *Pops* proxy will, as much as possible, imitate the object it wraps. It passes along method calls and returns the underlying result, and allows transparent access to properties (for both setting and getting).

Pops is the underlying system behind [Liberator](https://github.com/eloquent/liberator).

Creating proxies
----------------

[](#creating-proxies)

Let's write a simple proxy that converts everything to uppercase. Here we have a class:

```
class Confusion
{
    public function wat()
    {
        return "What is this? I don't even...";
    }

    public $derp = 'Has anyone really been far even as decided to use even?';
}
```

And here is our proxy:

```
use Eloquent\Pops\ProxyObject;

class UppercaseProxyObject extends ProxyObject
{
    public function popsCall(string $method, array &$arguments): mixed
    {
        return strtoupper(parent::popsCall($method, $arguments));
    }

    public function __get(string $property): mixed
    {
        return strtoupper(parent::__get($property));
    }
}
```

We use `popsCall()` here rather than `__call()` to get around PHP limitations to do with passing arguments by reference. See [calling methods with by-reference parameters](#calling-methods-with-by-reference-parameters) for a deeper explanation.

Now when we access `wat()` and `$derp` both normally, and through our proxy, we can see the effect:

```
$confusion = new Confusion;
$proxy = new UppercaseProxyObject($confusion);

echo $confusion->wat(); // outputs "What is this? I don't even..."
echo $proxy->wat();     // outputs "WHAT IS THIS? I DON'T EVEN..."

echo $confusion->derp;  // outputs 'Has anyone really been far even as decided to use even?'
echo $proxy->derp;      // outputs 'HAS ANYONE REALLY BEEN FAR EVEN AS DECIDED TO USE EVEN?'
```

Recursive proxies
-----------------

[](#recursive-proxies)

*Pops* proxies can be applied to any value recursively. This comes in handy when designing, for example, an output escaper (similar to Symfony). Here's an example of how such a system could be created for escaping HTML output:

```
namespace OutputEscaper;

use Eloquent\Pops\Proxy;

/**
 * Escapes output for use in HTML.
 */
class OutputEscaperProxy extends Proxy
{
    /**
     * Get the array proxy class.
     *
     * @return string The array proxy class.
     */
    protected static function proxyArrayClass()
    {
        return __NAMESPACE__ . '\OutputEscaperProxyArray';
    }

    /**
     * Get the class proxy class.
     *
     * @return string The class proxy class.
     */
    protected static function proxyClassClass()
    {
        return __NAMESPACE__ . '\OutputEscaperProxyClass';
    }

    /**
     * Get the object proxy class.
     *
     * @return string The object proxy class.
     */
    protected static function proxyObjectClass()
    {
        return __NAMESPACE__ . '\OutputEscaperProxyObject';
    }

    /**
     * Get the proxy class for primitive values.
     *
     * @return string The proxy class for primitive values.
     */
    protected static function proxyPrimitiveClass()
    {
        return __NAMESPACE__ . '\OutputEscaperProxyPrimitive';
    }
}
```

```
namespace OutputEscaper;

use Eloquent\Pops\ProxyArray;

/**
 * Wraps an array to escape any sub-values for use in HTML.
 */
class OutputEscaperProxyArray extends ProxyArray
{
    /**
     * Get the proxy class.
     *
     * @return string The proxy class.
     */
    protected static function popsProxyClass(): string
    {
        return __NAMESPACE__ . '\OutputEscaperProxy';
    }
}
```

```
namespace OutputEscaper;

use Eloquent\Pops\ProxyClass;

/**
 * Wraps a class to escape any sub-values for use in HTML.
 */
class OutputEscaperProxyClass extends ProxyClass
{
    /**
     * Get the proxy class.
     *
     * @return string The proxy class.
     */
    protected static function popsProxyClass(): string
    {
        return __NAMESPACE__ . '\OutputEscaperProxy';
    }
}
```

```
namespace OutputEscaper;

use Eloquent\Pops\ProxyObject;

/**
 * Wraps an object to escape any sub-values for use in HTML.
 */
class OutputEscaperProxyObject extends ProxyObject
{
    /**
     * Get the proxy class.
     *
     * @return string The proxy class.
     */
    protected static function popsProxyClass(): string
    {
        return __NAMESPACE__ . '\OutputEscaperProxy';
    }
}
```

```
namespace OutputEscaper;

use Eloquent\Pops\ProxyPrimitive;

/**
 * Wraps a primitive to escape its value for use in HTML.
 */
class OutputEscaperProxyPrimitive extends ProxyPrimitive
{
    /**
     * Get the HTML-escaped version of this primitive.
     *
     * @return string The HTML-secaped version of this primitive.
     */
    public function __toString(): string
    {
        return htmlspecialchars(
            strval($this->popsValue()),
            ENT_QUOTES,
            'UTF-8'
        );
    }
}
```

The output escaper can now be used like so:

```
use OutputEscaper\OutputEscaperProxy;
use Eloquent\Pops\Safe\SafeProxy;

$list = new ArrayIterator(
    array(
        'foo',
        'bar',
        'alert(document.cookie);',
        SafeProxy::proxy('ooh...'),
    )
);
$proxy = OutputEscaperProxy::proxy($list, true);

echo "\n";
foreach ($proxy as $item) {
    printf("%s\n", $item);
}
echo "\n";
```

Which would output:

```

foo
bar
&lt;script&gt;alert(document.cookie);&lt;/script&gt;
ooh...

```

Note that the above example should **NOT** be used in production. Output escaping is a complex issue that should not be taken lightly.

### Excluding values from recursion

[](#excluding-values-from-recursion)

Note that in the above example, the last list item was wrapped in a *Safe*proxy. When *Pops* applies its proxies, it will skip anything marked as safe in this manner.

Calling methods with by-reference parameters
--------------------------------------------

[](#calling-methods-with-by-reference-parameters)

Because of PHP limitations, methods with arguments that are passed by reference must be called in a special way.

To explain futher, let's assume our class from before also has a method which accepts a reference:

```
class Confusion
{
    public function butWho(&$wasPhone)
    {
        $wasPhone = 'Hello? Yes this is dog.';
    }
}
```

This method cannot be proxied normally because the `$wasPhone` argument is passed by reference. The correct way to call the above butWho() method through a *Pops* proxy looks like this:

```
use Eloquent\Pops\Proxy;

$proxy = Proxy::proxy(new Confusion);

$wasPhone = null;
$arguments = array(&$wasPhone);

$proxy->popsCall('butWho', $arguments);

echo $wasPhone; // outputs 'Hello? Yes this is dog.'
```

Note that there **must** be a variable for the `$wasPhone` argument, and there **must** be a variable for the arguments themselves. Neither can be passed directly as a value. The arguments must also contain a **reference** to `$wasPhone` argument.

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance81

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 81.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

99d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ee4ad7e16481b8e1396978ef1416fe323cae31434cbc844b011c9850c5d30ab4?d=identicon)[vedavith](/maintainers/vedavith)

---

Top Contributors

[![ezzatron](https://avatars.githubusercontent.com/u/100152?v=4)](https://github.com/ezzatron "ezzatron (31 commits)")[![vedavith](https://avatars.githubusercontent.com/u/18259805?v=4)](https://github.com/vedavith "vedavith (6 commits)")[![jmalloc](https://avatars.githubusercontent.com/u/761536?v=4)](https://github.com/jmalloc "jmalloc (1 commits)")

---

Tags

proxyobjectpropertymethod

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/vedavith-pops-fork/health.svg)

```
[![Health](https://phpackages.com/badges/vedavith-pops-fork/health.svg)](https://phpackages.com/packages/vedavith-pops-fork)
```

###  Alternatives

[symfony/property-access

Provides functions to read and write from/to an object or array using a simple string notation

2.8k295.3M2.5k](/packages/symfony-property-access)[myclabs/deep-copy

Create deep copies (clones) of your objects

8.9k849.8M169](/packages/myclabs-deep-copy)[fideloper/proxy

Set trusted proxies for Laravel

7.3k174.4M559](/packages/fideloper-proxy)[symfony/var-exporter

Provides tools to export, instantiate, hydrate, clone and lazy-load PHP objects

2.1k378.1M441](/packages/symfony-var-exporter)[friendsofphp/proxy-manager-lts

Adding support for a wider range of PHP versions to ocramius/proxy-manager

1.2k139.1M104](/packages/friendsofphp-proxy-manager-lts)[cuyz/valinor

Dependency free PHP library that helps to map any input into a strongly-typed structure.

1.5k9.2M108](/packages/cuyz-valinor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
