Bug #61970 [Com]: Restraining __construct() access level in subclass gives a fatal error

2012-12-04 Thread pwolfenden at qualys dot com
Edit report at https://bugs.php.net/bug.php?id=61970&edit=1

 ID: 61970
 Comment by: pwolfenden at qualys dot com
 Reported by:postmaster at greg0ire dot fr
 Summary:Restraining __construct() access level in subclass
 gives a fatal error
 Status: Open
 Type:   Bug
 Package:Class/Object related
 Operating System:   Linux
 PHP Version:5.3.12
 Block user comment: N
 Private report: N

 New Comment:

I don't understand why the example described on [2012-05-08 10:46 UTC] by 
cataphr...@php.net poses a problem.

I would expect class B to inherit reset(), which remains public. So what?

The point of the factory pattern, for example, is precisely to force the use of 
a single method to control the creation of new objects. And it is common OOP 
practice to implement this pattern using protected constructor methods. So it 
strikes me as bizzarre that PHP forces me to modify the whole class hierarchy 
if 
I want to enforce the use of a factory method for a derived class, and the base 
class has a public constructor.

Thank you, greg0ire, for opening this bug.


Previous Comments:

[2012-05-08 13:04:18] postmaster at greg0ire dot fr

Thanks for the detailed answer, it is very informative, especially the first 
bit, which even shows the LSP could be applied in this case.


[2012-05-08 10:46:42] cataphr...@php.net

It's true that PHP's behavior doesn't make a lot of sense from a theoretical 
perspective. However, there are some practical reasons why a different behavior 
would be -- arguably -- less desirable.

Namely, in PHP the constructor can be called from every instance method, even 
after construction. This makes it a necessity that the constructor act like 
regular instance methods. Consider:

a = new stdclass; }
function reset() { $this->__construct(); }
}
class B extends A {
private function __construct() { } //what of reset() now?
}

Plus, PHP allows enforcing constructor signatures via interfaces. This means 
you have to enforce that signature throughout the hierarchy, and this includes 
not allows changing the visibility of the constructor.

Similarly, there's no principled reason to be unable to reduce the visibility 
in static methods. But PHP also prohibits such a pattern, like Java does, even 
though there's no overriding (the method in the superclass is said to be 
hidden). But PHP, like Java, allows calling static methods through an instance 
and through the subclass name. Then if you call the reduced visibility static 
method with the subclass name or a subclass instance, what would you do? Would 
it depend on the access of the caller has to the subclass method?


[2012-05-07 18:47:00] postmaster at greg0ire dot fr

fixed the title


[2012-05-07 18:40:56] postmaster at greg0ire dot fr

Description:

Restraining the __construct() method un a subtype gives a Fatal error.
As stated in the following resources, the LSP should not apply here.


- https://bugs.php.net/bug.php?id=40880
- 
http://stackoverflow.com/questions/5490824/should-constructors-comply-with-the-liskov-substitution-principle
- 
http://ralphschindler.com/2012/03/09/php-constructor-best-practices-and-the-prototype-pattern

Test script:
---
 PHP Fatal error:  Access level to Bar::__construct() must be public (as in 
> class Foo) in /tmp/bug.php on line 9

> Fatal error: Access level to Bar::__construct() must be public (as in class 
> Foo) in /tmp/bug.php on line 9






-- 
Edit this bug report at https://bugs.php.net/bug.php?id=61970&edit=1


Bug #52339 [Com]: SPL autoloader breaks class_exists()

2012-03-16 Thread pwolfenden at qualys dot com
Edit report at https://bugs.php.net/bug.php?id=52339&edit=1

 ID: 52339
 Comment by: pwolfenden at qualys dot com
 Reported by:dangerous dot ben at gmail dot com
 Summary:SPL autoloader breaks class_exists()
 Status: Re-Opened
 Type:   Bug
 Package:SPL related
 Operating System:   any (debian)
 PHP Version:5.3.3RC2
 Block user comment: N
 Private report: N

 New Comment:

Although I have not yet migrated to 5.3, I care about this bug because I'm 
using 
an autoload function (in 5.2) which contains some directory traversal logic and 
uses class_exists() to decide whether or not to keep looking. I need to do this 
because I'm in the scenario described by james (and so cannot assume that all 
the 
package files in my codebase follow my preferred naming convention), and I 
would 
much prefer class_exists() to continue to return false rather than having it 
throw 
a new Exception.


Previous Comments:

[2012-02-03 00:01:46] frozenf...@php.net

Re-opening, as there still exists the conflict of class_exists() generating an 
error when autoloading fails, which is a chicken and the egg sort of issue. If 
one wants to try autoloading if the class doesn't exist, but autoloading fails, 
it should be possible to recover from that failure.

My understanding of the underlying code is that it generates an error in this 
case. Perhaps it should generate an exception, which can be caught an handled.


[2010-10-11 21:37:47] james at nearlysensical dot com

I 100% agree with dangerous dot ben. class_exists should return false if the 
class 
can't be autoloaded. Allowing it to do so would make it much easier to use an 
autoloader in contexts where you're interacting with an existing codebase that 
may 
not be so spl_autoload friendly. Bump.


[2010-07-15 08:18:01] dangerous dot ben at gmail dot com

I beg to differ.  As you say, class_exists() attempts to autoload if there 
second param is true, but if autoloading fails it should simply return false as 
usual rather than throw an exception.  Otherwise it is rather useless.

The fact that this only occurs when there isn't another autoloader in the stack 
should make it clear that this is a bug.  For example, the following code does 
not throw an exception:

spl_autoload_register();
spl_autoload_register(function(){});
class_exists('foo\bar');


[2010-07-15 05:11:04] ka...@php.net

You are calling class_exists() with just a class name, which leaves the second 
parameter ($autoload) set to true, which then invokes SPL and throws the 
exception, so no bug here


[2010-07-14 21:54:08] dangerous dot ben at gmail dot com

On further investigation, it appears that the error is meant to happen only if 
spl_autoload is called directly, and not via spl_autoload_call.  Unfortunately 
when spl_autoload is the only autoloader in the stack it gets called directly 
and spl_autoload_call doesn't get a look in.




The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

https://bugs.php.net/bug.php?id=52339


-- 
Edit this bug report at https://bugs.php.net/bug.php?id=52339&edit=1