php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #70761 Fatal error if missing parent class - create "stub" class instead
Submitted: 2015-10-21 17:19 UTC Modified: 2017-03-16 18:22 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: andreas at dqxtech dot net Assigned:
Status: Suspended Package: Scripting Engine problem
PHP Version: 7.0.0RC5 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: andreas at dqxtech dot net
New email:
PHP Version: OS:

 

 [2015-10-21 17:19 UTC] andreas at dqxtech dot net
Description:
------------
(similar to https://bugs.php.net/bug.php?id=53036&edit=2, but more relevant issue summary - * see below)

Currently if a script wants to declare a class, and inherit from a missing parent class, a fatal error will occur.

This causes problems with class_exists() + autoload:
- If class C cannot be autoloaded, then class_exists('C') will simply return false.
- If class C can be autoloaded, but the parent class P can not, then class_exists('C') will include the file that defines C, which triggers a fatal error because P does not exist and cannot be autoloaded.

Typical scenario:
- Library LibC contains a class C with parent class P, where P is defined in another library LibP.
- Library LibC does NOT explicitly depend on LibP. Instead, the class C should only be used if LibP is installed in the project. We could say, LibP is an "optional dependency" of LibC.
- A discovery algorithm scans LibC for useful classes, and tries "class_exists('C')", or explicitly includes the file defining C -> fatal error, because P is missing.

Instead, such discovery algorithms nowadays need to use PHP parsing and stuff like Doctrine's StaticReflectionParser. https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Reflection/StaticReflectionParser.php

Solution:
- Instead of a fatal, simply behave as if the class C is not defined. So, class_exists('C') should return FALSE.
- Internally remember the "stub" definition of C.
- If class_exists('C') is called again, and autoloading for 'C' would be triggered again, instead trigger the autoload for 'P' and attempt to complete the stub definition of C.
- Provide a new language feature to test for "stub" class definitions.

---------

* Why a new issue, and not comment on https://bugs.php.net/bug.php?id=53036&edit=2 ?
The other issue paints this as a problem with class_exists() + autoload. But solution is to change the behavior of include(), independent of class_exists() + autoload. The description and code example in this issue focuses directly on the include(). I expect this to allow for a more focused discussion.

Test script:
---------------
// Assuming class P does not exist and cannot be autoloaded either.
class C extends P {}

print class_exists('C') ? 'yes' : 'no';

Expected result:
----------------
'no'
(because C has a non-existing base class)

Actual result:
--------------
PHP Fatal error:  Class 'P' not found [..]

(triggered by the class definition, NOT by the class_exists())

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-10-21 17:22 UTC] stas@php.net
-Package: PHP Language Specification +Package: Scripting Engine problem
 [2017-03-16 18:22 UTC] nikic@php.net
-Status: Open +Status: Suspended
 [2017-03-16 18:22 UTC] nikic@php.net
Marking as suspended as such a change would require an RFC (https://wiki.php.net/rfc/howto).

Personally, I very much doubt this is going to happen. This is a lot of complexity for an edge-case, and will additionally convert currently obvious failures (typo in extends clause) into a lot of head scratching about classes silently not being defined for unknown reasons.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 03:01:28 2024 UTC