Einfaches Problem mit explode()

  • PHP

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von DerDomi.

    Einfaches Problem mit explode()

    Hallo Community,
    ich habe kein anspruchsvolles Problem, aber ich bin noch nicht sonderlich gut in PHP und finde einen Fehler in einem Codeausschnitt nicht :(

    In dem Benutzerprotokoll "Clients.log" steht, wann ein Benutzer das letzte mal angemeldet war. Die Liste liegt wie folgt vor:

    HTML-Quellcode

    1. Josef: 07.02.12 / 15:12:16
    2. Franz: 15.03.12 / 12:17:44
    3. Klaus: 27.01.12 / 20:18:11


    Wenn sich ein Benutzer verbindet, soll der folgende Code das Datum hinter dem entsprechenden Benutzer aktualisieren.

    PHP-Quellcode

    1. <?php
    2. $invoegen = $_POST['Username'] . ": " . date("d-m-y / H:i:s") . "<br>";
    3. $fopen = fopen("Clients.log", "w+");
    4. $contents = fread($fopen, filesize("Clients.log"));
    5. $users = explode("\n", $contents);
    6. $max = sizeof($users);
    7. for ($i=0; $i<$max; $i++) {
    8. $currentClient = expode(":",$users[$i]);
    9. if ($_POST['Username'] != &currentClient) {
    10. &data += $users[$i] . "\n";
    11. }
    12. if ($_POST['Username'] == &currentClient) {
    13. &data += $invoegen . "\n";
    14. }
    15. }
    16. fwrite($fopen, $data);
    17. fclose($fopen);
    18. ?>


    Es passiert jedoch nichts und ich kann den Fehler nicht finden.

    Danke im Voraus!
    DerDomi
    Konfiguriere den Interpreter über die php.ini so, dass er dir alle Fehler anzeigt.

    php.net/manual/de/function.error-reporting.php
    php.net/manual/de/errorfunc.co…on.php#ini.display-errors
    „Was daraus gefolgert werden kann ist, dass jeder intelligentere User sein Geld lieber für Bier ausgibt, um einen schönen Rausch zu haben, und nicht dieses Ranzprodukt.“

    -Auszug aus einer Unterhaltung über das iPhone und dessen Vermarktung.
    Hi,

    hui, da ist so manches im Argen.

    Zuerst mal Datei auslesen, kannst einfacher machen wenn du einfach schreibst

    PHP-Quellcode

    1. <?php $inhalt = file_get_contents('./Clients.log'); ?>


    Aber nur als Tipp, geht natürlich auch so.

    Nächstes: expode gibt es nicht, hast das "l" vergessen. -> expLode

    Weiter: Wieso steht da &data? Vermutlich hast das mit dem $ verwechselt. Also: &data -> $data.
    Gibt höchstens &$variable, aber das nur für z.B. Methoden, und auch nur, wenn du Argumente per Referenz übergeben willst. Ist hier aber ja nicht der Fall. Achja, und "&currentClient" soll vermutlich auch "$currentClient" heißen.

    Außerdem (in der selben Zeile wie &data) versuchst du offenbar, mit "+" Strings zu verketten. Kann nicht hinhauen, nur für numerische Werte. Bitte Zeichenketten (Strings, also Text) mit dem Punkt (.) verketten.


    Weitere mögliche Ursachen:
    Sicher, dass deine Datei "Clients.log" heißt? Könnte auch (bitte prüfen) "Clients.log.txt" sein. Oder du vertust dich mit Groß- / Kleinschreibung, dass es vielleicht "clients.log" ist.
    Hinweis: auch darauf achten, dass das was via GET oder POST übergeben wird ebenfalls case sensitive ist, das heißt auch hier ist Groß- und Kleinschreibung zu beachten. Und (auch ein beliebter Fehler) sicherstellen, dass das Zeugs was du abfragst auch wirklich via POST übergeben wurde, und nicht mit GET.

    Bitte ganz am Anfang deines Skripts so schreiben (also nach <?php in der Zeile drunter):

    PHP-Quellcode

    1. <?php
    2. $debug = true;
    3. if($debug){
    4. @error_reporting(E_ALL);
    5. @ini_set('display_errors', 1);
    6. }
    7. ?>


    Um Fehler nicht mehr auszugeben reicht es, $debug auf false zu setzen.


    Link :thumbup:
    Hello World
    Wow da warn ja ganz schön viele Leichtsinnsfehler drin!
    Danke an alle die geholfen haben, besonders an


    Link275
    !

    Ich versuche gegen Nachmittag den Code so anzupassen, dass er tut was er auch soll.
    Wenn Probleme auftreten oder wenn alles funktioniert meld ich mich wieder :thumbup:

    DerDomi
    Da hier in VB Forum ist, nehme ich ma an das du auch VB kannst, nutze statt explode() lieber str_split() oder preg_split() ist verständlicher als explode() macht aber das selbe. Genau andersrum join() statt implode().
    Und count() statt sizeof() *g*
    @Dodo:
    str_split ist in dem Fall wohl überhaupt nicht brauchbar und preg_split verwendet Regexs, was in diesem Fall nicht nötig ist.
    explode ist hier vollkommen richtig. (Auch wenn bei der zweiten Verwendung noch der $limit-Parameter fehlt.)

    join ist ein Alias für implode und sizeof einer für count.
    Richtiger wäre daher eigentlich die Empfehlung von implode und count.
    3daycliff: du wirst es nicht glauben, aber das weiß ich ;)

    Allerdings sind split(), join() und count() Funktionen sind die in etlichen anderen Programmiersprachen genauso heißen und gerade wenn man mehrere Sprachen beherscht ist es einfacherer und verständlicher wenn man damit Programmiert.

    Btw: Wieso sollte str_split() überhaupt nicht Brauchbar sein? Macht, wie du selbst sagst, das selbe wie explode()?
    Ich habe hier den funktionierenden Code: :D

    PHP-Quellcode

    1. <?php
    2. $debug = false;
    3. if($debug){
    4. @error_reporting(E_ALL);
    5. @ini_set('display_errors', 1);
    6. }
    7. if ($_POST['Username'] == '') {
    8. exit();
    9. }
    10. $invoegen = $_POST['Username'] . ": " . date("d-m-y / H:i:s");
    11. $contents = file_get_contents('./Clients.log');
    12. $users = explode("\r\n", $contents);
    13. $max = sizeof($users);
    14. for ($i=0; $i<$max; $i++) {
    15. $currentClient = explode(":",$users[$i]);
    16. if ($_POST['Username'] != $currentClient[0]) {
    17. $data = $data . $users[$i] . "\r\n";
    18. }
    19. if ($_POST['Username'] == $currentClient[0]) {
    20. $data = $data . $invoegen . "\r\n";
    21. }
    22. }
    23. $fopen = fopen("Clients.log", "w");
    24. fwrite($fopen, $data);
    25. fclose($fopen);
    26. ?>


    Wenn ihr noch Verbesserungsvorschläge habt, oder weiter diskutieren wollt, habe ich ein offennes Ohr!

    Lg,
    DerDomi

    @Dodo: Wenn ich das richtig gelesen habe, trennt str_split() nach einer bestimmten Anzahl an Zeichen, nicht nach Delimiter.
    Btw: Wieso sollte str_split() überhaupt nicht Brauchbar sein? Macht, wie du selbst sagst, das selbe wie explode()?
    Und das habe ich bitte wo geschrieben?
    str_split zerlegt einen string in substrings mit fester Länge. explode zerlegt einen string in substrings unterschiedlicher Länge anhand eines Trennzeichen.

    [...] etlichen anderen Programmiersprachen genauso heißen und gerade wenn man mehrere Sprachen beherscht ist es einfacherer und verständlicher wenn man damit Programmiert.
    Man sollte aber nicht zwanghaft versuchen, Programmiersprachen auf einen Nenner zu bringen. Jeder Sprache liegt ein anderes Design zugrunde und selbst wenn mal etwas ähnlich heißt, bedeutet das ja noch nicht, dass der Aufruf oder das Ergebnis ähnlich ist:
    In C ist sizeof ein Operator und bestimmt die Größe eines Datentyps in bytes. In PHP ist es eine Funktion, welche die Anzahl der Elemente eines Arrays bestimmt.
    In python schreibt man ' '.join(['foo', 'bar']), in javascript ['foo', 'bar'].join(' '), in C# string.Join(" ", "foo", "bar"), matlab verwendet strjoin({'foo', 'bar'}, ' '), ...
    .NET akzeptiert bei String.Split beliebig viele Trennzeichen. Java genau einen Regex, wie PHP. Python erwartet einen string.

    Man sollte immer das Werkzeug nehmen, was am besten geeignet ist. Und in dem Fall ist das nun mal explode, was man als "PHP-Programmierer" auch kennen sollte.

    Btw. split ist seit PHP 5.3 deprecated.

    @On-Topic / @DerDomi:
    ein paar Vorschläge:
    - wenn du file_get_contents verwendest, kannst du zum schreiben auch file_put_contents verwenden
    - statt sizeof besser count verwenden oder gleich eine foreach-Schleife
    - $data vor der Schleife initialisieren, also $data = '';
    - explode(":",$users[$i]); durch explode(":", $users[$i], 2); ersetzen
    - if-Abfrage etwas vereinfachen:

    PHP-Quellcode

    1. if($_POST['Username'] != $currentClient[0]) {
    2. $data .= $users[$i]."\r\n";
    3. }
    4. else {
    5. $data .= $invoegen."\r\n";
    6. }

    - kein @ in Zeile 4 und 5
    - wenn du PHP vor 5.4 verwendest, ersetze E_ALL durch -1
    - statt einer Textdatei verwende eine Datenbank
    - damit dir niemand deine Datei zerhaut, solltest du verhindern, das ein Doppelpunkt oder Zeilenumbruch im Namen stehen
    @3daycliff:
    Und das habe ich bitte wo geschrieben

    Na hier

    Btw. split ist seit PHP 5.3 deprecated

    Verwendet ja niemand hier.


    @DerDomi:
    Nicht zu vergessen die for-Schleife. Die extra Variable $max kannst dir sparen, wenn du anstatt $i<$max schreibt $i < count($users). Wesentlich eleganter wäre an dieser Stelle natürlich die Verwendung von foreach:

    PHP-Quellcode

    1. foreach($users as $key => $value){
    2. // Dein Code und Zeugs ..........
    3. }

    Falls du den $key überhaupt brauchst, sieht aber nicht so aus ;)
    Und anstatt $currentClient[0] nimmst dann $value als Vergleich (oder $users[$key], aber das is ja eher überflüssig).

    preg_split verwendet Regexs, was in diesem Fall nicht nötig ist

    Ne, nötig isses eigentlich ned. Aber allein auf Flexibilitätsgründen verwende ich persönlich auch oft preg_split lieber als explode.

    Stutzig macht mich, dass nirgends abgefragt wird, ob $users vielleicht leer ist, z.B. weil keine Delimiter gefunden wurde oder einfach die Clients.log leer ist. Das sollte vorab unbedingt geprüft werden.

    Außerdem: $_POST wird auch ned geprüft. Was aber schon gemacht werden sollte. Zeichen die nicht enthalten sein dürfen müssen raus und dann noch vorsorgen, dass kein Fremd-Code ausgeführt werden kann.


    Link :thumbup:
    Hello World

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Link275“ ()

    Aufmerksam lesen könnte helfen...

    Ich schrieb das str_split in dem Fall absolut fehl am Platz ist. Nicht dass es das gleiche macht wie explode.

    Verwendet ja niemand hier.
    Habe ich auch nicht behauptet, allerdings legt Dodo nahe, diese zu verwenden ("Allerdings sind split() [...] ist es einfacherer und verständlicher wenn man damit Programmiert.").


    Und eine teure Funktion allein deshalb zu benutzen, weil man meint, flexibler zu sein, ist ehrlich gesagt schwachsinnig. Du verlängerst damit nicht nur die Ausführungszeit, sondern verringerst auch die Lesbarkeit.

    Sorry @all für den Off-Topic.
    Und eine teure Funktion allein deshalb zu benutzen, weil man meint, flexibler zu sein, ist ehrlich gesagt schwachsinnig. Du verlängerst damit nicht nur die Ausführungszeit, sondern verringerst auch die Lesbarkeit.


    Du ich schreibe meine Skripte wie's mir passt und wenn ich preg_split benötige dann verwende ich das auch. Außerdem ist die Flexibilität nicht nur (m)eine Meinung sondern eine Tatsache. Sag mir mal bitte, wie splittest du bei jedem "|"-Zeichen unter der Bedingung, dass vor dem "|"-Zeichen kein "x" oder "y" stehen darf? Bevor du dir jetzt peinliche Texte aus den Fingern ziehst, sieh doch ein dass es für die Funktion durchaus sinnvolle Anwendungsgebiete gibt. Und wenn wir schon kleinlich sind: mit Lesbarkeit hat das absolut nichts zu tun. Ausführungszeit ist zwar richtig, aber dennoch kleinlich, denn ich hab bereits geschrieben, dass die Verwendung von preg_split in diesem Fall nicht nötig ist (von wegen aufmerksam lesen ;) ).

    Dein überhebliches Getue geht mir ehrlich gesagt auf die Nerven. Ich mein damit nicht deine Antworten an den TE, sondern deine Kleinlichkeit und dieses offensichtliche ich-muss-Fehler-bei-anderen-suchen.

    @DerDomi: preg_split brauchst du (wie beschrieben) nicht, explode ist für deine Zwecke mehr als ausreichend.


    Link :thumbup:
    Hello World
    Ich habe den Code gemäß den Vorschlägen verbessert.
    Verbotene Zeichen habe ich auf folgende Weise realisiert:

    PHP-Quellcode

    1. if (strpos($_POST['Username'], ':')!= false) {
    2. exit();
    3. }
    4. if (strpos($_POST['Username'], '\r\n')!= false) {
    5. exit();
    6. }


    Aber wie verhindere ich die Einführung von Fremdcode?

    DerDomi
    Hi,

    Ein exit würde ich deswegen nicht gleich machen, eine Meldung dass unerlaubte Zeichen enthalten sein reicht, inkl. Ein Link um zur Seite zurück zu kehren und die Eingaben erneut vorzunehmen.

    Stichwort htmlspecialchars, htmlentities und ENT_QUOTES. Unabdingbar au jeden Fall, wenn du Usereingaben ausgibst.


    Link :thumbup:
    Hello World
    Das ist ja relativ simpel, wenn ich es richtig verstanden habe:

    PHP-Quellcode

    1. $acUsername = htmlentities($_POST['Username'], ENT_QUOTES);

    Wenn ich das am Anfang setze und im nachfolgenden Code $_POST['Username'] durch $acUsername ersetzte, werden die Sonderzeichen umgewandelt.

    DerDomi