|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2013-02-18 11:58 UTC] imenem at inox dot ru
Description:
------------
In PHP 5.4.4 test script works as expected, in 5.4.11 script caused fatal error.
Test script:
---------------
<?php
class TestParentClass
{
public function method()
{
print_r('Parent method');
print "\n";
}
}
trait TestTrait
{
public function method()
{
print_r('Trait method');
print "\n";
}
}
class TestChildClass extends TestParentClass
{
use TestTrait
{
TestTrait::method as methodAlias;
TestParentClass::method insteadof TestTrait;
}
}
(new TestChildClass)->method();
(new TestChildClass)->methodAlias();
Expected result:
----------------
Parent method
Trait method
Actual result:
--------------
Fatal error: Trait TestParentClass is not used in test.php on line 28
Patchesdeny_use_with_classes.patch (last revision 2013-02-21 09:09 UTC by laruence@php.net)bug64235.patch (last revision 2013-02-20 08:07 UTC by laruence@php.net) bug64235.phpt (last revision 2013-02-20 07:41 UTC by laruence@php.net) Pull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 20 21:00:02 2025 UTC |
actually, I was looking into this, I have thought the similar fix of you, but unfortunatly, it is wrong, thinking of this: <?php class TestParentClass { public function method() { print_r('Parent method'); print "\n"; } } trait TestTrait { public function method() { print_r('Trait method'); print "\n"; } } class TestChildClass extends TestParentClass { use TestTrait { TestParentClass::method as methodParent; } } (new TestChildClass)->methodParent(); ~Hi: The `insteadof` and `as` operators where not intended to be used with classes. The syntax is intended to convey that the use operation is refined by specifying how to resolve conflicts __between__ traits. That's the idea at least. My solution for the initial problem presented would be to provide a method such as follows in the TestChildClass: public function method() { parent::method(); } I understand that this is not ideal, and requires you to repeat yourself. However, it is consistent in the sense that traits are traits and not classes, and both get mixed up as little as possible, However, beside the academic notion of purity, I can see that `TestParentClass::method insteadof TestTrait;` is useful. [I wonder whether `parent::method insteadof TestTrait;` should be supported as well.] Laruence's example with `TestParentClass::method as methodParent;` is however problematic. Traits are not supposed to conflict with classes, but with traits. So, allowing the introduction of aliases for method of the super class seems to me as something that is problematic, because it mixes up the concepts. If you need an alias for the method of a parent class, the classic way would be: public function foo() { parent::bar(); } No? Well, that's my point of view. So, from a practical point of view, referring to the parent (and only the direct parent) class in `insteadof` might be a useful/acceptable feature. The use in conjunction with `as` seems to be something I would advocate against. In either way, beside bugs that made this possible in the first place, I would consider both ideas as new features that need to be documented/discussed. I thought that we had a test that only the traits listed in the `use` clause can be used for the `as`/`insteadof` operators, but that's either broken or not there, or a bug that was fixed in 5.4.11 as the original report suggests. Therefore, from my perspective, 5.4.11 shows the behavior that's intended by the spec/RFC. Best regards Stefancurrently using class in context of trait 'as' and 'inteadof' didn't work most of the time (as the code below demonstrated, even after apply the patch larucence attached). Only the use case of this bug report, it HAPPENED to work. To keep the BC of the problem reported, as I suggested in the previous patch we could mark it as deprecated in 5.4. So forbid class in 'as' and 'insteadof' didn't break because most of them didn't even work. in the case of parent class insteadof usage, the REAL need is avoid trait's method overwrite the method inherited but not refer to parent class. there is a really easy workaround: rename the conflict method as a new one `Traits::method as _use_less` or something else, if we really need the method from parent. <?php class Standalone { function foo() { echo "I shouldn't been called"; } } class GrandParent { function foo() { echo "GrandParent"; } } class Parent extends GrandParent { function foo() { echo "Parent"; } } trait T { function foo() { echo "Trait"; } } class Child extends Parent { use T { /* as */ Parent::foo as bar; // Child::bar() -> undefined method StandAlone::foo as bar; // Child::bar() -> undefined method StandAlone::foo as foo; // Child::foo() -> "Trait" GrandParent::foo as bar; // Child::bar() -> undefined method /* insteadof */ Parent::foo insteadof T; // works by accident -> "Parent" GrandParent::foo insteadof T; // -> "Parent" but not "Grand" StandAlone::foo insteadof T; // ->"Parent" } }