Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

di->get vs di->getShared

Hello,

if we do setShared(service) then no matter which way we call it get or getShared.

But if we do set(service) then: ->get(service) we always get the new instance ->getShared(service) we always get new instance

Why do we need to have services in DI which always gets new instance? Do you have real life example?

I suggest to keep get() & set() methods as shared services and getFresh() if we really want to get new instance of that service

The same reason one might need both instances and singletons of a class.

Consider this service:

class TimeElapsed {
    protected $_start;
    public function __construct()
    {
        $this->start();
    }

    public function start()
    {
        $this->_start = microtime(true);
    }

    public function print()
    {
        echo round((microtime(true)-$this->_start)/1000), ' seconds elapsed', PHP_EOL;
    }
}
$di->set('elapsed', function() {
    return new TimeElapsed();
});
$elapsed = $this->getDI()->get('elapsed');
sleep(5);
$elapsed->print();
// Should print 5 seconds elapsed

This way you can arbitrarily stack these timers.

edited 12d ago

Why do you need DI for this class? You can do the same just by doing

$elapsed = new TimeElapsed();
sleep(5);
$elapsed->print();

Also you cannot inject anywhere such service:

$di->set('custom.service', function () use ($di) {
    return new CustomService($di->get('elapsed')); // does it looks correct?
});

The same reason one might need both instances and singletons of a class.

Consider this service:

class TimeElapsed {
  protected $_start;
  public function __construct()
  {
      $this->start();
  }

  public function start()
  {
      $this->_start = microtime(true);
  }

  public function print()
  {
      echo round((microtime(true)-$this->_start)/1000), ' seconds elapsed', PHP_EOL;
  }
}
$di->set('elapsed', function() {
  return new TimeElapsed();
});
$elapsed = $this->getDI()->get('elapsed');
sleep(5);
$elapsed->print();
// Should print 5 seconds elapsed

This way you can arbitrarily stack these timers.

actually Di::getShared() resolves the service and stores it in Di::_services for future recalls

check the source code @ https://github.com/phalcon/cphalcon/blob/master/phalcon/di.zep

@Karolis I changed the behaviour of DI::get for v4.0-alpha3. Now if the service is set as shared then it will treat it the same for DI::get and DI::getShared. Up until then it was essentially a bit broken in that it didn't do what I always though that it did (until I looked into the source). I made these changes in preparation of officially proposing that some of the internal Phalcon usage of DI::getShared be changed to DI::get. With the changes to get it should be just about as fast as using getShared in addition to proper shared instance caching. By using get it will allow for individual services to be defined as non-shared. This will set the stage for better or easier process forking (DB, etc) as well as future async app designs. I figure that every internal Phalcon usage of getShared should be changed to get unless that service would always need to be shared for the program to function correctly. So there would basically be an audit of every service to see how it needs to operate. The factory default DI definitions could always be shared and then the special cases would require the user to override it with a non-shared service. I don't exactly know how that will work out but it needs to go that way.



82.8k
Accepted
answer

An example could be a component that connects to a Google account. You pass it along the connection variables when calling get(), in order to be able to connect to multiple different accounts - possibly concurrently.