jdwx/iproxy

There is no license information available for the latest version (v0.0.2) of this package.

v0.0.2 2023-04-06 00:33 UTC

This package is auto-updated.

Last update: 2024-09-06 03:26:32 UTC


README

This automatically generates the code for a PHP proxy trait for a given interface. The Proxy pattern allows incorporating functionality into a class without using inheritance. This is useful when extending an interface with multiple implementations that may need to be swapped out at runtime.

This is a very limited implementation of the "20% of the effort gives 80% of the results" variety. It works well for my needs, but there are known limitations, and probably some unknown ones.

  • Does not (yet) support DNF types for arguments and return types.
  • Does not (yet) support variadic functions.
  • Does not (yet) support default values for arguments.
  • Does not support interfaces that inherit from other interfaces. (This would be very challenging.)

Installation

Via composer:

composer require jdwx/iproxy

This requires the PHP AST extension to run, but generates new PHP source files that have no external dependencies.

Usage

Create a file (e.g. IFoo.php) with an interface to proxy:

<?php


interface IFoo {


    public function bar() : baz;


}

Run the command:

YourPrompt$ vendor/bin/iproxy.php IFoo.php >FooProxy.php

This will create a file (e.g. FooProxy) with a trait that implements the interface:

<?php


trait TFooProxy {


    private IFoo $proxyFoo;


    public function bar() : baz {
        return $this->proxyFoo->bar();
    }


    protected function setProxyFoo( IFoo $i_proxyFoo ) : void {
        $this->proxyFoo = $i_proxyFoo;
    }


}

The trait will implement the interface proxy, and adds a setProxy{Name}() method that can be used from the constructor to set the proxy target.

Adding this trait to a class is sufficient to allow "implements FooInterface" to be added to the class definition:

<?php


class DecoratedFoo implements IFoo {


    use TFooProxy;
    
    
    public function __construct( IFoo $i_foo ) {
        $this->setProxyFoo( $i_foo );
    }
    
    
    public function alsoDoesQux() : void {
        // ... whatever ...
    }


}

To an external user, DecoratedFoo will act as if it has inherited from whatever IFoo-implementing class you pass in as the argument to the constructor.

The proxy generator will attempt to preserve the namespace, declare, and use statements (but not use function or use const) from the original file.

If the first character of the interface name is a capital I and the second letter is also a capital letter, the leading I will be removed. If "Interface" appears in the interface name, it will be removed. In all cases, a capital T will be added to the trait name.