TerrePorter's avatar

Type hint hell

Is what I’m trying to do possible?

I am trying to use orchestral/asset package, but I want to make some changes to the functionality in the Dispatcher class.

So this is the Orchestra\Asset\Service Provider:

  • register Resolver, ['orchestra.asset.resolver' => DependencyResolver]
  • register Dispatcher, ['orchestra.asset.dispatcher' => Dispatcher], with Resolver as a construct var
  • register Asset, ['orchestra.asset' => Factory], with Dispatcher as construct var

I copied the service provider, as i wanted to make a isolated copy of the class registrations.

The problem I'm having is I can't change the classe references as they have type hinted all the constructs with specific class references.

\Orchestra\Asset\Dispatcher
/**
 * Create a new asset dispatcher instance.
 *
 * @param \Illuminate\Filesystem\Filesystem  $files
 * @param \Collective\Html\HtmlBuilder  $html
 * @param \Orchestra\Asset\DependencyResolver  $resolver
 * @param string  $path
 */
public function __construct(
        Filesystem $files,
        HtmlBuilder $html,
        DependencyResolver $resolver,
        string $path
    ) { ... }
    
\Orchestra\Asset\Factory
/**
 * Construct a new environment.
 *
 * @param  \Orchestra\Asset\Dispatcher  $dispatcher
 */
public function __construct(Dispatcher $dispatcher) { ... }

For example, I can't replace the Dispatcher in the Factory instantiation with my own class, as it always complains that is is not a instance of the Orchestra\Asset\Dispatcher class.

Is there any way around this ?

Or should I just fork the damn thing and str_replace the namespace make my changes and go on.

0 likes
1 reply
TerrePorter's avatar

I just wanted to post my solution, here also. (I posted the question at StackOverflow also, https://stackoverflow.com/questions/55593792/how-can-i-overwrite-a-php-function-that-has-a-argument-type-hint-set/)

namespace Original;

class ClassExtra {}

class ClassA {
    public function __construct($container, ClassB $classB) {}
}

class ClassB {
    public function __construct(ClassExtra $classExtra) {}
}

class ClassC {
    public $classB;
    public $containers;
    public function __construct(ClassB $classB) {
        $this->classB = $classB;
    }
    public function container(string $container = 'default'): ClassA
    {
        $this->containers[$container] = new ClassA($container, $this->classB);
        return $this->containers[$container];
    }
}

Namespace Changes;

Class NewClassA extends \Original\ClassA {}
Class NewClassB extends \Original\ClassB {}
Class NewClassC extends \Original\ClassC {
    public function container(string $container = 'default'): \Original\ClassA
    {
        $this->containers[$container] = new NewClassA($container, $this->classB);
        return $this->containers[$container];
    }
}

$classC = new \Original\ClassC(new \Original\ClassB(new \Original\ClassExtra()));
var_dump(get_class($classC->container('test')));
/* string(15) "Original\ClassA" */

$classC = new NewClassC(new NewClassB(new \Original\ClassExtra()));
var_dump(get_class($classC->container('test')));
/* string(17) "Changes\NewClassA" */

I did the equivalent to the Orchestra\Assets package.

Please or to participate in this conversation.