New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot modify container when locked #118

Closed
fredw opened this Issue Feb 16, 2016 · 6 comments

Comments

Projects
None yet
3 participants
@fredw

fredw commented Feb 16, 2016

Hi,

I have a problem/doubt about locked container, I don't understand the functioning of this issue.
I'm trying to set after call a get and an exception is thrown:

Fatal error: Uncaught exception 'Aura\Di\Exception\ContainerLocked' with message 'Cannot modify container when locked.' 

I'm trying to do something like this:

$container = (new Aura\Di\ContainerBuilder)->newInstance();

$container->set('object1', new stdClass);
var_dump($container->isLocked());
$container->get('object1');
var_dump($container->isLocked());
$container->set('object3', new stdClass); // Exception thrown
@pmjones

This comment has been minimized.

Show comment
Hide comment
@pmjones

pmjones Feb 16, 2016

Member

Hi @fredw -- this has been a subject of some discussion. Short version: calling get() or newInstance() locks the container automatically, because further modifications to $params and $setters after creating a concrete object instance are not honored. Thus, the container is locked to prevent making changes that won't be recognized.

Although the docs say the container will be locked after get/newInstance(), I went back and forth on how to prevent changes to the container that would not be honored. Perhaps the right thing to do is throw an exception when get/newInstance are called and the container is not locked.

To pre-empt one objection: yes, the container should be locked and prevent changes after initial setup. The idea is to do all setup work before creating any objects.

Thoughts?

Member

pmjones commented Feb 16, 2016

Hi @fredw -- this has been a subject of some discussion. Short version: calling get() or newInstance() locks the container automatically, because further modifications to $params and $setters after creating a concrete object instance are not honored. Thus, the container is locked to prevent making changes that won't be recognized.

Although the docs say the container will be locked after get/newInstance(), I went back and forth on how to prevent changes to the container that would not be honored. Perhaps the right thing to do is throw an exception when get/newInstance are called and the container is not locked.

To pre-empt one objection: yes, the container should be locked and prevent changes after initial setup. The idea is to do all setup work before creating any objects.

Thoughts?

@harikt

This comment has been minimized.

Show comment
Hide comment
@harikt
Member

harikt commented Feb 16, 2016

@fredw

This comment has been minimized.

Show comment
Hide comment
@fredw

fredw Feb 17, 2016

Now I understand the reason of lock, but I have some problems that I don't know how to handle with.
I have just read the issue #107, but still don't know how to act.

I'm using Slim as router and I'm implementing middlewares to overwrite the 'errorHandler' service. Some like this:

$container = (new Aura\Di\ContainerBuilder)->newInstance();
$app = new Slim\App($container);
$app->add(new MyMiddleware($app));

// Routes - Iternally Slim calls $this->container->get('router'), 
// which causes the container to be locked
$app->get('/', function () { /* ... */ }); 

// Here all middlewares are invoked
$app->run(); 

Here is my middleware class:

class MyMiddleware
{
    private $app;

    public function __construct(Slim\App $app)
    {
        $this->app = $app;
    }

    public function __invoke($req, $resp, $next)
    {
        // ...
        $container = $this->app->getContainer();
        // Here the exception is thrown, because the container is locked
        $container->set('errorHandler', function () {});
        // ...
    }
}

I realy would like to use Aura.DI, replacing the Pimple which is the standard Slim container.
Sorry for post this particular type of question here, but I would like to know the best way to handle this situation.

fredw commented Feb 17, 2016

Now I understand the reason of lock, but I have some problems that I don't know how to handle with.
I have just read the issue #107, but still don't know how to act.

I'm using Slim as router and I'm implementing middlewares to overwrite the 'errorHandler' service. Some like this:

$container = (new Aura\Di\ContainerBuilder)->newInstance();
$app = new Slim\App($container);
$app->add(new MyMiddleware($app));

// Routes - Iternally Slim calls $this->container->get('router'), 
// which causes the container to be locked
$app->get('/', function () { /* ... */ }); 

// Here all middlewares are invoked
$app->run(); 

Here is my middleware class:

class MyMiddleware
{
    private $app;

    public function __construct(Slim\App $app)
    {
        $this->app = $app;
    }

    public function __invoke($req, $resp, $next)
    {
        // ...
        $container = $this->app->getContainer();
        // Here the exception is thrown, because the container is locked
        $container->set('errorHandler', function () {});
        // ...
    }
}

I realy would like to use Aura.DI, replacing the Pimple which is the standard Slim container.
Sorry for post this particular type of question here, but I would like to know the best way to handle this situation.

@harikt

This comment has been minimized.

Show comment
Hide comment
@harikt

harikt Feb 17, 2016

Member

@fredw move $container->set('errorHandler', function () {}); to outside.

So you can set the container definitions before calling it. That means

$container = (new Aura\Di\ContainerBuilder)->newInstance();

// move all container definitions here

$app = new Slim\App($container);

You don't need to set an error handler on execution MyMiddleware .

I suggest you to visit http://auraphp.com/packages/Aura.Di/config.html and see all examples.

Thank you.

Member

harikt commented Feb 17, 2016

@fredw move $container->set('errorHandler', function () {}); to outside.

So you can set the container definitions before calling it. That means

$container = (new Aura\Di\ContainerBuilder)->newInstance();

// move all container definitions here

$app = new Slim\App($container);

You don't need to set an error handler on execution MyMiddleware .

I suggest you to visit http://auraphp.com/packages/Aura.Di/config.html and see all examples.

Thank you.

@pmjones

This comment has been minimized.

Show comment
Hide comment
@pmjones

pmjones Feb 17, 2016

Member

Yes, @harikt has the right answer here. The intent behind Aura.Di is to use it as a Dependency Injection container, not as a service locator. Among other things, that means you configure the container in advance, and then pull objects out of it. Essentially that means putting your configurations in a config section of the application, not mixing configuration and creation.

Does that help at all?

Member

pmjones commented Feb 17, 2016

Yes, @harikt has the right answer here. The intent behind Aura.Di is to use it as a Dependency Injection container, not as a service locator. Among other things, that means you configure the container in advance, and then pull objects out of it. Essentially that means putting your configurations in a config section of the application, not mixing configuration and creation.

Does that help at all?

@fredw

This comment has been minimized.

Show comment
Hide comment
@fredw

fredw Feb 17, 2016

Thank you for response.
I had some misconceptions about Dependency Injection and Service Locator. Now I can understand what I'm doing wrong.

fredw commented Feb 17, 2016

Thank you for response.
I had some misconceptions about Dependency Injection and Service Locator. Now I can understand what I'm doing wrong.

@fredw fredw closed this Feb 17, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment