Hello everybody!
At the moment the *get_class *function has three possible behaviors
-
get_class is called with the instance of the class and return the name
of the class name of the instance; -
get_class is called without any parameters inside a class and return
the containing class name -
get_class is called without any parameters outside a class, trigger a
warning complaining about this and return false
At the state of art of PHP the second behavior is not needed anymore
because the name of the containing class can be easily obtained via CLASS
or via get_class($this) or via *get_called_class() *when extending a class
in a static method.
Moreover get_class without any parameters is a possible source of bugs in
situations like this:
$result = $repository->find(100);
echo get_class($result);
If $result is null the output of get_class is the name of the
containing class instead of the name of the object I wanted.
I would like to a change to the get_class behavior in order to support
only the first behavior, unfortunately this is a huge BC, so we could start
triggering a deprecation warning at first.
What do you think? I'm missing something?
References:
Implementation of get_class
http://lxr.php.net/xref/PHP_MASTER/Zend/zend_builtin_functions.c#995
Thanks
Lorenzo
Hello everybody!
Hello Lorenzo,
If $result is null the output of get_class is the name of the
containing class instead of the name of the object I wanted.
Yes, that is bad. Perhaps a smaller change would give you the desired
behaviour though?
If we just give a warning/error if any non-object type is passed as
the parameter, that would achieve what you want wouldn't it? And it
provides a slightly easier 'upgrade' path for people who, for whatever
reason, are currently passing null to it.
the name of the containing class can be easily obtained via CLASS
or via get_class($this) or via *get_called_class()
The first two can't be used directly as a callable, and so can't be
passed around as a function. And get_called_class()
returns the late
static binding class.
So if the smaller change of just giving a warning/error on any
non-object as a parameter gives the desired result, I would recommend
doing just that. It might even be possible to do it as a bug fix...
cheers
Dan
Refactoring if non-objects are no longer allowed.
Current code:
echo get_class($result);
Would need to be changed to:
if ($result === null) {
echo get_class()
;
}
else {
echo get_class($result);
}
get_called_class is late static binding.
class foo {
static function bar() {
//return $fn(null);
echo get_class()
."\n";
echo get_called_class()
."\n";
}
}
class Quux extends foo { }
Quux::bar();
// Output is:
// foo
// Quux
Callables can passed around
class foo {
public static function bar(callable $fn) {
return $fn();
}
}
echo foo::bar('get_class');
2016-01-28 23:35 GMT+01:00 Dan Ackroyd danack@basereality.com:
On 28 January 2016 at 19:17, Lorenzo Fontana fontanalorenz@gmail.com
wrote:Hello everybody!
Hello Lorenzo,
If $result is null the output of get_class is the name of the
containing class instead of the name of the object I wanted.Yes, that is bad. Perhaps a smaller change would give you the desired
behaviour though?If we just give a warning/error if any non-object type is passed as
the parameter, that would achieve what you want wouldn't it? And it
provides a slightly easier 'upgrade' path for people who, for whatever
reason, are currently passing null to it.the name of the containing class can be easily obtained via CLASS
or via get_class($this) or via *get_called_class()The first two can't be used directly as a callable, and so can't be
passed around as a function. Andget_called_class()
returns the late
static binding class.So if the smaller change of just giving a warning/error on any
non-object as a parameter gives the desired result, I would recommend
doing just that. It might even be possible to do it as a bug fix...cheers
DanRefactoring if non-objects are no longer allowed.
Current code:
echo get_class($result);Would need to be changed to:
if ($result === null) {
echoget_class()
;
}
else {
echo get_class($result);
}get_called_class is late static binding.
class foo {
static function bar() {
//return $fn(null);
echoget_class()
."\n";
echoget_called_class()
."\n";
}
}class Quux extends foo { }
Quux::bar();
// Output is:
// foo
// QuuxCallables can passed around
class foo {
public static function bar(callable $fn) {
return $fn();
}
}echo foo::bar('get_class');
Yes, that is bad. Perhaps a smaller change would give you the desired
behaviour though?
If we just give a warning/error if any non-object type is passed as
the parameter, that would achieve what you want wouldn't it? And it
provides a slightly easier 'upgrade' path for people who, for whatever
reason, are currently passing null to it.
Yes is what I would like to do, start saying people that they should change
that by triggering a deprecation notice so they can refactor their code.
The first two can't be used directly as a callable, and so can't be
passed around as a function. And
get_called_class()
returns the late
static binding class.
I don't see any way to get the declaring class passing a callable as you
pointed out in the following code if not using get_class without
parameters. Any idea?
class foo {
public static function bar(callable $fn) {
return $fn();
}
}
echo foo::bar('get_class');
Thanks,
Lorenzo
2016-01-29 0:22 GMT+01:00 Lorenzo Fontana fontanalorenz@gmail.com:
2016-01-28 23:35 GMT+01:00 Dan Ackroyd danack@basereality.com:
On 28 January 2016 at 19:17, Lorenzo Fontana fontanalorenz@gmail.com
wrote:Hello everybody!
Hello Lorenzo,
If $result is null the output of get_class is the name of the
containing class instead of the name of the object I wanted.Yes, that is bad. Perhaps a smaller change would give you the desired
behaviour though?If we just give a warning/error if any non-object type is passed as
the parameter, that would achieve what you want wouldn't it? And it
provides a slightly easier 'upgrade' path for people who, for whatever
reason, are currently passing null to it.the name of the containing class can be easily obtained via CLASS
or via get_class($this) or via *get_called_class()The first two can't be used directly as a callable, and so can't be
passed around as a function. Andget_called_class()
returns the late
static binding class.So if the smaller change of just giving a warning/error on any
non-object as a parameter gives the desired result, I would recommend
doing just that. It might even be possible to do it as a bug fix...cheers
DanRefactoring if non-objects are no longer allowed.
Current code:
echo get_class($result);Would need to be changed to:
if ($result === null) {
echoget_class()
;
}
else {
echo get_class($result);
}get_called_class is late static binding.
class foo {
static function bar() {
//return $fn(null);
echoget_class()
."\n";
echoget_called_class()
."\n";
}
}class Quux extends foo { }
Quux::bar();
// Output is:
// foo
// QuuxCallables can passed around
class foo {
public static function bar(callable $fn) {
return $fn();
}
}echo foo::bar('get_class');
Yes, that is bad. Perhaps a smaller change would give you the desired
behaviour though?
If we just give a warning/error if any non-object type is passed as
the parameter, that would achieve what you want wouldn't it? And it
provides a slightly easier 'upgrade' path for people who, for whatever
reason, are currently passing null to it.Yes is what I would like to do, start saying people that they should
change that by triggering a deprecation notice so they can refactor their
code.The first two can't be used directly as a callable, and so can't be
passed around as a function. And
get_called_class()
returns the late
static binding class.I don't see any way to get the declaring class passing a callable as you
pointed out in the following code if not using get_class without
parameters. Any idea?class foo {
public static function bar(callable $fn) {
return $fn();
}
}
echo foo::bar('get_class');Thanks,
Lorenzo
Another way to obtain the declaring class in static methods but it's not a
callable is the use of self::class
class foo { static function bar() { echo self::class."\n";
echo get_called_class()
."\n"; }}class Quux extends foo {
}Quux::bar();// Output is:// foo// Quux
Yes is what I would like to do, start saying people that they should change
that by triggering a deprecation notice so they can refactor their code.
I don't think we need a deprecation notice. The behaviour when the
function is passed a null parameter is bogus, and could just be
changed to emit an E_WARNING
for the PHP 7.1 release.
cheers
Dan
Dan Ackroyd wrote on 28/01/2016 22:35:
Refactoring if non-objects are no longer allowed.
Current code:
echo get_class($result);Would need to be changed to:
if ($result === null) {
echoget_class()
;
}
else {
echo get_class($result);
}
You appear to be suggesting that "get_class()" should behave differently
than "get_class(null)". Normally a function doesn't distinguish between
"called with no parameters" and "called with default parameters". I
don't know if internal parameter handling (ZPP) works like userland
parameters in this respect, but if not impossible this would at least be
rather surprising.
It also doesn't help with your stated point of using get_class as a
callable, since you'd have to know what function it was in order to call
it in the right way (although exactly what the use case for that would
be, I've no idea).
Regards,
Rowan Collins
[IMSoP]
You appear to be suggesting that "get_class()" should behave differently
than "get_class(null)".
I don't know if internal parameter handling (ZPP) works like userland
parameters
Regardless of how internals works, it's a thing in userland PHP.
function foo($bar = null)
{
echo "number of args is: ".func_num_args(). "\n";
}
foo();
foo(null);
// Output is:
// number of args is: 0
// number of args is: 1
It's a useful thing to do when you want to distinguish between null
being passed, and the default value being used. Just like in this
case. The same is possible for internal functions.
cheers
Dan
Dan Ackroyd wrote on 29/01/2016 13:56:
You appear to be suggesting that "get_class()" should behave differently
than "get_class(null)".
I don't know if internal parameter handling (ZPP) works like userland
parameters
Regardless of how internals works, it's a thing in userland PHP.function foo($bar = null)
{
echo "number of args is: ".func_num_args(). "\n";
}foo();
foo(null);// Output is:
// number of args is: 0
// number of args is: 1It's a useful thing to do when you want to distinguish between null
being passed, and the default value being used. Just like in this
case. The same is possible for internal functions.
OK, so it's possible, but it's not something I've seen done very often,
and in my opinion it would be a really confusing thing to do.
"Ah, an optional parameter, what does it default to?" "Nothing" "You
mean null?" "No, null has a separate meaning" "Separate from what?"
"Nothing" etc...
It's worryingly reminiscent of the endless debates about isset() and
distinguishing an non-existent variable from one which has been
explicitly set to null - you're inventing an extra kind of "very null".
Presumably you'd get to this point by saying "if $bar is an int, do
this; if $bar is null, do this; oh, I need a third case, let's do some
magic with func_num_args()
"; so what happens when you need a fourth case?
Even worse, in this case, you're doing the opposite of what many
functions do - rather than saying "this parameter used to be optional,
but now you have to be specific even if you pass null", you're saying
"this parameter is still optional, but if you pass its default value in
you'll get a notice/warning".
I understand the intention, but I think this approach would just lead to
confusion.
Regards,
Rowan Collins
[IMSoP]