php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #38286 Class with interface implemented by a parent class fails due to constants
Submitted: 2006-08-01 18:43 UTC Modified: 2007-08-27 01:00 UTC
Votes:13
Avg. Score:4.7 ± 0.6
Reproduced:10 of 10 (100.0%)
Same Version:7 (70.0%)
Same OS:6 (60.0%)
From: baldurien at bbnwn dot eu Assigned:
Status: No Feedback Package: Scripting Engine problem
PHP Version: 5CVS-2006-08-01 (snap) OS: Windows XP
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: baldurien at bbnwn dot eu
New email:
PHP Version: OS:

 

 [2006-08-01 18:43 UTC] baldurien at bbnwn dot eu
Description:
------------
Hi,

I've got this following error :

Fatal error: Cannot inherit previously-inherited constant SEEK_SET from interface InputStream in bugs\Stream\FooInputStream.php on line 5

The contract is simple : it tell me that I'm redefining a constant, in class FooInputStream, while I use the same code in BarInputStream (see source below)

The Idea of what I'm trying to do is nothing less than simple OOP, by having an abstract class implementing class of an interface A for me, extending the abstract class, and implementing another interface that also implements (or extends) A.

Reproduce code:
---------------
See http://www.bbnwn.eu/works/stream-bugs.zip

run bugs.php for a complete test

The test will do the following :

1. get all file finishing by Loader.php, which are class supposed to load some kind of class, extending class Loader.
2. get all class, and via Reflection, check if we may instanciate them, store them into a classes array (this will also bug if you directly call $clazz->newInstance()->load())
3. create a new instance, and call load() method.

It was tested on php5.1.4 but also on php5.2, and php6 (snapshots dated on 1 august)

It is somehow related to bug 33732 (http://bugs.php.net/bug.php?id=33732)

Note that if you don't use a loop, and instead put 

require_once 'BarLoader.php';
require_once 'FooLoader.php';

It fails.

But: if BarStream and FooStream does not implements Stream, it works.

It also fails without using reflection :

$b = new BarLoader();
$b->load();
$f = new FooLoader();
$f->load();

Expected result:
----------------
No fatal error for FooInputStream, like in class BarInputStream

Actual result:
--------------
A fatal error, in class FooInputStream

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-08-01 20:39 UTC] tony2001@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc.

If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.


 [2006-08-02 06:05 UTC] baldurien at bbnwn dot eu
If you read carefully, then you'll find a link :

http://www.bbnwn.eu/works/stream-bugs.zip

This an archive file containing all the sources (eg: the test case for the bug), which when you call the file "bug.php" will show you an example of bug.

I can't provide it on the server, as a PHP file, as it is a php4 server (which does not support interface).

If you want a txt file with all the code inlined, then no : the bug is DUE to the presence of require_once. The sole thing I can do is to prepend the name of each file before, meaning you will have the create each file on your own, while they are in the archive file.
 [2006-08-02 10:16 UTC] tony2001@php.net
Please provide SHORT but COMPLETE reproduce script.
I don't think you need a bunch of files to get such a simple error message. I'm pretty sure it's possible to reproduce it with just a couple of classes in 10 lines.

# unzip stream-bugs.zip
Archive:  stream-bugs.zip
   creating: Stream/
  inflating: Stream/BarInputStream.php
  inflating: Stream/BarLoader.php
  inflating: Stream/BarStream.php
  inflating: Stream/bug.php
  inflating: Stream/FooInputStream.php
  inflating: Stream/FooLoader.php
  inflating: Stream/FooStream.php
  inflating: Stream/InputStream.php
  inflating: Stream/Loader.php
  inflating: Stream/Stream.php

I don't see any "bug.php" or anything else that could help first of all to understand what is the problem.
 [2006-08-02 12:00 UTC] baldurien at bbnwn dot eu
For the content of archive, you should look for Stream/bug.php.

For the number of files, no:

1. I tell you that a problem with require_once, hence, having all class and interface declared in the same file work as expected

2. I can go down to 4 files. Whose content is that (I'm not at home, today and tomorrow, so I can't send an archive file) : 

--- bug.php
<?php
abstract class Loader {
  protected abstract function loadFiles();
  protected abstract function doSomething();
  public final function load() {
    $this->loadFiles();
    $this->doSomething();
  }
}
class BarLoader extends Loader {
  protected function loadFiles() {require_once 'BarInputStream.php';}
  protected function doSomething() {
    $bar = new BarInputStream();
    $bar->seek(1);
  }
}
class FooLoader extends Loader {
  protected function loadFiles() {require_once 'FooInputStream.php';}
  protected function doSomething() {
    $foo = new FooInputStream();
  }
}
$b = new BarLoader();
$b->load();
$f = new FooLoader();
$f->load();
?>

--- InputStream.php
<?php
interface Stream {
  const SEEK_SET = SEEK_SET;
  const SEEK_CUR = SEEK_CUR;
  const SEEK_END = SEEK_END;
  
  public function seek($pos, $whence = Stream::SEEK_SET);
}
interface InputStream extends Stream {
  public function read(&$data);
}
?>
--- BarInputStream
<?php
require_once 'InputStream.php';
abstract class BarStream implements Stream {
  public function seek($pos, $whence = Stream::SEEK_SET) {
    echo __CLASS__, '->', __FUNCTION__, '()', "\n";
  }
}
class BarInputStream extends BarStream implements InputStream {
  public function read(&$data) {
    echo __CLASS__, '->', __FUNCTION__, '()', "\n";
  }
}
?>
--- FooInputStream
<?php
require_once 'InputStream.php';
abstract class FooStream implements Stream {
  public function seek($pos, $whence = Stream::SEEK_SET) {
    echo __CLASS__, '->', __FUNCTION__, '()', "\n";
  }
}
class FooInputStream extends FooStream implements InputStream {
  public function read(&$data) {
    echo __CLASS__, '->', __FUNCTION__, '()', "\n";
  }
}
?>
---END

I will add a short notice (if that serve): this will not happen if you don't call $bar->seek(1).
 [2006-08-02 12:00 UTC] baldurien at bbnwn dot eu
Note : that BarInputStream.php and FooInputStream.php.
 [2006-08-08 09:13 UTC] baldurien at bbnwn dot eu
Here is a zip file with less file (in fact, just 4) :

http://www.bbnwn.eu/works/stream-bugs-with-less-files.zip

Simply run php -f bug.php
 [2007-08-27 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 23:01:28 2024 UTC