PHP Landminen im Allgemeinen [closed]

Lesezeit: 6 Minuten

Benutzer-Avatar
David

Welche Überraschungen haben andere Leute beim Schreiben von PHP-Webanwendungen gefunden? Es gibt das bekannte und zu behebende Problem mit der Vererbung von Klassen zur Kompilierungszeit, aber ich kenne ein paar andere und wollte versuchen, eine Liste der wichtigsten Fallstricke der Sprache zu erstellen.

Notiz:

Ich habe mehrere Positionen als Sr. PHP5-Entwickler innegehabt, also zahlt sich die PHP-Arbeit für meine Rechnungen aus. Diese Frage soll nicht auf PHP als Sprache abzielen, da jede einzelne Sprache, mit der ich gearbeitet habe, einige bekannte oder weniger bekannte Überraschungen hat .

Benutzer-Avatar
CG.

Ich bin mir nicht sicher, ob das zählt, aber die Notwendigkeit, PHP-Skripte zu kompilieren, ist ein großes Leistungsproblem. In jedem ernsthaften PHP-Projekt benötigen Sie eine Art Compiler-Cache wie z APC, eBeschleuniger, PHP-Beschleunigeroder die (kommerzielle) Zend-Plattform.

  • Stimmen Sie dem definitiv zu, deshalb glaube ich, dass PHP jetzt APC als Teil seines Standardsatzes von Erweiterungen enthält.

    – David

    4. Februar 2009 um 16:37 Uhr

  • Ach ja, du hast Recht. Ich habe APC vergessen!

    – vgl.

    4. Februar 2009 um 16:40 Uhr

  • @David: Ich glaube nicht, dass es schon enthalten ist, aber es ist für die Aufnahme in PHP6 geplant.

    – Machtherr

    11. Februar 2009 um 19:50 Uhr

  • @R. Bemrose, das ist enttäuschend, wenn es wahr ist

    – David

    12. Februar 2009 um 2:59 Uhr

Benutzer-Avatar
zu viel php

Rekursive Referenzen verlieren Speicher

Wenn Sie zwei Objekte erstellen und sie in Eigenschaften voneinander speichern, wird der Garbage Collector sie niemals berühren:

$a = new stdClass;
$b = new stdClass;
$a->b = $b;
$b->a = $a;

Dies ist eigentlich ganz einfach, wenn eine große Klasse ein kleines Hilfsobjekt erstellt, das normalerweise die Hauptklasse speichert:

// GC will never clean up any instance of Big.
class Big {
  function __construct() {
    $this->helper = new LittleHelper($this);
  }
}
class LittleHelper {
  function __construct(Big $big) {
    $this->big = $big;
  }
}

Solange PHP auf kurze schnelle Seitenanfragen abzielt, wird dieses Problem wahrscheinlich nicht behoben. Das bedeutet, dass man sich bei Daemons oder anderen Anwendungen, die eine lange Lebensdauer haben, nicht auf PHP verlassen kann.

  • Circular Garbage Collector sollte in PHP 5.3 enthalten sein: ibm.com/developerworks/opensource/library/os-php-5.3new1/…

    – OIS

    22. April 2009 um 23:23 Uhr

  • Sie sollten dies ändern, um “Zirkuläre Referenzen” zu sagen, den gebräuchlichen Begriff.

    – erikkallen

    11. Februar 2010 um 12:03 Uhr

Benutzer-Avatar
David

require_once und include_once können bei übermäßiger Verwendung oft zu großen Leistungskillern führen. Wenn Sie eine Datei einschließen/erfordern, die eine Klasse enthält, kann ein Muster wie dieses einiges an Verarbeitungszeit sparen.

class_exists("myFoo") or require("myFoo.someClass.php");

Update: Dies ist immer noch ein Problem – http://www.techyouruniverse.com/software/php-performance-tip-require-versus-require_once

Update: Lesen Sie die ausgewählte Antwort auf die folgende Frage: Würde die Leistung beim automatischen Laden in PHP und bei der Suche nach der Klassendatei leiden? Wenn Sie in dieser Richtung implementiert werden, minimieren Sie so gut wie möglich die Strafen für file include/requires.

  • Wirklich? Das war mir nicht bewusst. Hat jemand den Unterschied zwischen require_once() und Ihrem Muster gemessen?

    – vgl.

    4. Februar 2009 um 16:43 Uhr

  • Ich finde das auch schwer zu glauben – class_exists wird eine Art Hash-Lookup beinhalten, ebenso wie require_once

    – Paul Dixon

    4. Februar 2009 um 16:44 Uhr

  • Automatisches Laden (de.php.net/autoload) ist eine sauberere und flexiblere Problemumgehung dafür.

    – Rauben

    4. Februar 2009 um 16:46 Uhr

  • @CG & @Paul techyouruniverse.com/software/…. – Lesen Sie die Kommentare dazu, da es einige Teilkorrekturen für das Leistungsproblem gibt, bei denen der Statistik-Cache für Dateisuchen erhöht wird.

    – David

    4. Februar 2009 um 16:50 Uhr

  • Interessant! Obwohl ich selbst das automatische Laden verwende 🙂

    – Paul Dixon

    4. Februar 2009 um 16:59 Uhr

Benutzer-Avatar
Richard Levasseur

Eine lustige Landmine: Globale Variablen können sich auswirken $_SESSION Wenn register_globals ist an. Aber ich denke, das passiert, wenn register_globals, eine Landmine selbst, eingeschaltet wird.

NULL und der “0”-String sind in Php das reinste Übel

if ("0" == false) //true
if ("0" == NULL)  //true
if ("0" == "NULL")//true

  • Das zweite Beispiel erscheint mir faul: Null im Vergleich zu ALLEM ist Null. Es ist die Wertlosigkeit, dagegen kann man keinen Gleichheitsvergleich anstellen.

    – Shane H

    5. Februar 2009 um 4:26 Uhr

  • Das Problem ist, dass NULL in eine Zeichenfolge “0” konvertiert wird … warum, keine Ahnung, aber es steht in den Spezifikationen …

    – Robert Gould

    5. Februar 2009 um 5:36 Uhr

  • Deshalb sollten Sie den strengen Vergleich verwenden (===)

    – Jan Hancic

    5. Februar 2009 um 10:37 Uhr

  • auf jeden Fall, aber wenn Sie gerade erst anfangen und besonders wenn Sie von Sprachen ohne === kommen, sagen wir C oder C++, ist das wirklich frustrierend

    – Robert Gould

    5. Februar 2009 um 10:57 Uhr

  • +1 stimme definitiv zu, dass dies eine Überraschung für Programmierer sein kann, die ins Skriptland ziehen 🙂

    – David

    5. Februar 2009 um 22:32 Uhr

Benutzer-Avatar
Pim Jäger

  • foreach() kopiert das Array stillschweigend im Hintergrund und iteriert durch diese Kopie. Wenn Sie ein großes Array haben, wird dies die Leistung beeinträchtigen. In diesen Fällen die by-reference-Optionen von foreach(), die neu in php5 sind oder eine for()-Schleife verwenden.

  • Achten Sie auf Gleichheit (==) vs. Identität (===).

  • Achten Sie darauf, was empty() und was isset() ausmacht.


Mehr Landminen jetzt, wo ich etwas mehr Zeit habe:

  • Floats nicht auf Gleichheit vergleichen. PHP ist nicht Matlab und es ist einfach nicht für präzise Fließkommaarithmetik ausgelegt. Probier diese:
if (0.1 + 0.2 == 0.3)
  echo "equal";
else
  echo "nope"; // <-- ding ding
  • Vergessen Sie auch nicht Ihre Oktale! Ein int mit führender Null wird als Oktal gecastet.
if (0111 == 111)
  echo "equal";
else
  echo "nope"; // <-- ding ding

  • Das zweite Beispiel erscheint mir faul: Null im Vergleich zu ALLEM ist Null. Es ist die Wertlosigkeit, dagegen kann man keinen Gleichheitsvergleich anstellen.

    – Shane H

    5. Februar 2009 um 4:26 Uhr

  • Das Problem ist, dass NULL in eine Zeichenfolge “0” konvertiert wird … warum, keine Ahnung, aber es steht in den Spezifikationen …

    – Robert Gould

    5. Februar 2009 um 5:36 Uhr

  • Deshalb sollten Sie den strengen Vergleich verwenden (===)

    – Jan Hancic

    5. Februar 2009 um 10:37 Uhr

  • auf jeden Fall, aber wenn Sie gerade erst anfangen und besonders wenn Sie von Sprachen ohne === kommen, sagen wir C oder C++, ist das wirklich frustrierend

    – Robert Gould

    5. Februar 2009 um 10:57 Uhr

  • +1 stimme definitiv zu, dass dies eine Überraschung für Programmierer sein kann, die ins Skriptland ziehen 🙂

    – David

    5. Februar 2009 um 22:32 Uhr

Benutzer-Avatar
David

Es war im Nachhinein irgendwie offensichtlich, aber ein bekannter Fallstrick hat mit Umfang und Referenzen zu tun, wenn er in foreach verwendet wird.

foreach($myArray as &$element){
   //do something to the element here... maybe trim or something more complicated
}
//Multiple lines or immediately after the loop

$element = $foobar;

Die letzte Zelle in Ihrem Array ist jetzt zu $foobar geworden, da sich die Referenz in foreach oben immer noch im aktuellen Kontextbereich befindet.

  • PHP hat keinen Blockbereich, nur Funktions-/Klassen-/globalen Bereich.

    – Gumbo

    4. Februar 2009 um 16:38 Uhr

  • Zugegeben, aber das ist kein Leistungsproblem, oder? Vielleicht sollten Sie Ihre Frage bearbeiten, um andere Fallstricke aufzunehmen?

    – vgl.

    4. Februar 2009 um 16:46 Uhr

  • Der Verweis auf foreach() ist mehr Mühe als es wert ist, holen Sie sich einfach gleichzeitig den Array-Schlüssel und aktualisieren Sie das Array manuell.

    – zu viel php

    5. Februar 2009 um 4:00 Uhr

  • Eine gängige Praxis ist immer unset($element); unmittelbar nach dem Iterieren eines Arrays per Referenz. Dann sind Sie später auf der Seite sicher. Ich habe es sogar in derselben Zeile wie die schließende Klammer gesehen.

    – Philfreo

    26. Juni 2010 um 22:19 Uhr


1215650cookie-checkPHP Landminen im Allgemeinen [closed]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy