Beiträge von SinnlosS

    Switch bietet zudem dank 'default:' den Vorteil Programmlogik die in verschiedenen cases - aber nicht in allen - vorkommt zusammenzufassen, indem man bei diesen cases auf das 'break;' verzichtet. Bei einem if-elseif-Konstrukt musst du eine weitere if-Abfrage bemühen, den wiederkehrenden Code in allen entsprechenden Fällen wiederholen, oder in eine Funktion auslagern.
    Kommt jetzt nicht so häufig vor, ich fand es aber das ein oder andere Mal schon durchaus praktisch.

    Dass switch da jetzt schneller ist als ein if-elseif-Konstrukt wage ich grad auch zu bezweifeln, werde ich aber bei Gelegenheit mal aus Neugier testen.

    Ich finde aber eine Switch-Anweisung übersichtlicher als ein ellenlanges if-elseif-Konstrukt. Daher bevorzuge ich im Zweifelsfall immer switch.

    Ist zwar nur eine Kleinigkeit und wirkt sich nicht auf die Funktionalität aus, aber du kannst das ganze performanter gestalten, wenn du die ganzen if-Abfragen zu einem if-elseif-Konstrukt zusammenfasst.
    Dafür brauchst du nur die Reihenfolge der Abfragen umdrehen, dann werden nicht in jedem Schleifendurchlauf alle Bedingungen geprüft, sondern nur bis eine erfüllt wird. Bei jedem Diamant-Member sparst du damit drei Überprüfungen, bei jedem Platinum-Member zwei und bei jedem Gold-Member eine.

    PHP
    if($row['turnierspiele']>349) $status = "<img src=\"grafik/diamand.gif\" border=\"0\" alt=\"".$row['nick']." ist diamand Spieler, dazu kommt man ab 350 Turnierteilnahmen\">";
    elseif($row['turnierspiele']>249) $status = "<img src=\"grafik/platinum.gif\" border=\"0\" alt=\"".$row['nick']." ist Platinum Spieler, dazu kommt man ab 250 Turnierteilnahmen\">";
    elseif($row['turnierspiele']>149) $status = "<img src=\"grafik/gold.gif\" border=\"0\" alt=\"".$row['nick']." ist Gold Spieler, dazu kommt man ab 150 Turnierteilnahmen\">";
    elseif($row['turnierspiele']>49) $status = "<img src=\"grafik/vip.gif\" border=\"0\" alt=\"".$row['nick']." ist Vip Spieler, dazu kommt man ab 50 Turnierteilnahmen\">";

    Ist jetzt nichts allzu gravierendes, aber Kleinvieh macht ja bekanntlich auch Mist. :)

    Da ich gerade etwas Zeit hatte, mal noch eine Beschreibung der Klasse. Die restlichen Methoden folgen noch.

    Konstanten
    In den Konstanten werden einige Einstellungen für Registrierung und Login festgelegt. Im Einzelnen sind dies:

    const activationExpires
    Hier wird die Anzahl der Tage festgelegt, nach denen ein Aktivierungscode ungültig wird. Wird nur benötigt wenn registrierte User nicht direkt nach der Registrierung freigeschaltet werden, sondern ihre Email-Adresse durch einen Aktivierungslink der ihnen zugeschickt wird verifizieren müssen.
    Kann beliebig festgelegt werden, Default-Wert ist 14.

    const IP_maxLoginTries
    Hier wird die maximale Anzahl fehlgeschlagener Logins festgelegt, nach denen die Anmeldung von dieser IP aus für einen bestimmten Zeitraum gesperrt wird.
    Kann beliebig festgelegt werden, Default-Wert ist 5.

    const IP_blockDuration
    Hier wird die Dauer in Minuten festgelegt, für die eine IP-Adresse gesperrt wird, nachdem sie eine bestimmte Anzahl fehlgeschlagener Login-Versuche hatte (festgelegt in const IP_maxLoginTries).
    Kann beliebig festgelegt werden, Default-Wert ist 15.


    Eigenschaften
    private $db
    Selbsterklärend (hoffentlich). Hier wird das Datenbank-Objekt abgelegt.

    private $cache
    In diesem Array werden User-Daten gecached um sie bei mehrmaliger Abfrage nicht jedesmal aufs neue aus der Datenbank holen zu müssen. Weiteres siehe bei der Beschreibung der Eigenschaft $fields und den Beschreibungen der magischen Methoden __set und __get.

    private $fields
    In diesem Array werden die Spaltennamen der User-Tabelle abgelegt, deren Werte für den aktuellen User aus der Datenbank gelesen und in der Datenbank geupdated werden dürfen. Für weiteres siehe die Beschreibungen der magischen Methoden __set und __get.
    Kann beliebig um weitere Felder der eigenen User-Tabelle erweitert werden.

    private $id
    Hier wird die ID des Users abgelegt.


    Magische Methoden
    Für diejenigen die den Begriff magische Methoden nicht kennen: Damit werden Methoden bezeichnet, die nicht explizit aufgerufen werden, sondern automatisch beim Eintreten gewisser Umstände. Ein Beispiel ist der Konstruktor einer Klasse, die magische Methode __construct. Diese wird automatisch aufgerufen, wenn via new ein neues Objekt einer Klasse erzeugt wird. Weiterhin verwendet werden von mir __get und __set.
    __get wird automatisch aufgerufen, wenn lesend auf eine Objekt-Eigenschaft zugegriffen wird, die nicht gesetzt ist.
    __set wird automatisch aufgerufen, wenn schreibend auf eine Objekt-Eigenschaft zugegriffen wird, die nicht gesetzt ist.

    __get


    Wird lesend auf eine Eigenschaft eines User-Objektes zugegriffen die nicht gesetzt ist, so wird überprüft ob diese Eigenschaft in den als verfügbar festgelegten Feldern des Arrays $fields enthalten ist. Wenn dem so ist wird überprüft, ob der Wert dieser Eigenschaft bereits im Array $cache abgelegt ist. Falls nicht, wird das Feld aus der Datenbank ausgelesen und im Array $cache abgelegt. Anschließend wird der entsprechende Wert zurückgegeben.
    Beispiel:

    PHP
    <?php
    // ...code blabla code...
    $user = new User($db,$user_id);
    echo $user->name;
    ?>


    name ist keine gesetzte Eigenschaft in dem User-Objekt, also wird auf die magische Methode __get zugegriffen. Diese sieht, dass "name" durch den Array fields zugelassen (=enthalten) ist, liest das entsprechende Feld aus der Datenbank, schreibt es in den Array cache und gibt den Wert zurück. Beim nächsten Zugriff auf $user->name wird in diesem Scriptdurchlauf nicht mehr die Datenbank abgefragt, sondern auf den Wert aus dem Array cache zurückgegriffen.

    __set


    Wird schreibend auf eine Eigenschaft eines User-Objektes zugegriffen die nicht gesetzt ist (auch wenn sie nur nicht im Sichtbarkeitsbereich liegt, aufgrund von private/protected), so wird überprüft ob diese Eigenschaft in den als verfügbar festgelegten Feldern des Arrays fields enthalten ist. Wenn dem so ist wird ein Datenbank-Query ausgeführt, der das entsprechende Feld für den aktuellen User updated, und der neue Wert dann in den Array cache geschrieben (ein eventuell bereits vorhandener Eintrag für diese Eigenschaft wird überschrieben, klar).
    Beispiel:

    PHP
    <?php
    // ...code blabla code...
    $user = new User($db,$user_id);
    $user->name = "Peter";
    ?>


    name ist keine gesetzte Eigenschaft in dem User-Objekt, also wird auf die magische Methode __get zugegriffen. Diese sieht, dass "name" durch den Array fields zugelassen (=enthalten) ist, aktualisiert das entsprechende Feld in der Datenbank und schreibt den neuen Wert in den Array cache. Der Name für unseren User wird also auf "Peter" gesetzt.

    Die Idee zu dieser Verwendung von __set und __get habe ich in einem Tutorial gefunden, für gut befunden, und dreist assimiliert.
    Hier die Quelle:
    http://professionelle-softwareentwicklung-mit-php5.de/oop.interceptors.set.html
    Beispiel 2.5: Virtuelle Instanzvariablen im Einsatz

    [Edit]
    Klassen-Beschreibung im 2. Post begonnen

    Kleinen Fehler in der Methode registerUser behoben, der dazu führte, dass neue User im mit isActive=0 registriert wurden, auch wenn durch Übergabe des Parameters $requiresActivation=false festgelegt wurde, dass keine Aktivierung nötig ist.
    [/Edit]


    Hier habe ich mal eine kleine User-Klasse mit ein paar Grundfunktionalitäten. Ist jetzt nicht besonders umfangreich, kann aber recht problemlos erweitert werden (weiter User-Felder z.B.).

    Benötigt:
    PHP5
    MySQLi (OOP-Stil)


    User können sich registrieren, hierbei kann per Parameter festgelegt werden, ob eine Aktivierung erforderlich ist oder der User direkt freigeschaltet wird.
    Ist eine Aktivierung erforderlich wird beim registrieren ein Aktivierungscode erstellt und zurückgegeben. Mit diesem Aktivierungscode und der id des soeben angelegten Users kann der User dann freigeschaltet werden, bzw ein Link generiert werden den man dem User per Email schickt, wie ihr das macht ist eure Sache. :)
    Für das User-Login kann festgelegt werden, ob IP-Adressen nach einer bestimmten Anzahl fehlgeschlagener Login-Versuche in einem bestimmten Zeitraum für einen bestimmten Zeitraum gesperrt werden sollen.
    Die entsprechende Anzahl und der entsprechende Zeitraum können in den Klassen-Konstanten angepasst werden.


    User.class.php

    tables.sql


    Desweiteren habe ich hier noch einen kleinen Beispielcode zur Verwendung. Man kann sich damit registrieren, der Aktivierungslink wird nicht verschickt sondern direkt ausgegeben. Man kann sich einloggen und ausloggen. Ist aber alles eher schlampig auf die schnelle runtergehackt. Zum testen reicht es aber :)
    Die Dateien müssen so benannt werden wie hier und im gleichen Verzeichnis wie die User.class.php abgelegt werden. Natürlich müssen vorher die MySQL-Tabellen angelegt werden.
    In der test.php müssen außerdem die Daten für die DB-Verbindung angepasst werden.

    test.php

    loginForm.tpl.php

    registerForm.tpl.php

    Nur mal so nebenbei:
    Das Datenbankobjekt im Konstruktor der Klasse zu erstellen ist ganz schlecht. Wenn die Datenbankverbindung ausschließlich in dieser Klasse und nirgends sonst benötigt wird, dann ist es noch halbwegs vertretbar, wenn auch immer noch schlecht in Sachen Wiederverwendbarkeit.
    Ich gehe aber mal davon aus, dass die DB-Verbindung auch von anderen Klassen benötigt wird. Generiert da jede Klasse ein eigenes DB-Objekt? Sehr unperformant.
    Sinnvoller ist es, das Datenbankobjekt im Hauptprogramm zu erzeugen und den Klassen die es benötigen als Parameter an den Konstruktor zu übergeben.



    Natürlich geht das, habe grad mal eben exakt deine Beschreibung nachgebaut:

    PHP
    <?php
    session_start();
    $_SESSION['var'] = !isset($_SESSION['var']) ? uniqid() : $_SESSION['var'];
    if(!isset($_GET['redir']) || $_GET['redir']!="no") {
    	header("Location: mytest.php?redir=no");
    }
    echo $_SESSION['var'];
    ?>

    Was soll da jetzt nicht funktionieren? Läuft einwandfrei.


    Allerdings habe ich mir grad nochmal das Eröffnungspost angeschaut. Der TE hat uns da offensichtlich eine wichtige Fehlermeldung verheimlicht. Diese ist so einleuchtend und selbsterklärend, dass er sich den Thread hier auch hätte sparen können, bzw. zumindest den Hinweis darauf hätte bringen müssen:

    PHP
    header("HTTP/1.1 301 Moved Permanently");
    header("Location:#foot");


    Damit begibst du dich in einen Endlos-Loop, die Seite ruft sich immer wieder selbst auf. Und der Browser gibt auch eine entsprechende Meldung aus.
    Du kannst mit PHP nicht innerhalb einer HTML-Datei springen, weil PHP serverseitig läuft. header("Location: xxx") führt immer zu einem neuen Seitenaufruf. Und wenn das selbe Script immer wieder aufgerufen wird und der header()-Befehl nicht in einem einschränkenden if-Befehl liegt, der dafür sorgt, dass er nur beim ersten Aufruf der Seite ausgeführt wird, hat man einen klassischen Endlos-Loop.

    Nä, das hätt ich bestimmt bemerkt.
    Es ging einfach nur die Session Variable nicht, wie hier schon Donkey beschrieb.

    So wies aussieht, weiss also keiner eine Lösung dazu.
    Ich sag jetzt halt nur, falls du - Donkey - das wieder brauchen solltest, dann merk dir, geh einfach über eine redirect-PHP-Seite und dann wieder zurück ins index Script, natürlich aufpassen wegen Endlosschleifen.



    Ohne Code weiß natürlich keiner wo der Fehler liegt und kann eine Lösung bieten. Aber einen Fehler habt ihr beide definitiv gemacht. PHP ist bei euch sicherlich nicht "kaputt", auch wenn viele Leute das gerne so haben wollen wenn etwas nicht klappt, da es ja keinesfalls an ihrem Code liegen kann, der selbstverständlich richtig ist...

    Wenn man es richtig macht funktioniert sowas völlig problemlos.

    Nur mal so aus Neugier: Du nimmst für Sprachkürzel und Name der Sprache den Feldtyp Text? Sind die Felder falsch benannt und da steht was völlig anderes drin als der Bezeichner vermuten lässt, oder was spricht gegen Feldtyp Varchar?
    Das Sprachkürzel wird ja nie länger als 2 ("de","en",etc.) bzw 5 ("de-DE","en-EN",etc.) Zeichen sein und der Name der Sprache sicherlich auch nicht über ~30-40 Zeichen gehen. Wozu da einen so enormen Überhang mit Feldtyp Text generieren?

    Wie sinnvoll ORDER BY RAND() ist hängt stark von der Größe der Tabelle ab. Wenn da nur ein paar Hundert zeilen drin stehen ist es kein allzu großes Ding. Je mehr Zeilen eine Tabelle hat, desto sinnvoller kann es aber sein einen alternativen Weg zu gehen.
    Wenn du eine Tabelle mit 10000 Zeilen hast und darauf ein ORDER BY RAND() verwendest muss SQL erstmal 10000 random ids erstellen, was relativ kostspielig ist. Daraus muss dann die niedrigste ermittelt werden (bzw. in diesem Fall z.B. die 8 niedrigsten).
    Eine Alternative wird hier gezeigt: http://www.titov.net/2005/09/21/do-…ows-from-table/

    Es ist natürlich immer im Einzelfall abzuwägen ob die höhere Belastung durch ORDER BY RAND() ins Gewicht schlägt, bzw. sich überhaupt bemerkbar macht. Auf den meisten kleineren Seiten dürfte das kein Problem darstellen und die bequemste Lösung sein.

    naja genau genommen is ne ci-variante allein schon von der kollation her pfuscherei...

    Für beispielsweise Passwörter, die nicht gerade in eine Form verschlüsselt/gehasht werden, die sowieso nur Zahlen und Kleinbuchstaben ausspuckt, sollte selbstverständlich eine case-sensitive Kollation gewählt werden.
    Für beispielsweise Textfelder, über die Volltext-Suchen laufen sollen, würde ich die ci-Variante wählen.
    Es hat beides seine Vor- und Nachteile, die sollte man sich bewußt machen und dann anhand der Anforderungen problembezogen entscheiden. Ich finde nicht, dass es da allgemeingültig ein richtig oder falsch, sauber oder unsauber gibt.

    also ich werd jetzt meinen beitrag nicht rezitieren, aber für jemanden der programmieren kann ist das problem ja wohl unterste tischkante...
    die von mir gepostete und auch übliche herangehensweise kenne ich schon seit meiner zertifizierungs-vorbereitungen zum sun certified java programmer (das war 2005!!)



    Naja... wenn man das Problem nur umgehen will ist dein Vorschlag ok. Meiner Meinung nach wäre es aber wesentlich sinnvoller herauszufinden wieso die Queries nicht korrekt bei der DB ankommen. Denn in phpmyadmin direkt funktionieren sie ja.
    Deine Lösung ist praktikabel, wenn man zwangsweise mit (case-sensitiven) BIN-Kollationen arbeiten muss, aber nicht wenn man case-ignore-Kollationen verwendet.
    Da ich aber für eine Ferndiagnose hier momentan auch mit meinem Latein am Ende bin, kannst du es ja mal so probieren @ naggison:

    PHP
    $result = mysql_query("SELECT * FROM enn_usr WHERE LOWER(firstname)='".strtolower($firstname)."' AND LOWER(surname)='".strtolower($surname)."'");