ClassHints and NULL

php.internals

Michael Wallner

22 years ago
Hi, I wonder if it is intended behavior, that execution stops when PHP stumbles across something like the following: ===#=== function doSth(Foo $Foo) { if (!isset($Foo)) return; // ... } doSth(null); ===#=== PHP Fatal Error: Argument 1 must not be null at ... on line 2 Is there *ANY* serious reason why NULL is not allowed in place of an object? PHP will become *really* odd if this is the way it goes. People won't stick to this new feature... Also, these errors are hard to track because they refer to the line number where the function definition is, not where the actual violation was comitted. Regards,
-- Michael - < mike(@)php.net >

Christian Schneider

22 years ago
Michael Wallner wrote:
> Is there *ANY* serious reason why NULL is not allowed in place > of an object? PHP will become *really* odd if this is the way > it goes. People won't stick to this new feature...
There was a (very) long discussion about this on this mailing list a couple of weeks ago, please check the archive. It was decided to leave it the way it is for now.
> Also, these errors are hard to track because they refer to > the line number where the function definition is, not where > the actual violation was comitted.
This is a good point and the same applies to the "Missing argument" error message. Best would be if both lines are mentioned. - Chris

Michael Wallner

22 years ago
Hi Christian Schneider, you wrote:
> There was a (very) long discussion about this on this mailing list a > couple of weeks ago, please check the archive. It was decided to > leave it the way it is for now.
Thanks. It's a pity.
>> Also, these errors are hard to track because they refer to the line >> number where the function definition is, not where the actual >> violation was comitted. > > This is a good point and the same applies to the "Missing argument" > error message. Best would be if both lines are mentioned.
Regards,
-- Michael - < mike(@)php.net >

Ray Hilton

22 years ago
Hi all, With these changes, im not entirely sure how one is supposed to indicate that the given argument to a method is not valid, not set, default, etc... I have been using PHP5 for some time now, but i can't say im up to speed on the internal technicalities of PHP, but i feel that typehinting is a fantastic new feature to help enforce, at a PHP level, your applications integrity, esepcially when you have several people working on projects. If you can no longer pass nulls, in many (of my) cases the typehinting will have to be removed, undermining the benifit. This is the way that things have been working up until now, and im sure many people have become used to this behaviour, why suddenly change it? I have also been using null to set default values of typehinted arguments as follows: function Example(DateTime $date = null) { if($date == null) { $date = DateTime::Today(); } } This is quite fundamental to a lot of the work i have been doing with PHP5, and as such have had to reverse the patch that was applied before RC3. It is also possible that there is another coding practice i could use here, in which case, any suggestions? Appologies if this is revisiting already discussed issues, but this is a rather major change in the languages functionality (well, with regards to how i have been using it). Additionally, are there any plans to allow hinting of built in types such as string, int, double and even object? Ray Christian Schneider wrote:

Marcus Börger

22 years ago
Hello Ray, Wednesday, June 16, 2004, 4:26:26 PM, you wrote:
> Hi all,
[....] - NOTHING stops you from passing NULL to functions. - Typhints are a shortcut for an 'instanceof'`test - now try NULL instanceof stdclass: php-cvs $ php -r 'var_dump(NULL instanceof stdclass);' bool(false) - what you probablywant is function bla($x) { if (is_null($x)) { // handle null } else if ($x instanceof whatever) { // handle instance } else { // handle error } } - if you look again you'll see that you are doing *three different* things in your code. Typehints have a different usage! best regards marcus

Ray Hilton

22 years ago
I understand your point, however, this is the way that other languages behave and its a feature that i consider to be very necessary and timesaving. My understanding was that Typehinting exists to save having to do such if-else clauses all the time, since 99.9% of the time, you will expect an object of a certain class or nothing at all. The problem here is that i need only to know that an argument is either an instance of a class or null, nothing else, but removing the typehinting effectively means any argument can be passed, and its not longer enforced at a PHP level, but within my own code... and since this is something that happens a lot, it seems a shame to loose this handy, timesaving functionality. Ray and Marcus Boerger wrote:

Marcus Börger

22 years ago
Hello Ray, Thursday, June 17, 2004, 3:23:10 PM, you wrote:
> I understand your point, however, this is the way that other languages > behave and its a feature that i consider to be very necessary and > timesaving.
In this case PHP behaves like Java very only one pass by reference is allowed. You compare this to C++ and others where pointers exist. And obviously you can set a pointer to NULL. BUT we are talking of pass by reference or pass by value since a PHP pointer is a '$$name' construct.
> My understanding was that Typehinting exists to save having > to do such if-else clauses all the time, since 99.9% of the time, you > will expect an object of a certain class or nothing at all.
Exactly. And i don't want to have to write function bla(Classname $x) { if (!is_null($x)).... all the time.
> The problem > here is that i need only to know that an argument is either an instance > of a class or null, nothing else, but removing the typehinting > effectively means any argument can be passed, and its not longer > enforced at a PHP level, but within my own code... and since this is > something that happens a lot, it seems a shame to loose this handy, > timesaving functionality.
I don't think it is timesaving to have to write '!is_null()' all the time. And once again null is not an instance of any class. Last but not least we know already that a lot of people like to be able to handle both instanceof or null with typehints. But at the moment we have no solution that can go into PHP 5.0. However i am quite sure we will address this for 5.1.
> Ray
> and Marcus Boerger wrote:
>>Hello Ray, >> >>Wednesday, June 16, 2004, 4:26:26 PM, you wrote: >> >> >> >>>Hi all, >>> >>> >> >>[....] >> >> - NOTHING stops you from passing NULL to functions. >> - Typhints are a shortcut for an 'instanceof'`test >> >> - now try NULL instanceof stdclass: >> >>php-cvs $ php -r 'var_dump(NULL instanceof stdclass);' >>bool(false) >> >>- what you probablywant is >>function bla($x) { >> if (is_null($x)) { >> // handle null >> } else if ($x instanceof whatever) { >> // handle instance >> } else { >> // handle error >> } >>} >> >>- if you look again you'll see that you are doing *three different* >> things in your code. Typehints have a different usage! >> >>best regards >>marcus >> >> >>
-- Best regards, Marcus mailto:helly@php.net

Hans Lellelid

22 years ago
Hi, Marcus Boerger wrote:
> Last but not least we know already that a lot of people like to > be able to handle both instanceof or null with typehints. But at > the moment we have no solution that can go into PHP 5.0. However > i am quite sure we will address this for 5.1.
I'm glad this issue will be re-evaluated. I think the loss of null option is disappointing since it precludes optional params (which was really the only place I was using it), but I also understand the reasoning. Here is a slightly related example from my code which is preventing me from being able to use typehints at all -- the issue is more than just allowing null, clearly: abstract class BasePeer { // ... public static function doDelete(Criteria $criteria, Connection $con) { // ... } } class AuthorPeer extends BasePeer { public static function doDelete(Criteria $criteria, $con = null) { if ($con === null) { $con = Transaction::begin(); } // ... parent::doDelete($criteria, $con); } } Now, even though I am using typehints propertly (i.e. not specifying one for $con in subclass), my code is no longer E_STRICT -- because the signatures do not match. :( Obviously issue is larger than the typehints, but it would be nice if the above code were able to be E_STRICT (especially since BasePeer is an abstract class) -- and it would be nice if I could use optional paramters w/ typehints. Of course, namespaces are more important than anything ;) Hans

Marcus Börger

22 years ago
Hello Hans, Friday, June 18, 2004, 4:41:08 PM, you wrote:
> Hi,
> Marcus Boerger wrote: >> Last but not least we know already that a lot of people like to >> be able to handle both instanceof or null with typehints. But at >> the moment we have no solution that can go into PHP 5.0. However >> i am quite sure we will address this for 5.1.
> I'm glad this issue will be re-evaluated. I think the loss of null > option is disappointing since it precludes optional params (which was > really the only place I was using it), but I also understand the reasoning.
gooood :-)
> Here is a slightly related example from my code [....] -- and it > would be nice if I could use optional paramters w/ typehints.
IMO thats the only valid point you brought up here. Another thing missing is that in derived classes the typehints should be able to accept superclasses like the following patch does: http://marcus-boerger.de/php/ext/ze2/ze2-type-hint-classes-20040327.diff.txt [This patch may be a little bit outdated though :-) ]
> Of course, namespaces are more important than anything ;)
hehe, could you live with packages? regards marcus

Hans Lellelid

22 years ago
Marcus Boerger wrote:
>>Here is a slightly related example from my code [....] -- and it >>would be nice if I could use optional paramters w/ typehints. > > > IMO thats the only valid point you brought up here. Another thing missing > is that in derived classes the typehints should be able to accept > superclasses like the following patch does: > http://marcus-boerger.de/php/ext/ze2/ze2-type-hint-classes-20040327.diff.txt > [This patch may be a little bit outdated though :-) ] >
Ok, well yes my message sorta morphed as I realized that the central problem was my subclasses with fewer params in method sig than the parent class. But the optional typehinted params are very useful & glad that'll be revisited.
>>Of course, namespaces are more important than anything ;) > > > hehe, could you live with packages?
Probably! yeah :) -- what's the difference? Are namespaces more like what's implement in C#/.NET (i.e. no necessary correspondence between namespace and actual assembly used to provide them) and packages something more like Java? Forgive my ignorance & if there's already a thread on this, just say so :) Thanks, Hans

Marcus Börger

22 years ago
Hello Hans, Friday, June 18, 2004, 9:15:47 PM, you wrote:
>>>Of course, namespaces are more important than anything ;) >> >> >> hehe, could you live with packages?
> Probably! yeah :) -- what's the difference? Are namespaces more like > what's implement in C#/.NET (i.e. no necessary correspondence between > namespace and actual assembly used to provide them) and packages > something more like Java? Forgive my ignorance & if there's already a > thread on this, just say so :)
something alike but without inner classes (of course) Best regards, Marcus mailto:helly@php.net

Andrei Zmievski

22 years ago
On Fri, 18 Jun 2004, Hans Lellelid wrote:
> abstract class BasePeer { > > // ... > public static function doDelete(Criteria $criteria, Connection $con) { > // ... > } > > } > > class AuthorPeer extends BasePeer { > > public static function doDelete(Criteria $criteria, $con = null) { > if ($con === null) { > $con = Transaction::begin(); > } > // ... > parent::doDelete($criteria, $con); > } > }
Wow. When did Java get $ for variables? - Andrei

Hans Lellelid

22 years ago
Andrei Zmievski wrote:
>>abstract class BasePeer { >> >> // ... >> public static function doDelete(Criteria $criteria, Connection $con) { >> // ... >> } >> >>} >> >>class AuthorPeer extends BasePeer { >> >> public static function doDelete(Criteria $criteria, $con = null) { >> if ($con === null) { >> $con = Transaction::begin(); >> } >> // ... >> parent::doDelete($criteria, $con); >> } >>} > > > Wow. When did Java get $ for variables? >
Just about the same time that Apache Torque got ported to PHP5 ;) Hans

Timm Friebe

22 years ago
On Fri, 2004-06-18 at 21:43, Andrei Zmievski wrote: [...]
> Wow. When did Java get $ for variables?
It already has:) $ cat Dollar.java public class Dollar { public static void main(String[] args) { String $str= "Hello"; System.out.println($str); } } $ /usr/local/jdk1.4.2/bin/javac Dollar.java $ CLASSPATH="." /usr/local/jdk1.4.2/bin/java Dollar Hello - Timm