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

Cause error: Error: Cannot access trait constant self::CONTROL_FLASH_MESSAGE directly #315

Open
zeleznypa opened this issue May 19, 2024 · 13 comments

Comments

@zeleznypa
Copy link

Last change on this line cause an error.

? is_object($tmp = $param->getDefaultValue()) ? ['object' => $tmp::class] : ['value' => $tmp]

Previous code works well

? is_object($tmp = Reflection::getParameterDefaultValue($param)) ? ['object' => $tmp::class] : ['value' => $tmp]

When I have a Presenter that use trait that contains the following code:

<?php

declare(strict_types=1);

namespace Interitty\FlashMessageControl;

use Nette\ComponentModel\IComponent as ComponentInterface;

use function assert;

trait FlashMessageControlHelperTrait
{
    /** All available control name constants */
    public const CONTROL_FLASH_MESSAGE = 'flashMessage';

    /**
     * Componentby name getter
     *
     * @param bool $throw Throw exception if component doesn't exist?
     * @return ComponentInterface|null
     */
    abstract public function getComponent(string $name, bool $throw = true): ?ComponentInterface;

    /**
     * FlashMessage control getter
     *
     * @param string $name [OPTIONAL]
     * @return FlashMessageControl
     */
    public function getComponentFlashMessage(string $name = self::CONTROL_FLASH_MESSAGE): FlashMessageControl
    {
        $control = $this->getComponent($name);
        assert($control instanceof FlashMessageControl);
        return $control;
    }
}
@dg
Copy link
Member

dg commented May 19, 2024

Could you please report this as a PHP bug as well? That ReflectionParameter::getDefaultValue() crashes in this situation?

@zeleznypa
Copy link
Author

The old version with ReflectionParameter::getDefaultValue() works well in the same situation

@dg
Copy link
Member

dg commented May 19, 2024

So where's the problem?

@zeleznypa
Copy link
Author

The problem is in the new version, where the code $param->getDefaultValue()) is used and cause the "Error: Cannot access trait constant self::CONTROL_FLASH_MESSAGE directly"

@dg
Copy link
Member

dg commented May 19, 2024

So ReflectionParameter::getDefaultValue() isn't working so well, is it?

@zeleznypa
Copy link
Author

ReflectionParameter::getDefaultValue() works well
$param->getDefaultValue() cause the "Error: Cannot access trait constant self::CONTROL_FLASH_MESSAGE directly"

Nette\DI 3.2.0 works well
Nette\DI 3.2.2 cause the "Error: Cannot access trait constant self::CONTROL_FLASH_MESSAGE directly"

@zeleznypa
Copy link
Author

zeleznypa commented May 19, 2024

It is really strange, because when I tried to isolate the root cause in the 3v4l.org, it works also with the $param->getDefaultValue().

@dg
Copy link
Member

dg commented May 19, 2024

What is the difference between ReflectionParameter::getDefaultValue() and $param->getDefaultValue() ????

@zeleznypa
Copy link
Author

zeleznypa commented May 19, 2024

Sorry my fault :(

I was reporting and speaking about \Nette\Utils\Reflection::getParameterDefaultValue($param)

But you are speaking about \ReflectionParameter::getDefaultValue()

@mabar
Copy link
Contributor

mabar commented May 19, 2024

It is really strange, because when I tried to isolate the root cause in the 3v4l.org, it works also with the $param->getDefaultValue().

It happens only when $method is got from the trait reflection instead of the class reflection https://3v4l.org/s8ofg#v8.3.7
PHP (mostly) requires traits analysed in context of the class where the trait is used. And it makes sense in this case - constant could be defined by the class using the trait, not by the trait itself - https://3v4l.org/V4RNt#v8.3.7

(Interesting side-note: PHP allows to redefine constant value if it is defined by interface and overriden by a class or a trait, but constant value defined by a trait can't be redefined by a class, PHP would throw fatal error for that - https://3v4l.org/oYmEW#v8.3.7)

@zeleznypa
Copy link
Author

zeleznypa commented May 19, 2024

Great point @mabar. When I debug/try/catch/parse and then debug the situation that happening in my code, the $method when it crashed return the Trait as a result for ->getDeclaringClass().

The previous mechanism was safe, because it was parsing the constant value different way than current version, that try to access the trait constant directly.

So the \Nette\Utils\Reflection::getParameterDefaultValue() still have some place and should not be deprecated, because it can parse default value also for methods from trait?

@dg
Copy link
Member

dg commented May 19, 2024

And that brings us back to whether you could report this as a bug on PHP, because it should work.

@zeleznypa
Copy link
Author

@dg Im not sure with that.

A) I have never report a bug to PHP. Where should I do that?

B) I think, that it is not a bug of PHP.

You cant call PHP Trait::CONST, so you cant ask for Reflection on trait and getDefaultParameter, that (from my point of view) do the same.

When you call the reflection on the class that use the trait, it works.

What do you think?

dg added a commit that referenced this issue Jun 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants