-
Notifications
You must be signed in to change notification settings - Fork 32
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
Incorrect default value for methods in \Psr\Log\LoggerInterface #78
Comments
@jbboehr could you check this issue? |
This does appear to be an issue, however the API for describing default parameter values in PHP 7 for extensions doesn't seem to allow it: Here's where the error is thrown in the reflection module: From what I can tell, reflection is getting the default value by looking at the function opcodes, and, well, since internal functions don't have opcodes there is nothing to look at. I agree that the current behavior of the extension is not optimal, but I don't really see a solution to the problem on my end. I will have to think about it and research some more. |
@jbboehr oh... I got it. Do you thing we have some workaround? |
If it's not too much trouble, can I see a copy of an invalid It pains me to say this, but I don't see a practical workaround on my end. PHP 7's reflection will not report a default value for an internal function. On the bright side, if I understand it correctly, it appears that PHP has implemented this functionality for PHP 8, so the extension will be correct in PHP 8 if I make the appropriate changes. |
For reference, here is the commit to php-src that will allow this to work on PHP 8: php/php-src@3709e74 |
Using ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE See #78
I hate to be that guy but the PSR interfaces are, like, super frozen so, in theory, you shouldn't have to call reflection on them. |
@jbboehr In magento we have code generation mechanism that creates "Proxy" class for the original class or interface. The instance of the interface/class will be created through ObjectManager only when some method will be called on proxy. For creating such Proxy magento uses reflection and it worked fine with all cases, except this one. Here us two examples: ❌ generated/code/Psr/Log/LoggerInterface/Proxy.php with psr extension<?php
namespace Psr\Log\LoggerInterface;
/**
* Proxy class for @see \Psr\Log\LoggerInterface
*/
class Proxy implements \Psr\Log\LoggerInterface, \Magento\Framework\ObjectManager\NoninterceptableInterface
{
/**
* Object Manager instance
*
* @var \Magento\Framework\ObjectManagerInterface
*/
protected $_objectManager = null;
/**
* Proxied instance name
*
* @var string
*/
protected $_instanceName = null;
/**
* Proxied instance
*
* @var \Psr\Log\LoggerInterface
*/
protected $_subject = null;
/**
* Instance shareability flag
*
* @var bool
*/
protected $_isShared = null;
/**
* Proxy constructor
*
* @param \Magento\Framework\ObjectManagerInterface $objectManager
* @param string $instanceName
* @param bool $shared
*/
public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager, $instanceName = '\\Psr\\Log\\LoggerInterface', $shared = true)
{
$this->_objectManager = $objectManager;
$this->_instanceName = $instanceName;
$this->_isShared = $shared;
}
/**
* @return array
*/
public function __sleep()
{
return ['_subject', '_isShared', '_instanceName'];
}
/**
* Retrieve ObjectManager from global scope
*/
public function __wakeup()
{
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
}
/**
* Clone proxied instance
*/
public function __clone()
{
$this->_subject = clone $this->_getSubject();
}
/**
* Get proxied instance
*
* @return \Psr\Log\LoggerInterface
*/
protected function _getSubject()
{
if (!$this->_subject) {
$this->_subject = true === $this->_isShared
? $this->_objectManager->get($this->_instanceName)
: $this->_objectManager->create($this->_instanceName);
}
return $this->_subject;
}
/**
* {@inheritdoc}
*/
public function emergency($message, array $context)
{
return $this->_getSubject()->emergency($message, $context);
}
/**
* {@inheritdoc}
*/
public function alert($message, array $context)
{
return $this->_getSubject()->alert($message, $context);
}
/**
* {@inheritdoc}
*/
public function critical($message, array $context)
{
return $this->_getSubject()->critical($message, $context);
}
/**
* {@inheritdoc}
*/
public function error($message, array $context)
{
return $this->_getSubject()->error($message, $context);
}
/**
* {@inheritdoc}
*/
public function warning($message, array $context)
{
return $this->_getSubject()->warning($message, $context);
}
/**
* {@inheritdoc}
*/
public function notice($message, array $context)
{
return $this->_getSubject()->notice($message, $context);
}
/**
* {@inheritdoc}
*/
public function info($message, array $context)
{
return $this->_getSubject()->info($message, $context);
}
/**
* {@inheritdoc}
*/
public function debug($message, array $context)
{
return $this->_getSubject()->debug($message, $context);
}
/**
* {@inheritdoc}
*/
public function log($level, $message, array $context)
{
return $this->_getSubject()->log($level, $message, $context);
}
} ✔ generated/code/Psr/Log/LoggerInterface/Proxy.php without psr extension<?php
namespace Psr\Log\LoggerInterface;
/**
* Proxy class for @see \Psr\Log\LoggerInterface
*/
class Proxy implements \Psr\Log\LoggerInterface, \Magento\Framework\ObjectManager\NoninterceptableInterface
{
/**
* Object Manager instance
*
* @var \Magento\Framework\ObjectManagerInterface
*/
protected $_objectManager = null;
/**
* Proxied instance name
*
* @var string
*/
protected $_instanceName = null;
/**
* Proxied instance
*
* @var \Psr\Log\LoggerInterface
*/
protected $_subject = null;
/**
* Instance shareability flag
*
* @var bool
*/
protected $_isShared = null;
/**
* Proxy constructor
*
* @param \Magento\Framework\ObjectManagerInterface $objectManager
* @param string $instanceName
* @param bool $shared
*/
public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager, $instanceName = '\\Psr\\Log\\LoggerInterface', $shared = true)
{
$this->_objectManager = $objectManager;
$this->_instanceName = $instanceName;
$this->_isShared = $shared;
}
/**
* @return array
*/
public function __sleep()
{
return ['_subject', '_isShared', '_instanceName'];
}
/**
* Retrieve ObjectManager from global scope
*/
public function __wakeup()
{
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
}
/**
* Clone proxied instance
*/
public function __clone()
{
$this->_subject = clone $this->_getSubject();
}
/**
* Get proxied instance
*
* @return \Psr\Log\LoggerInterface
*/
protected function _getSubject()
{
if (!$this->_subject) {
$this->_subject = true === $this->_isShared
? $this->_objectManager->get($this->_instanceName)
: $this->_objectManager->create($this->_instanceName);
}
return $this->_subject;
}
/**
* {@inheritdoc}
*/
public function emergency($message, array $context = [])
{
return $this->_getSubject()->emergency($message, $context);
}
/**
* {@inheritdoc}
*/
public function alert($message, array $context = [])
{
return $this->_getSubject()->alert($message, $context);
}
/**
* {@inheritdoc}
*/
public function critical($message, array $context = [])
{
return $this->_getSubject()->critical($message, $context);
}
/**
* {@inheritdoc}
*/
public function error($message, array $context = [])
{
return $this->_getSubject()->error($message, $context);
}
/**
* {@inheritdoc}
*/
public function warning($message, array $context = [])
{
return $this->_getSubject()->warning($message, $context);
}
/**
* {@inheritdoc}
*/
public function notice($message, array $context = [])
{
return $this->_getSubject()->notice($message, $context);
}
/**
* {@inheritdoc}
*/
public function info($message, array $context = [])
{
return $this->_getSubject()->info($message, $context);
}
/**
* {@inheritdoc}
*/
public function debug($message, array $context = [])
{
return $this->_getSubject()->debug($message, $context);
}
/**
* {@inheritdoc}
*/
public function log($level, $message, array $context = [])
{
return $this->_getSubject()->log($level, $message, $context);
}
} Technically we might add some special case if we're generating Proxy class for the As a workaround for now we're going to add info that |
Originally issue came from the Magento 2: magento/magento2#30575
We faced an issue with auto-generated proxy code based on the \Psr\Log\LoggerInterface.
Investigation shown that actually issue was caused by
psr
php extension - seems like default value isn't specified, while on original LoggerInterface we do have optionalcontext
argument wit default value - empty array.Tested on php 7.3 and php 7.4, both versions having the same issue.
I was able to reproduce this issue even on a simple file (checked on emergency method, but issue the same for others):
and
psr/log
installed through composer.Expected result
✔ Result without
psr
extensionActual result
❌ Result with
psr
extensionThe text was updated successfully, but these errors were encountered: