I was browsing through Drupal 8's source code to try to educate myself a bit about Symfony's dependency injection and how it's used in Drupal.

Then I stumbled upon these lines in core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php:

/**
   * Overrides Symfony\Component\DependencyInjection\ContainerBuilder::set().
   *
   * Drupal's container builder can be used at runtime after compilation, so we
   * override Symfony's ContainerBuilder's restriction on setting services in a
   * frozen builder.
   *
   * @todo Restrict this to synthetic services only. Ideally, the upstream
   *   ContainerBuilder class should be fixed to allow setting synthetic
   *   services in a frozen builder.
   */
  public function set($id, $service, $scope = self::SCOPE_CONTAINER) {
    Container::set($id, $service, $scope);
  }

So then I looked at core/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Container.php where the set method is defined like this:

  /**
     * Sets a service.
     *
     * @param string $id      The service identifier
     * @param object $service The service instance
     * @param string $scope   The scope of the service
     *
     * @api
     */
    public function set($id, $service, $scope = self::SCOPE_CONTAINER)
    {
        if (self::SCOPE_PROTOTYPE === $scope) {
            throw new InvalidArgumentException('You cannot set services of scope "prototype".');
        }

        $id = strtolower($id);

        if (self::SCOPE_CONTAINER !== $scope) {
            if (!isset($this->scopedServices[$scope])) {
                throw new RuntimeException('You cannot set services of inactive scopes.');
            }

            $this->scopedServices[$scope][$id] = $service;
        }

        $this->services[$id] = $service;
    }

The thing that struck me is that is isn't defined as a static method, but it is called as one. At first I thought this might be some Drupal/Symfony/PHP magic I didn't know about, so I downloaded the Drupal 8 version of Devel and went to /devel/php to test the following code snippet:

  use Symfony\Component\DependencyInjection\Container;
  Container::set('test', new StdClass());

I got the following error:

Fatal error: Using $this when not in object context in core/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Container.php on line 201

I assume the set method of Drupal's ContainerBuilder isn't used anywhere in core? If it is, how come it doesn't throw the fatal error?

I set the priority to minor and the category to support request because obviously this doesn't actually break anything (I can use Drupal as expected). I'm just curious about how this actually works... I would be very thankful to anyone who's able and willing to explain this to me :-)

Comments

dawehner’s picture

Component: other » base system
Priority: Minor » Normal
Status: Active » Fixed

Yeah well, this is only possible if you are in the context of the calling code, so sure your custom code is simply not wrong.

You should get the container via drupal_container() and then you can set.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

Updated issue summary.

Codenator’s picture

Priority: Normal » Critical
Status: Closed (fixed) » Active

When I call use Drupal\Core\Extension\InfoParser; in my project i got the same error.
I try use InfoParser::parse($file); in code.
Thanks.

p.s. Maybe I use wrong class for parse info?
drupal_parse_info_file not working for me like in drupal 7.
p.s. I find answer but should be information in documentation about this because it is about developing modules
so using \Drupal::service('info_parser')->parse($file); help well
I am new there if I doo wrong post please explain me how do right way.

dawehner’s picture

Priority: Critical » Normal

Do you use still php 5.3?

Codenator’s picture

No php 5.5

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

cilefen’s picture

Title: Fatal error: Using $this when not in object context » Why does Drupal\Core\DependencyInjection\ContainerBuilder::set() appear to call Symfony\Component\DependencyInjection\ContainerBuilder::set() statically?
cilefen’s picture

Title: Why does Drupal\Core\DependencyInjection\ContainerBuilder::set() appear to call Symfony\Component\DependencyInjection\ContainerBuilder::set() statically? » Why does Drupal\Core\DependencyInjection\ContainerBuilder::set() appear to call Symfony\Component\DependencyInjection\Container::set() statically?

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

longwave’s picture

Status: Active » Fixed

Answering this because I've just run across this myself: although it looks like a static call, the Symfony ContainerBuilder extends Container, so Container is the grandparent class of the Drupal ContainerBuilder, and specifying the class name is the correct - and only - way to call a grandparent (or higher) method. This isn't very well documented in the PHP docs, as far as I could see.

See https://3v4l.org/P80HK for a simplified example.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.