Description
If I enable developer mode by adding the following to my .htacess file
SetEnv MAGE_MODE developer
and then add a plugin configuration
#File: app/code/Pulsestorm/Testbed/etc/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<type name="Magento\Framework\Logger\Monolog">
<plugin name="namespace_vendor_magento_framework_logger_monolog" type="Pulsestorm\Testbed\Plugin\MagentoFrameworkLoggerMonolog" />
</type>
</config>
Magento doesn't seem to see the plugin until I do a full compile
php bin/magento setup:di:compile
Expected Behavior: When Magento developer mode is enabled, all plugins are active immediately. From an end-client-programmer-user perspective the plugin system should behave the same in all Magento modes (developer, production, default, etc.) irrespective of the implementation details
Actual Behavior: Magento doesn't recognize certain plugins until the setup:di:compile
command is run
Notes
I believe this problem is limited to what I'd call early stage single-instance-object instantiation. If the object manager creates an instance/singleton object (i.e. via get
) before the framework loads the di configuration, that instance/singleton is cached in the object manager. Since the object manager, by definition, caches instance/singleton objects, this means these early stage objects never have a chance to be intercepted in developer mode.
That is, in
#File: vendor/magento/framework/Interception/ObjectManager/Config/Developer.php
public function getInstanceType($instanceName)
{
$type = parent::getInstanceType($instanceName);
if ($this->interceptionConfig && $this->interceptionConfig->hasPlugins($instanceName)) {
return $type . '\\Interceptor';
}
return $type;
}
The $this->interceptionConfig
is false for a time. In a quick test on the 2.0 system, that means the following classes are "un-intercept-able" by the developer mode object manager (without a compile)
Magento\Framework\App\ObjectManager\ConfigLoader
Magento\Framework\App\Cache\Type\Config
Magento\Framework\App\Cache\Type\FrontendPool
Magento\Framework\App\Cache\Frontend\Pool
Magento\Framework\App\Cache\Frontend\Factory
Magento\Framework\Filesystem
Magento\Framework\Filesystem\Directory\ReadFactory
Magento\Framework\Filesystem\Directory\WriteFactory
Magento\Framework\App\ResourceConnection\Proxy
Magento\Framework\ObjectManager\Config\Reader\DomFactory
Magento\Framework\App\ObjectManager\ConfigCache
Magento\Framework\Cache\Frontend\Adapter\Zend
Magento\Framework\Cache\Frontend\Decorator\TagScope
Magento\Framework\Cache\Frontend\Decorator\Logger
Magento\Framework\Cache\InvalidateLogger
Magento\Framework\App\Request\Http
Magento\Framework\Stdlib\Cookie\PhpCookieReader
Magento\Framework\Stdlib\StringUtils
Magento\Framework\App\Route\ConfigInterface\Proxy
Magento\Backend\App\Request\PathInfoProcessor\Proxy
Magento\Framework\Logger\Monolog
Magento\Framework\Logger\Handler\System
Magento\Framework\Filesystem\Driver\File
Magento\Framework\Logger\Handler\Exception
Magento\Framework\Logger\Handler\Debug
Magento\Framework\Cache\Frontend\Adapter\Zend
Magento\Framework\Cache\Frontend\Decorator\TagScope
Magento\Framework\Cache\Frontend\Decorator\Logger
Magento\Framework\App\Cache\Type\AccessProxy
Magento\Framework\App\Cache\State
Magento\Framework\App\DeploymentConfig\Writer
Magento\Framework\App\DeploymentConfig\Reader
Magento\Framework\Config\File\ConfigFilePool
Magento\Framework\Config\Scope
Magento\Framework\App\AreaList\Proxy
Magento\Framework\Interception\Config\Config
Magento\Framework\ObjectManager\Config\Reader\Dom\Proxy
Magento\Framework\Config\Scope
Not sure what the right fix here is. My naive approach to something like this would be to
- Limit the pre di configuration loading use of the object manager
- Formally introduce the concept of stages into the object manager (pre-di.xml, pre area-di.xml, etc.)
- Add tooling that warns developers if they're trying to plugin to one of these classes.
That said, as a third-part I wouldn't presume to come up with a solution myself as this is the sort of thing that will have impact system wide across multiple teams.
Right now if developers are trying to plugin to one of the above classes while working in developer mode they're going to spin their wheels for a bit before realize them need to run setup:di:compile
even though developer mode is supposed, and sometimes does, make that unnecessary. That's the problem I'd be interested in seeing solved.