nach einiger Verwirrung in den Kommentaren dazu
- Ist es sicher, Klassennamen mit einem Buchstaben in PHP zu haben, z. B. A, B, C
Ich dachte, ich mache eine Frage. Laut dem PHP-Handbuch sollte ein gültiger Klassenname mit übereinstimmen [a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*
. Aber anscheinend wird dies nicht erzwungen, noch gilt es für irgendetwas anderes:
define('π', pi());
var_dump(π);
class ␀ {
private $␀ = TRUE;
public function ␀()
{
return $this->␀;
}
}
$␀ = new ␀;
var_dump($␀ );
var_dump($␀->␀());
funktioniert gut (obwohl meine IDE kein ␀ anzeigen kann). Kann mir das irgendein gelehrter Mensch erklären? Können wir Unicode verwenden? Und wenn ja, seit wann? Nicht, dass ich das eigentlich tun würde wollen alles andere als verwenden A-Za-z_
aber ich bin neugierig.
Klärung: Ich bin nicht hinter einem Regex her, um Klassennamen zu validieren, und ich weiß auch nicht, ob PHP intern den im Handbuch vorgeschlagenen Regex verwendet. Das, was mich (und anscheinend die anderen Jungs in der verknüpften Frage) verwirrt hat, ist, warum Dinge wie $☂ = 1
kann überhaupt in PHP verwendet werden. PHP6 sollte die Unicode-Version sein, aber PHP6 befindet sich in einer Pause. Aber wenn es keine Unicode-Unterstützung gibt, warum kann ich das dann tun?
Diese Frage beginnt mit der Erwähnung von Klassennamen im Titel, fährt dann aber mit einem Beispiel fort, das exotische Namen für Methoden, Konstanten, Variablen und Felder enthält. Dafür gibt es tatsächlich unterschiedliche Regeln. Beginnen wir mit den Groß- und Kleinschreibung.
Bezeichner ohne Berücksichtigung der Groß-/Kleinschreibung (Klassen- und Funktions-/Methodennamen)
Die allgemeine Richtlinie hier wäre, nur druckbare ASCII-Zeichen zu verwenden. Der Grund dafür ist, dass diese Bezeichner auf ihre Kleinbuchstabenversion normalisiert sind, diese Konvertierung jedoch vom Gebietsschema abhängig ist. Betrachten Sie die folgende PHP-Datei, die in ISO-8859-1 codiert ist:
<?php
function func_á() { echo "worked"; }
func_Á();
Wird dieses Skript funktionieren? Könnte sein. Es kommt darauf an, was tolower
(
193
)
wird zurückgegeben, was vom Gebietsschema abhängig ist:
$ LANG=en_US.iso88591 php a.php
worked
$ LANG=en_US.utf8 php a.php
Fatal error: Call to undefined function func_Á() in /home/glopes/a.php on line 3
Daher ist es keine gute Idee, Nicht-ASCII-Zeichen zu verwenden. Allerdings können sogar ASCII-Zeichen in einigen Gebietsschemas Probleme bereiten. Sehen diese Diskussion. Es ist wahrscheinlich, dass dies in Zukunft behoben wird, indem eine vom Gebietsschema unabhängige Kleinschreibung vorgenommen wird, die nur mit ASCII-Zeichen funktioniert.
Zusammenfassend lässt sich sagen, dass wir nach Ärger suchen, wenn wir Multi-Byte-Codierungen für diese Kennungen verwenden, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird. Es ist nicht nur so, dass wir die Groß-/Kleinschreibung nicht ausnutzen können. Wir könnten tatsächlich auf unerwartete Kollisionen stoßen, da alle Bytes, aus denen ein Multibyte-Zeichen besteht, mithilfe von Gebietsschemaregeln einzeln in Kleinbuchstaben umgewandelt werden. Es ist möglich, dass zwei verschiedene Multibyte-Zeichen derselben modifizierten Bytestream-Darstellung zugeordnet werden, nachdem die Kleinbuchstabenregeln des Gebietsschemas auf jedes der Bytes angewendet wurden.
Groß-/Kleinschreibung beachtende Bezeichner (Variablen, Konstanten, Felder)
Das Problem ist hier weniger schwerwiegend, da bei diesen Bezeichnern zwischen Groß- und Kleinschreibung unterschieden wird. Sie werden jedoch nur als Bytestreams interpretiert. Das heißt, wenn wir Unicode verwenden, müssen wir konsequent dieselbe Byte-Darstellung verwenden; wir können UTF-8 und UTF-16 nicht mischen; wir können auch keine Stücklisten verwenden.
Tatsächlich müssen wir uns an UTF-8 halten. Außerhalb des ASCII-Bereichs verwendet UTF-8 Lead-Bytes von 0xc0 bis 0xfd und die Trail-Bytes liegen im Bereich von 0x80 bis 0xbf, die im zulässigen Bereich laut Handbuch liegen. Nehmen wir nun an, wir verwenden das Zeichen „Ġ“ in einer UTF-16BE-codierten Datei. Dies wird zu 0x01 0x20 übersetzt, sodass das zweite Byte als Leerzeichen interpretiert wird.
Dass Multi-Byte-Zeichen so gelesen werden, als wären sie Single-Byte-Zeichen, ist natürlich überhaupt keine Unicode-Unterstützung. PHP hat etwas Multibyte-Unterstützung in Form des Kompilierungsschalters “–enable-zend-multibyte” (ab PHP 5.4 ist die Multibyte-Unterstützung standardmäßig einkompiliert, aber deaktiviert; Sie können sie mit aktivieren zend.multibyte=On
in php.ini). Dies ermöglicht Ihnen erklären die Kodierung des Skripts:
<?php
declare(encoding='ISO-8859-1');
// code here
?>
Es verarbeitet auch Stücklisten, die zur automatischen Erkennung der Codierung verwendet werden und nicht Teil der Ausgabe werden. Es gibt jedoch ein paar Nachteile:
- Performance-Hit, sowohl Speicher als auch CPU. Es speichert eine Darstellung des Skripts in einer internen Multi-Byte-Codierung, die mehr Platz benötigt (und es scheint auch die Originalversion im Speicher zu speichern) und es verbraucht auch etwas CPU, um die Codierung zu konvertieren.
- Multi-Byte-Unterstützung ist normalerweise nicht einkompiliert, daher weniger getestet (mehr Fehler).
- Portabilitätsprobleme zwischen Installationen, die die Unterstützung einkompiliert haben, und solchen, die dies nicht tun.
- Bezieht sich nur auf die Parsing-Phase; löst nicht das beschriebene Problem für Bezeichner ohne Berücksichtigung der Groß-/Kleinschreibung.
Schließlich gibt es noch das Problem der fehlenden Normalisierung – dasselbe Zeichen kann mit unterschiedlichen Unicode-Codepunkten dargestellt werden (unabhängig von der Kodierung). Dies kann zu einigen sehr schwer zu verfolgenden Fehlern führen.
Ihr Zeichen ist kodiert als 0x80 0x90 0xe2
oder so ähnlich, also stimmt es mit Ihrem Regexp überein, wenn Sie den Unicode nicht interpretieren (Arbeiten mit einzelnen Bytes).
Von die offizielle Dokumentation:
Der Klassenname kann ein beliebiges gültiges Label sein, vorausgesetzt, es ist kein von PHP reserviertes Wort. Ein gültiger Klassenname beginnt mit einem Buchstaben oder Unterstrich, gefolgt von einer beliebigen Anzahl von Buchstaben, Zahlen oder Unterstrichen. Als regulärer Ausdruck würde es so ausgedrückt werden: ^[a-zA-Z_x80-xff][a-zA-Z0-9_x80-xff]*$
.
Nach meinem Verständnis haben die aktuellen Versionen von PHP etwas Unicode-Unterstützung, aber es ist inkonsistent. Wie andere vorgeschlagen haben, sollte dies in PHP6 angegangen werden, das abgesagt (nicht verschoben) wurde. Am Ende des Tages werden einige “exotische” Charaktere funktionieren und andere nicht; und offensichtlich ist es besser, wie Sie vorgeschlagen haben, dabei zu bleiben A-Za-z0-9_
.
Gleichzeitig habe ich Gerüchte gehört, dass die Unicode-Diskussion kürzlich neu gestartet wurde, vermutlich von Grund auf neu, da der ursprüngliche Vorschlag für UTF-16 in PHP6 eine Menge Aufwand mit sehr geringem Ertrag erforderte.
Randnotiz: Nach dem, was ich gelesen habe, wird die nächste große PHP-Version PHP 5.4 sein, die horizontale Integration (Traits), Array-Kurzschrift, integrierten HTTP-Server und einige andere dringend benötigte Funktionen enthalten könnte.
http://www.mail-archive.com/[email protected]/msg35720.html
.
Ich glaube nicht, dass Sie Unicode bis PHP6 vollständig verwenden können … aber es könnte eine Art teilweise Unterstützung in 5.3 geben … Ich habe es nie selbst versucht und verfolge es auch nicht genau 🙂
– prodigitalson
5. August 10 um 17:03 Uhr
sehen Protokoll des PHP-Entwicklertreffens
– bcosca
5. August 10 um 17:10 Uhr
Zeigt die Regex x7f an, dass Byte Wert 0x7f?
– Paul Nathan
5. August 10 um 21:17 Uhr