We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Cannot replace DI-injected service

For tests I'm trying to replace injected service. But can't do it.

<?php
error_reporting(E_ALL | E_NOTICE | E_STRICT);

$di = new \Phalcon\DI\FactoryDefault();
$di->set('inst', '\\Instance1');

class Instance1 {}
class Instance2 {}

$di->set('view', function() {
    return new \Phalcon\Mvc\View();
});

class IndexController extends \Phalcon\Mvc\Controller
{
    public function indexAction()
    {
        echo get_class($this->inst) . '<br />'; //outputs "Instance1"

        //trying to replace
        $this->getDi()->remove('inst');
        $this->getDi()->set('inst', '\\Instance2');

        echo get_class($this->inst) . '<br />'; //still outputs "Instance1"
    }
}

$application = new \Phalcon\Mvc\Application();
$application->setDI($di);
echo $application->handle()->getContent();

Is there a right way to replace a service?



98.9k

The service is replaced, but the first time $this->inst is accessed the service is resolved and the property is updated with the returned instance.

This will work as you expect:

<?php
error_reporting(E_ALL | E_NOTICE | E_STRICT);

$di = new \Phalcon\DI\FactoryDefault();
$di->set('inst', '\\Instance1');

class Instance1 {}
class Instance2 {}

$di->set('view', function() {
    return new \Phalcon\Mvc\View();
});

class IndexController extends \Phalcon\Mvc\Controller
{
    public function indexAction()
    {
        echo $this->getDi()->getInst() . '<br />';

        //trying to replace
        $this->getDi()->remove('inst');
        $this->getDi()->set('inst', '\\Instance2');

        echo $this->getDi()->getInst() . '<br />';
    }
}

$application = new \Phalcon\Mvc\Application();
$application->setDI($di);
echo $application->handle()->getContent();

Thank you. As I understand it's an issue with $this->inst call, because it always returns cached value. Is there a way to unset this cached instance, because I have a code and I use $this->smth everywhere. This trick won't help me.

<?php
error_reporting(E_ALL | E_NOTICE | E_STRICT);

$di = new \Phalcon\DI\FactoryDefault();
$di->set('inst', '\\Instance2');

class Instance2 {
    private $inc = 0;
    public function get()
    {
        $this->inc++;
        return $this->inc;
    }
}
class Instance3 {
    private $inc = 0;
    public function get()
    {
        $this->inc++;
        return $this->inc;
    }
}

$di->set('view', function() {
    return new \Phalcon\Mvc\View();
});

class IndexController extends \Phalcon\Mvc\Controller
{
    public function indexAction()
    {
        echo $this->getDi()->getInst()->get() . '<br />';// outputs 1
        echo $this->getDi()->getInst()->get() . '<br />';// outputs 1

        echo $this->inst->get() . '<br />';//1
        echo $this->inst->get() . '<br />';//starting to increment value: 2

        $this->getDi()->remove('inst');
        $this->getDi()->set('inst', '\\Instance3');

        echo $this->getDi()->getInst()->get() . '<br />';// new object: 1
        echo $this->getDi()->getInst()->get() . '<br />';// outputs 1

        echo $this->inst->get() . '<br />';//increment of OLD CACHED object: 3
        echo $this->inst->get() . '<br />';//4
    }
}

$application = new \Phalcon\Mvc\Application();
$application->setDI($di);
echo $application->handle()->getContent();