Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

::class und constant()

0 views
Skip to first unread message

Stefan Froehlich

unread,
Jan 10, 2022, 4:46:28 AM1/10/22
to
Das folgende Codefragment:

#v+
<?php

class C {
const c = 'c';
}

var_dump(constant('C::class'));

?>
#v-

ergibt bis einschließlich PHP 7.4 "NULL", ab PHP 8.0 offenbar (das
habe ich nur mit 3v4l.org getestet) einen fatal error.

Ist das ein Bug, ein Feature, oder halt einfach so passiert? Wieso
darf ::class, das im Manual als "special constant" bezeichnet wird,
nicht wie eine Konstante verwendet werden?

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - die faszinierendste Nuance von narzistisch!
(Sloganizer)

Karl Pflästerer

unread,
Jan 10, 2022, 4:29:03 PM1/10/22
to
Stefan...@Froehlich.Priv.at (Stefan Froehlich) writes:

> Das folgende Codefragment:
>
> #v+
> <?php
>
> class C {
> const c = 'c';
> }
>
> var_dump(constant('C::class'));
>
> ?>
> #v-
>
> ergibt bis einschließlich PHP 7.4 "NULL", ab PHP 8.0 offenbar (das
> habe ich nur mit 3v4l.org getestet) einen fatal error.
>
> Ist das ein Bug, ein Feature, oder halt einfach so passiert? Wieso
> darf ::class, das im Manual als "special constant" bezeichnet wird,
> nicht wie eine Konstante verwendet werden?

Was hättest du denn erwartet?

,----[ https://www.php.net/constant: ]
| 8.0.0 If the constant is not defined, constant() now throws an Error
| exception; previously an E_WARNING was generated, and null was returned.
`----

Vorher ging es nicht und lieferte NULL, nun mit PHP 8 geht es nicht und
gibt eine Exception

Stefan Froehlich

unread,
Jan 10, 2022, 6:12:29 PM1/10/22
to
On Mon, 10 Jan 2022 22:29:01 Karl Pflästerer wrote:
> Stefan...@Froehlich.Priv.at (Stefan Froehlich) writes:
>> Das folgende Codefragment:
>>
>> #v+
>> <?php
>>
>> class C {
>> const c = 'c';
>> }
>>
>> var_dump(constant('C::class'));
>>
>> ?>
>> #v-
>>
>> ergibt bis einschließlich PHP 7.4 "NULL", ab PHP 8.0 offenbar (das
>> habe ich nur mit 3v4l.org getestet) einen fatal error.
>>
>> Ist das ein Bug, ein Feature, oder halt einfach so passiert? Wieso
>> darf ::class, das im Manual als "special constant" bezeichnet wird,
>> nicht wie eine Konstante verwendet werden?
>
> Was hättest du denn erwartet?

Naja, das gleiche wie ohne die Verwendung von constant():

#v+
php > var_dump(C::class);
php shell code:1:
string(1) "C"
#v-

> ,----[ https://www.php.net/constant: ]
> | 8.0.0 If the constant is not defined, constant() now throws an Error
> | exception; previously an E_WARNING was generated, and null was returned.
> `----

> Vorher ging es nicht und lieferte NULL, nun mit PHP 8 geht es
> nicht und gibt eine Exception

Die Frage ist, ob man eine "special constant" als "nicht definiert"
betrachten sollte, nur weil sie "special" ist. Meiner Meinung ja
eher nicht.

Servus,
Stefan


--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - Warum sollte man das eigentlich ernst nehmen?
(Sloganizer)

Arno Welzel

unread,
Jan 11, 2022, 5:50:42 AM1/11/22
to
Stefan Froehlich:

> Das folgende Codefragment:
>
> #v+
> <?php
>
> class C {
> const c = 'c';
> }
>
> var_dump(constant('C::class'));
>
> ?>
> #v-
>
> ergibt bis einschließlich PHP 7.4 "NULL", ab PHP 8.0 offenbar (das
> habe ich nur mit 3v4l.org getestet) einen fatal error.
>
> Ist das ein Bug, ein Feature, oder halt einfach so passiert? Wieso
> darf ::class, das im Manual als "special constant" bezeichnet wird,
> nicht wie eine Konstante verwendet werden?

Nein, es ist ein Missverständnis deinerseits.

Mit dieser Anweisung wird versucht, den Inhalt einer Konstanten zu
ermittelt, die den Name "ABC" hat:

$valueOfABC = constant('ABC');

In der Praxis ist das exakt gleichbedeutend mit

$valueOfABC = ABC;

Nun gibt es einige "magische" Konstanten, die man nicht selber
definiert, sondern die PHP schon kennt:

<https://www.php.net/manual/en/language.constants.magic.php>

Dazu gehört dann u.A. eben auch <Klassename>::class, was aufgelöst wird
zu einem String, der den Namen einer Klasse repräsentiert.

Beispiel:

$className = C::class;

ist dann gleichbedeutend mit:

$className = 'C';

Da PHP zur Laufzeit aus C::class eben 'C' macht.

Oder wenn Du den die aktuelle Zeile im Code haben willst:

$currentLineOfCode = __LINE__;

Wenn diese Anweisung in Zeile 5 steht, würde zur Laufzeit umgewandelt in:

$currentLineOfCode = 5;

Was aber *nicht* geht, ist Konstanten als Teil eines String zu verwenden.

$currentLineOfCode = '__LINE__';

Das liefert eben nur den Text "__LINE__" und nicht den Wert 5, weil es
sich bei dem Ausdruck '__LINE__' um einen String handelt.

Wenn Du sowas machst:

var_dump(constant('C::class'));

Dann sucht PHP nach der Konstante mit den *exakten* Namen 'C::class' -
und die gibt es eben nicht.


--
Arno Welzel
https://arnowelzel.de

Stefan Froehlich

unread,
Jan 11, 2022, 8:41:25 AM1/11/22
to
On Tue, 11 Jan 2022 11:50:40 Arno Welzel wrote:
> Stefan Froehlich:
>> [var_dump(constant('C::class'))]

>> Ist das ein Bug, ein Feature, oder halt einfach so passiert?
>> Wieso darf ::class, das im Manual als "special constant"
>> bezeichnet wird, nicht wie eine Konstante verwendet werden?

> Nein, es ist ein Missverständnis deinerseits.

Offenbar, ja.

> Nun gibt es einige "magische" Konstanten, die man nicht selber
> definiert, sondern die PHP schon kennt:

> <https://www.php.net/manual/en/language.constants.magic.php>

> Da PHP zur Laufzeit aus C::class eben 'C' macht.
> Oder wenn Du den die aktuelle Zeile im Code haben willst:
> $currentLineOfCode = __LINE__;

> Was aber *nicht* geht, ist Konstanten als Teil eines String zu verwenden.

> $currentLineOfCode = '__LINE__';

> Das liefert eben nur den Text "__LINE__" und nicht den Wert 5,
> weil es sich bei dem Ausdruck '__LINE__' um einen String handelt.

Du gehst hier noch einen Schritt weiter:

Dass '__LINE__' einen String liefert ist klar, ebenso wie 'C::class'
ein String ist, aber auch der Namen jeder "echten" Konstante ein
String wäre. constant() verlangt einen String als Argument, bis
*hierher* wären '__LINE__' und 'C::class' also noch unproblematisch.

> Wenn Du sowas machst:
>
> var_dump(constant('C::class'));
>
> Dann sucht PHP nach der Konstante mit den *exakten* Namen
> 'C::class' - und die gibt es eben nicht.

...und genau da war meine Fehlannahme. Bei __LINE__ wäre ich gar
nicht erst auf die Idee gekommen, da das ja ganz offensichtlich
keine Konstante, sondern nur Magie sein kann. Auf der von Dir
verlinkten URL habe ich halt nicht gesucht, sondern auf:
<https://www.php.net/manual/en/function.constant.php>, und dort wird
man dann weiterverwiesen auf
<https://www.php.net/manual/en/language.oop5.constants.php>, wo
wiederum nach dem ersten Beispiel ::class erwähnt wird.

Aber ok, dann ist das halt so, wiewohl ärgerlich.

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Geht nicht!? Geht doch: Stefan.
(Sloganizer)

Karl Pflästerer

unread,
Jan 11, 2022, 10:40:38 AM1/11/22
to
Stefan...@Froehlich.Priv.at (Stefan Froehlich) writes:

>
> ...und genau da war meine Fehlannahme. Bei __LINE__ wäre ich gar
> nicht erst auf die Idee gekommen, da das ja ganz offensichtlich
> keine Konstante, sondern nur Magie sein kann. Auf der von Dir
> verlinkten URL habe ich halt nicht gesucht, sondern auf:
> <https://www.php.net/manual/en/function.constant.php>, und dort wird
> man dann weiterverwiesen auf
> <https://www.php.net/manual/en/language.oop5.constants.php>, wo
> wiederum nach dem ersten Beispiel ::class erwähnt wird.
>
> Aber ok, dann ist das halt so, wiewohl ärgerlich.

Wofür müsstest du denn Cls::class als Zeichenkette nutzen können
Ich nutze ::class genau um keine Klassennamen (inklusive namespace) als
String schreiben zu müssen (und weil die IDE dann die Klasse als
verwendet findet; ist praktisch wenn man Cls::class als Key in einem
Service Container nutzt)

Stefan Froehlich

unread,
Jan 11, 2022, 12:36:54 PM1/11/22
to
On Tue, 11 Jan 2022 16:40:36 Karl Pflästerer wrote:
> Stefan...@Froehlich.Priv.at (Stefan Froehlich) writes:
>> [constant('C::class') geht nicht]
>> Aber ok, dann ist das halt so, wiewohl ärgerlich.

> Wofür müsstest du denn Cls::class als Zeichenkette nutzen können
> Ich nutze ::class genau um keine Klassennamen (inklusive
> namespace) als String schreiben zu müssen

Dito, bzw. eigentlich vor allem für eine Validierung gegen
Schreibfehler (ich habe mir da ein AST-Modul gebastelt, das durch
die Quelltexte iteriert und alles auf Existenz prüft, was sich
prüfen lässt). Die Einführung von ::class war bei mir ein echter
game changer.

Es gibt genau eine Stelle im - von mir immer noch verwendeten -
Smarty, wo aus syntaktischen Gründen keine Konstanten stehen können.
Dort behelfe ich mir dann mit {'CONSTANT'|constant}, was definitiv
nur die zweitbeste Lösung ist, sich aber - wenn auch etwas halbgar -
immer noch automatisiert prüfen lässt. Dabei ist nun einmal ein
Klassenname aufgetaucht... und platsch.

So oft kommt's nicht vor, dass es ein Weltuntergang wäre, aber es
stört mich halt aus ästhetischen Gründen.

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Schmatzen auf den Brettern der Welt - Stefan, so ideal wie das Denken!
(Sloganizer)
0 new messages