Skip to content
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
Closed

Cannot modify container when locked #118

fredw opened this issue Feb 16, 2016 · 6 comments

Comments

@fredw
Copy link

@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
Copy link
Member

@pmjones 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
Copy link
Member

@harikt harikt commented Feb 16, 2016

@fredw
Copy link
Author

@fredw 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
Copy link
Member

@harikt 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
Copy link
Member

@pmjones 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
Copy link
Author

@fredw 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
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.