php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63816 implementation child interface and after parent cause fatal error.
Submitted: 2012-12-20 15:29 UTC Modified: 2020-03-06 10:18 UTC
Votes:7
Avg. Score:3.9 ± 1.5
Reproduced:5 of 6 (83.3%)
Same Version:1 (20.0%)
Same OS:2 (40.0%)
From: kotlyar dot maksim at gmail dot com Assigned: nikic (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.4.7 OS: linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
20 - 15 = ?
Subscribe to this entry?

 
 [2012-12-20 15:29 UTC] kotlyar dot maksim at gmail dot com
Description:
------------
Order of implemented interfaces should make any difference. But it is not the 
case. If I implement child interface and parent after I will get a fatal error


Test script:
---------------
<?php
ini_set('display_errors', 1);
error_reporting(-1);


interface RootInterface
{
    function foo();
}

interface FirstChildInterface extends RootInterface
{
    function foo();
}

interface SecondChildInterface extends RootInterface
{
    function foo();
}

//works fine.
class A implements FirstChildInterface, SecondChildInterface
{
    function foo()
    {
    }
}

//also ok.
class B implements RootInterface, FirstChildInterface
{
    function foo()
    {
    }
}

//there is a fatal error.
class C implements FirstChildInterface, RootInterface 
{
    function foo()
    {
    }
}

Expected result:
----------------
Should work without errors(as previous examples).

Actual result:
--------------
PHP Fatal error:  Class C cannot implement previously implemented interface 
RootInterface in /foo/test.php on line 35
PHP Stack trace:
PHP   1. {main}() /foo/test.php:0

Fatal error: Class C cannot implement previously implemented interface 
RootInterface in /foo/test.php on line 35

Call Stack:
    0.0008     238784   1. {main}() /foo/test.php:0

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-12-20 15:31 UTC] kotlyar dot maksim at gmail dot com
Change php version
 [2012-12-20 15:31 UTC] kotlyar dot maksim at gmail dot com
-PHP Version: 5.4.10 +PHP Version: 5.4.7
 [2013-01-05 05:37 UTC] laruence@php.net
-Assigned To: +Assigned To: dmitry
 [2013-01-05 05:37 UTC] laruence@php.net
not sure why such error is threw in zend_compile.c line 2926

we can simply be silence(or warning),  then ignore it.

diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index e395795..9063023 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2920,11 +2920,7 @@ ZEND_API void 
zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
 			memmove(ce->interfaces + i, ce->interfaces + i + 1, 
sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
 			i--;
 		} else if (ce->interfaces[i] == iface) {
-			if (i < parent_iface_num) {
-				ignore = 1;
-			} else {
-				zend_error(E_COMPILE_ERROR, "Class %s cannot 
implement previously implemented interface %s", ce->name, iface->name);
-			}
+			ignore = 1;
 		}
 	}
 	if (ignore) {
 [2013-01-09 09:41 UTC] dmitry@php.net
-Status: Assigned +Status: Feedback
 [2013-01-09 09:41 UTC] dmitry@php.net
I'm not sure if this is a bug. At least the error message is absolutely correct. When class "C" implements interface "FirstChildInterface" it also implements its parent interface - "RootInterface", and when it tries to implement "RootInterface" it sees that it was already implemented before.

The Laruence's patch removes the error message completely, so the following buggy code becomes legal.

<?php
interface foo {}
class bar implements foo, foo {}
?>

I would prefer not to do it.
 [2013-01-09 10:49 UTC] kotlyar dot maksim at gmail dot com
@dmitry I see you reason. I am completely agree with you that be silent and allow 
two same interface is not a good solution.

But from the other side. I believed that I could implement interface in any order 
I want. Ordering of interfaces(maybe should be?) is not documented anywhere.
Also the described situation could be resolved without a fatal error so it at 
least not developer friendly.
 [2013-01-10 04:40 UTC] laruence@php.net
Hey, I think it not deserved a FATAL.  maybe a warning ?
 [2013-01-10 06:20 UTC] dmitry@php.net
It may be a warning, but actually it's not a big deal to fix a script once you see this FATAL error.
Finally, if we change it to warning, some script will work on 5.5 but fail on 5.3. Do we really need to introduce another incompatibility because of this small issue?
 [2013-01-11 12:03 UTC] kotlyar dot maksim at gmail dot com
I think that described order of interfaces is absolutely correct. So there 
should not be a warning\fatal.

About BC break. I dont feel like expert in this question. Personally I dont 
think that this BC break would be a problem because:

1) There are few developers how can implement interfaces in this order. 
2) They will be affected only while downgrade of php version.
3) The fatal error message gives some usefull info about what could be a 
problem.
4) The change log of php 5.5 would contain description of this change.
 [2013-02-18 00:36 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.
 [2016-01-14 13:10 UTC] danack@php.net
-Status: No Feedback +Status: Open
 [2016-01-14 13:10 UTC] danack@php.net
Dmitry wrote:
"it's not a big deal to fix a script once you see this FATAL error." 

Why should people have to fix their script. There is nothing wrong with their code, PHP is just being a bit dumb.

"so the following buggy code becomes legal.

<?php
interface foo {}
class bar implements foo, foo {}
?>

"

I don't see the problem. All that implementing an interface does is say that a class must implement certain methods with particular signatures. Although implementing an interface multiple times doesn't add anything, I can't see the problem for the simple case, 


But for more complex cases where someone has multiple classes that implement various interfaces, including the "\Serializable" interface. They then realise that one of the user-defined interfaces should actually extend "\Serializable".

Doing that, would make some code break, depending on what order the implements interfaces was written as.

That's a real problem that imo people shouldn't have to 'fix their scripts' for.
 [2016-01-16 13:00 UTC] danack@php.net
Related, the checks for method signatures are done in an order dependent manner, https://bugs.php.net/bug.php?id=67270
 [2016-09-01 07:40 UTC] xedin dot unknown at gmail dot com
Of course this is a bug. "Re-implementing" an interface in such a way only says twice that certain signatures must be present. As has been said, this situation can be resolved easily without failure. I don't believe that this deserves a fatal error, but a warning at most.
 [2020-03-05 18:05 UTC] nikic@php.net
-Assigned To: dmitry +Assigned To: nikic
 [2020-03-06 10:18 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2020-03-06 10:18 UTC] nikic@php.net
This has been fixed in PHP 7.4, I've added a test in https://github.com/php/php-src/commit/c3ab8fd3f8d8212d51b14f4d9529fd1fd1f7c2ab.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 10:01:30 2024 UTC