AirMax: Sicherheit bei Formular erhöhen

Hallo zusammen

Ich habe ein Formular gebastelt, in das der Nutzer seinen Benutzername und sein Passwort eintragen kann. Zur recht komplexen Validierung binde ich ein zusätzliches Skript ein. Neben profanen Validierungen wie zum Beispiel:

  
if (  
	empty($_POST['userid'])  
	&&  
	$_POST['check'] == 'true'  
   ) {  
	$errormessage = 'Bitte geben Sie Ihre Kundennummer und das dazugehörige Passwort ein.';  
     }

habe ich auch noch Bedingungen, die die Benutzereingaben mit einer Datenbank abgleichen:

  
if (  
	!empty($_POST['userid'])  
	&&  
        // $result ist das assoziative array aus der Datenbank!  
	$_POST['userid'] != $result[userid]  
   ) {  
	$errormessage = 'Die von Ihnen eingegebene Kundennummer ist ungültig. Bitte überpüfen Sie Ihre Eingabe.';  
     }

Das Thema SQL-Injection hat mich dazu gebracht, die Sicherheit innerhalb des Validierungsprozesses zu erhöhen. Dazu will ich einen regulären Ausdruck nutzen. Jetzt habe ich aber ein Problem: Ich weiss nicht, an welcher Stelle ich preg_match() benutzen soll. Etwa IMMER an jeder Stelle, wo ich die Benutzereingabe abrufe? Also in etwa so:

  
if (  
	!empty(preg_match('/[a-z0-9]{12}/i', $_POST['userid']))  
	&&  
	preg_match('/[a-z0-9]{12}/i', $_POST['userid']) != $result[userid]  
   ) {  
	$errormessage = 'Die von Ihnen eingegebene Kundennummer ist ungültig. Bitte überpüfen Sie Ihre Eingabe.';  
     }

Ich sollte vielleicht noch erwähnen, dass ich das Formular bei jeder Anfrage mit $_SERVER['PHP_SELF'] erneut aufrufe.

Macht das Sinn? Das kommt mir ein bisschen komisch vor! Was passiert denn z.B., wenn sich die Benutzereingabe mit dem Suchmuster nicht deckt? Irgendwie sind das mehrere Bedingungen ineinander verschachtelt. preg_match() ist in empty() verschachtelt. Kann mir jemand einen Tipp geben, wie ich mein Durcheinander auflösen kann?

Danke & Gruß
AirMax

  1. Hi

    also ich bin mir, als noch kein profi, in allen Dingen auch noch nicht 100% sicher..

    aber schau die mal die PDO Funktionen in php an. Die beinhalten meiner meinung nach auch sicherheiten gegenüber sql injection.

    Und dann .. benutze doch https..

    grüße carsten

    1. also ich bin mir, als noch kein profi, in allen Dingen auch noch nicht 100% sicher..

      Ich auch nicht! :-D

      aber schau die mal die PDO Funktionen in php an. Die beinhalten meiner meinung nach auch sicherheiten gegenüber sql injection.

      Ich werd's mir mal anschauen.

      Und dann .. benutze doch https..

      Das ist bei dem Hoster leider nicht gratis! Hab mich noch nicht 'getraut' zu fragen, was sowas kostet...

      Gruß

      1. Das ist bei dem Hoster leider nicht gratis! Hab mich noch nicht 'getraut' zu fragen, was sowas kostet...

        also bei meinem Hoster ist das auch nicht gratis,

        aber es gibt einen ssl proxi Link. Quasi ein ssl link für alle und der ist gratis:

        https://sslLink.DomainHoster.de/eigene Domain  oder so ähnlich

        https://eigene Domain   würde auch bei meinem was kosten

        grüße carsten

    2. Und dann .. benutze doch https..

      Was hilft den https gegen bösartigen Userinput?

      mfg Beat

      --
      ><o(((°>           ><o(((°>
         <°)))o><                     ><o(((°>o
      Der Valigator leibt diese Fische
    3. Hi!

      aber schau die mal die PDO Funktionen in php an. Die beinhalten meiner meinung nach auch sicherheiten gegenüber sql injection.

      Fast jede in PHP enthaltene DBMS-API bietet Mittel, um SQL-Injection zu verhindern, man muss sie nur kennen und nutzen. Und man kann auch unter PDO unsichere Statements verfassen.

      Lo!

      1. Fast jede in PHP enthaltene DBMS-API bietet Mittel, um SQL-Injection zu verhindern, man muss sie nur kennen und nutzen. Und man kann auch unter PDO unsichere Statements verfassen.

        Hi

        kennst Du da ein konkretes Beispiel?

        Im php_manual meine ich gelesen zu haben, das PDO die sql-Anfragen automatisch vor sql injection schützt.
        Da gibt's auch ein beispiel , bei dem direkt eine $_GET Varibale in das Statement eingebaut wird, mit dem Hinweis, dass PDO automatisch vor SQL_injection schützt.

        Grüße carsten

        1. Hi!

          Im php_manual meine ich gelesen zu haben, das PDO die sql-Anfragen automatisch vor sql injection schützt.

          Das kann es natürlich nur dann machen, wenn es weiß, was Wert und was SQL-Statement ist.

          Wenn du die Methode PDO::query() verwendest, dann übergibst du ein fix und fertiges SQL-Statement, in das von PDO nicht weiter eingegriffen wird. Du musst dabei - so wie es auch im Manual steht - für die Behandlung von eingefügten Werten selbst sorgen ("Data inside the query should be properly escaped.")

          Da gibt's auch ein beispiel , bei dem direkt eine $_GET Varibale in das Statement eingebaut wird, mit dem Hinweis, dass PDO automatisch vor SQL_injection schützt.

          Du musst Prepared Statemens verwenden und dort die Parameter wie vorgesehen übergeben, sprich: binden. Prepared Statements schützen nicht per se vor SQL-Injection - viel besser: bei ihnen tritt bei richtiger Verwendung das Problem erst gar nicht auf. Üblicherweise geht das Statement zuerst zum DBMS (Prepare), erst dann folgen die Parameter getrennt davon (Execute mit vorherigem Bind). Da sie nicht in das Statement eingefügt werden, müssen sie auch nicht mit Begenzungszeichen versehen werden, und es ergibt sich dann keine Verwechslungsgefahr zwischen Anführungszeichen als Begrenzungszeichen und als Datenbestandteil. Die mit Bind gebundenen Werte sind komplett Daten.

          Es hindert dich aber niemand daran, das SQL-Statement mit selbst eingefügten Werten statt Platzhaltern (oder beides gemischt) zu versehen und es dann über den Prepared-Statement-Mechanismus abzusenden.

          SELECT feldliste FROM tabelle WHERE foo='bar' AND baz=:qux

          Nur qux ist ein Platzhalter, der - siehe oben - nicht anfällig für SQL-Injection ist. bar ist keiner und muss wie üblich selbst behandelt werden.

          Das gleiche Prinzip gilt auch für die mysqli-Extension: herkömmliche Query versus Prepared Statement. Die immer noch häufig verwendete mysql-Extension kennt hingegen keine Prepared Statements.

          Achte übrigens mal auf Example 6. Das erste ist nicht richtig angewendet, interessiert aber grad nicht. Beim zweiten sind zwar die Jokerzeichen für das LIKE an der richtigen Stelle, es kann sich aber ein ählicher Problemfall wie bei SQL-Injection ergeben. In $_GET[name] können sich vom Anwender eingegebene % und _ befinden, die ebenso vom Server als Jokerzeichen ausgewertet werden. Man kann damit zwar nicht ins SQL-Statement ausbrechen, doch es können sich Suchtreffer ergeben, die vom Programmierer nicht vorgesehen sind. Wenn dies nicht beabsichtigt ist, müssen die % und _ durch die im DBMS üblichen Ersatzschreibweisen ausgetauscht werden.

          Lo!

          1. Hi

            also ich benutze auch die prepared statements

            aber hierzu :

            Achte übrigens mal auf Example 6. Das erste ist nicht richtig angewendet, interessiert aber grad nicht. Beim zweiten sind zwar die Jokerzeichen für das LIKE an der richtigen Stelle, es kann sich aber ein ählicher Problemfall wie bei SQL-Injection ergeben. In $_GET[name] können sich vom Anwender eingegebene % und _ befinden, die ebenso vom Server als Jokerzeichen ausgewertet werden. Man kann damit zwar nicht ins SQL-Statement ausbrechen, doch es können sich Suchtreffer ergeben, die vom Programmierer nicht vorgesehen sind. Wenn dies nicht beabsichtigt ist, müssen die % und _ durch die im DBMS üblichen Ersatzschreibweisen ausgetauscht werden.

            Beim dem beispiel steht aber extra drüber, dass es sich bei beiden Beispielen um Falschbeispiele handelt...

            kann man dann nicht davon ausgehen, dass automatisch % escaped oder umgeschrieben wird.

            grüße carsten

            1. Hi!

              Achte übrigens mal auf Example 6.

              Beim dem beispiel steht aber extra drüber, dass es sich bei beiden Beispielen um Falschbeispiele handelt...

              Die Überschrift gilt zwar für den gesamten Kasten, aber der Kommentar vor dem zweiten hebt sie für dieses auf. Das heißt also, dass der zweite Teil richtig ist. Ansonsten könnte man ja gar kein LIKE mit Prepared Statements verwenden.

              kann man dann nicht davon ausgehen, dass automatisch % escaped oder umgeschrieben wird.

              Davon kann man nicht ausgehen. Zum einen, weil es nicht so definiert ist und zum anderen weil ein Prepared Statemend nicht unterscheiden kann, ob das % oder _ nun Jokerzeichen sein soll oder nicht.

              Lo!

              1. Hi

                Die Überschrift gilt zwar für den gesamten Kasten, aber der Kommentar vor dem zweiten hebt sie für dieses auf. Das heißt also, dass der zweite Teil richtig ist. Ansonsten könnte man ja gar kein LIKE mit Prepared Statements verwenden.

                aber ist es nicht so , dass man mit den prepared statements gar kein LIKE übergeben kann, sondern dass es schon im sql statement stehen muß????

                es gibt doch 3 Verschiedene methoden etwas ins statement einzufügen:

                $pdo->bindValue(...)
                $pdo->bindParam(...)
                $pdo->bindColumn(...)

                kann man dann nicht davon ausgehen, dass automatisch % escaped oder umgeschrieben wird.

                Davon kann man nicht ausgehen. Zum einen, weil es nicht so definiert ist und zum anderen weil ein Prepared Statemend nicht unterscheiden kann, ob das % oder _ nun Jokerzeichen sein soll oder nicht.

                ??
                kannst Du nicht mal ein Beispiel posten, wie man  konkret mit % oder _ etwas gefährliches über ein Formular einfügen kann.

                carsten

                1. Hi!

                  aber ist es nicht so , dass man mit den prepared statements gar kein LIKE übergeben kann, sondern dass es schon im sql statement stehen muß????

                  Ja, das ist nicht so. Man kann auch eine Parameter für LIKE per Platzhalter übergeben, aber man muss eben die Jokerzeichen wie Datenbestandteile übergeben. Sie müssen also mit in dem gebundenen Wert enthalten sein und nicht am Platzhalter kleben.

                  es gibt doch 3 Verschiedene methoden etwas ins statement einzufügen:

                  $pdo->bindValue(...)
                  $pdo->bindParam(...)
                  $pdo->bindColumn(...)

                  Es gibt nur zwei. PDO::bindColumn() scheidet aus, weil es einen Wert aus der Ergebnismenge an eine PHP-Variable bindet, so dass diese bei jedem PDO::fetch() den entsprechenden Wert aus der Zeile erhält und damit enthält.

                  Die beiden anderen binden Werte in Richtung DBMS.

                  (Übrigens schreibt man, wenn man außerhalb von Programmcode eine Methode mit ihrem Namen erwähnen möchte, es besser so als ob man sie statisch aufriefe. Das hat den Vorteil, dass der Klassenname mit dabei steht und nicht irgendein Variablenname, der theoretisch auch mit sonstwas instantiiert worden sein könnte. Also für PHP: Klassenname::Methodenname())

                  kannst Du nicht mal ein Beispiel posten, wie man  konkret mit % oder _ etwas gefährliches über ein Formular einfügen kann.

                  Das habe ich nicht behauptet. Ich sagte, dass das Ergebnis ein anderes sein kann als erwartet. Wenn der Anwender einen Text sucht, in dem »25% von« enthalten soll, und der gebundene Wert mit den vom Script hinzugefügten Jokerzeichen so aussieht: »%25% von%«, dann findet er alles, wo eine »25« und weiter hinten ein » von« vorkommt. Es muss also (für MySQL) zuerst eine Stringersetzung von % nach % und _ nach \_ vorgenommen werden, anschließend die % vorn und hinten hinzufügen und dann kann das Ergebnis gebunden werden. Inwieweit man damit Daten abfragen kann, die man nicht abfragen soll, hängt von der Anwendung ab.

                  Lo!

                  1. Hi

                    habe mir noch einmal

                    PDOStatement->bindParam
                    PDOStatement->bindValue

                    angeschaut und auf dem 2. Blick festgestellt, dass mir die Unterschiede zwischen beiden Funktionen doch nicht so klar sind.

                    .. weil beide Funktionen im phpmanual fast identisch beschrieben werden.
                    Habe früher  gedacht, dass eine wäre speziell für Insert-Werte und das andere für Select-Werte? aber dem scheint nicht so zu sein..

                    Das habe ich nicht behauptet. Ich sagte, dass das Ergebnis ein anderes sein kann als erwartet. Wenn der Anwender einen Text sucht, in dem »25% von« enthalten soll, und der gebundene Wert mit den vom Script hinzugefügten Jokerzeichen so aussieht: »%25% von%«, dann findet er alles, wo eine »25« und weiter hinten ein » von« vorkommt. Es muss also (für MySQL) zuerst eine Stringersetzung von % nach % und _ nach \_ vorgenommen werden, anschließend die % vorn und hinten hinzufügen und dann kann das Ergebnis gebunden werden. Inwieweit man damit Daten abfragen kann, die man nicht abfragen soll, hängt von der Anwendung ab.

                    Eigentlich könnten die PDO-Functionen das % doch automatisch verändern oder ?

                    liebe Grüße

                    carsten

                    1. Hi,

                      habe mir noch einmal

                      PDOStatement->bindParam
                      PDOStatement->bindValue

                      angeschaut und auf dem 2. Blick festgestellt, dass mir die Unterschiede zwischen beiden Funktionen doch nicht so klar sind.

                      .. weil beide Funktionen im phpmanual fast identisch beschrieben werden.

                      Ja, aber eben auch nur fast.

                      PDOStatement::bindParam
                      Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.

                      Nutzt du PDOStatement::bindValue, dann wird der aktuelle Wert der Variablen zum Zeitpunkt der Ausführung dieser Funktion eingesetzt.

                      Nutzt du hingegen PDOStatement::bindParam, dann kanst du dein Statement auch weit vorher vorbereiten, bspw. während der Initialisierung eines Moduls. Der Wert des ans Statement gebunden Parameters kann dann im weiteren Scriptverlauf noch beliebig manipuliert werden - erst, wenn du das Statement ausführst, wird der zu diesem Zeitpunkt aktuelle Wert eingesetzt.

                      Eigentlich könnten die PDO-Functionen das % doch automatisch verändern oder ?

                      Dann könntest du LIKE wirklich nicht mehr verwenden, weil nicht nur dein als Datenbestandteil gemeintes % behandelt würde, sondern auch dein als Platzhalterzeichen gemeintes %.

                      MfG ChrisB

                      --
                      “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
  2. Hi,

    Das Thema SQL-Injection hat mich dazu gebracht, die Sicherheit innerhalb des Validierungsprozesses zu erhöhen. Dazu will ich einen regulären Ausdruck nutzen.

    Warum?

    Behandle die Daten kontextgerecht, und fertig.

    MfG ChrisB

    --
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
    1. Warum?

      Behandle die Daten kontextgerecht, und fertig.

      Dieser Artikel ist einer meiner "liebsten".
      Trotzdem danke für Deinen Tipp.

      1. Hi,

        Behandle die Daten kontextgerecht, und fertig.

        Dieser Artikel ist einer meiner "liebsten".

        Welche Fragen hast du denn dann noch?

        MfG ChrisB

        --
        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
        1. Welche Fragen hast du denn dann noch?

          Ich muss zugeben, dass dieser Artikel 'schwere Kost' für mich ist. Der Anfang geht ja noch, aber dann wird's immer verrückter. aber da muss ich wohl durch ...

          1. Mahlzeit AirMax,

            aber da muss ich wohl durch ...

            Ja.

            MfG,
            EKKi

            --
            sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
        2. Welche Fragen hast du denn dann noch?

          Das Zauberwort heißt also mysql_real_escape_string()?!
          Mehr nicht?! Das reicht?

          Gruß

          1. Hi,

            Das Zauberwort heißt also mysql_real_escape_string()?!
            Mehr nicht?! Das reicht?

            Ja.

            MfG ChrisB

            --
            “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
            1. Das Zauberwort heißt also mysql_real_escape_string()?!
              Mehr nicht?! Das reicht?

              Ja.

              Wer hätte das gedacht! DANKE

            2. Hi ChrisB.

              Das Zauberwort heißt also mysql_real_escape_string()?!
              Mehr nicht?! Das reicht?

              Ja.

              Für SQL-Strings. Für numerische SQL-Werte: Nein.

              Viele Grüße,
              der Bademeister

  3. Mahlzeit

    Ich habe eine grundsätzliche Frage, die mich schon seit Tagen beschäftigt. Ich überlege hin und her und weiss nicht, was die bessere Lösung ist:
    Es wird ja immer wieder dazu geraten die Struktur einer HTML-Seite von dessen Gestaltung (CSS) zu trennen. Das leuchtet mir auch ein. Dieses Prinzip möchte ich auch auf die Kombination PHP-HTML anwenden. In meinen Augen sind PHP-Skripte dafür da einen Prozess abzuwickeln, um anschliessend ein Ergebnis zu liefern, dass unabhängig vom Kontext ist und frei von jeglicher Formatierung. Ich finde, dass diese Einstellung PHP-Skripte universeller einzetzbar und pflegeleichter macht. Soweit - sogut. Aber jetzt kommt mein Problem: Ich weiss nicht, wie ich den PHP-Return dynamisch in mein HTML-Dokument einbinden soll?! Hier mal ein Beispiel. Am besten gleich das von diesem Thread: Ein Formmailer, der bei falscher oder ungültiger Eingabe eine Fehlermeldung ausgibt.

    Das PHP-Skript 'uservalidation.php' gibt bei falscher oder ungültiger Eingabe eine Fehlermeldung aus:

      
    if (empty($_POST['userid']) && $_POST['check'] == 'true') {  
        $errormessage = 'Bitte geben Sie Ihre Kundennummer und das dazugehörige Passwort ein.';  
    }  
    
    

    $errormessage soll nun ins HTML-Dokument eingebunden werden:

      
    <?php include('uservalidation.php') ?>
    
      
    <form id="infomaterial" action="[code lang=php]<?php echo $_SERVER['PHP_SELF']; ?>
    ~~~" method="post">  
    .....  
    <input type="submit" class="submit" value="anmelden" />  
    <!-- An dieser Stelle könnte die Fehlermeldung kommen -->  
    <p class="xy">`<?php echo $errormessage; ?>`{:.language-php}</p>  
    </form>  
    [/code]  
    Das würde auch gut funktionieren:  
    ~~~html
      
    <form id="infomaterial" action="/php/login.php" method="post">  
    .....  
    <input type="submit" class="submit" value="anmelden" />  
    <p class="xy">Bitte geben Sie Ihre Kundennummer und das dazugehörige Passwort ein.</p>  
    </form>  
    
    

    Aber was, wenn kein Fehler auftrat?

      
    <form id="infomaterial" action="/php/login.php" method="post">  
    .....  
    <input type="submit" class="submit" value="anmelden" />  
    <p class="xy"></p>  
    </form>  
    
    

    Ist das akzeptabel? Wohl eher unvorteilhaft. Denn diese Ausgabe produziert mir einen Abzatz, den ich eigentlich garnicht haben will! Deshalb überlege ich, welche Möglichkeiten ich noch habe. Eine davon wäre, dass ich eine weitere PHP-Datei einbinde, sobald $errormessage gesetzt wurde:

    PHP-Datei 'errormessage.php':

      
    if (isset($errormessage){  
        echo "<p class=\"xy\">$errormessage</p>;"  
    }  
    
    

    HTML-Dokument:

      
    <?php include('uservalidation.php') ?>
    
      
    <form id="infomaterial" action="[code lang=php]<?php echo $_SERVER['PHP_SELF']; ?>
    ~~~" method="post">  
    .....  
    <input type="submit" class="submit" value="anmelden" />  
    <!-- An dieser Stelle könnte die Fehlermeldung kommen -->  
    <p class="xy">`<?php include('errormessage.php') ?>`{:.language-php}</p>  
    </form>  
    [/code]  
    Wäre das eine vernünftige Alternative? Bei dieser Variante habe ich nur die Befürchtung, dass ich am Ende immer mehr includes bekomme, dass die ganze Angelegenheit unübersichtlich wird. Es fällt ja öfter das Stichwort "HTML-Template". Ich weiss nicht genau, wie das funktioniert. Aber wäre das eine Lösung dafür? Ich wäre froh, wenn ich auf das zunächst verzichten könnte. Muss erst mal in PHP richtig fit werden.  
    Ich hoffe, Ihr habt mein Problem verstanden und könnt mit ein paar Tipps geben!  
      
    Danke & Gruss  
    AirMax
    
    1. Hab gerade noch einen Fehler gesehen. Es müsste richtig so lauten:

      HTML-Dokument:

        
      <?php include('uservalidation.php') ?>
      
        
      <form id="infomaterial" action="[code lang=php]<?php echo $_SERVER['PHP_SELF']; ?>
      ~~~" method="post">  
      .....  
      <input type="submit" class="submit" value="anmelden" />  
      <!-- An dieser Stelle könnte die Fehlermeldung kommen -->  
      `<?php include('errormessage.php') ?>`{:.language-php}  
      </form>  
      [/code]  
      anstatt:  
        
      
      > HTML-Dokument:  
      > ~~~php
        
      
      > <?php include('uservalidation.php') ?>
      
      

      <form id="infomaterial" action="[code lang=php]<?php echo $_SERVER['PHP_SELF']; ?>

      
      > .....  
      > <input type="submit" class="submit" value="anmelden" />  
      > <!-- An dieser Stelle könnte die Fehlermeldung kommen -->  
      > <p class="xy">`<?php include('errormessage.php') ?>`{:.language-php}</p>  
      > </form>  
      
      [/code]  
        
      Gruss
      
    2. Hallo

      ... Eine davon wäre, dass ich eine weitere PHP-Datei einbinde, sobald $errormessage gesetzt wurde:

      PHP-Datei 'errormessage.php':

      if (isset($errormessage){
          echo "<p class="xy">$errormessage</p>;"
      }

      
      > HTML-Dokument:  
      > ~~~php
        
      
      > <?php include('uservalidation.php') ?>
      
      

      <form id="infomaterial" action="[code lang=php]<?php echo $_SERVER['PHP_SELF']; ?>

      
      > .....  
      > <input type="submit" class="submit" value="anmelden" />  
      > <!-- An dieser Stelle könnte die Fehlermeldung kommen -->  
      > <p class="xy">`<?php include('errormessage.php') ?>`{:.language-php}</p>  
      > </form>  
      > [/code]  
      > Wäre das eine vernünftige Alternative?  
        
      Naja, irgendwie nicht. Das passt zwar logisch, aber ein Skript einzubinden, das nichts weiter macht, als eine Variable auf Existenz zu prüfen und bei Bejahung der Existenz mit einem HTML-Schnipsel drumrum auszugeben (siehe dein Folgeposting), ist mit Kanonen auf Spatzen geschossen.  
        
      `echo (isset($errormessage)) ? '<p class="xy">'.htmlspecialchars($errormessage).'</p>' : '';`{:.language-php}  
        
      ... direkt im Skript wäre eine einfache Möglichkeit.  
        
      
      > Bei dieser Variante habe ich nur die Befürchtung, dass ich am Ende immer mehr includes bekomme, dass die ganze Angelegenheit unübersichtlich wird.  
        
      Mehr Includes: ja; unübersichtlicher: nein; egal, welche Form du benutzt, wenn es zu einer Entscheidung kommt, ein Stück content auszugeben oder nicht, muss sie getroffen werden. Das mit include zu machen, ist eine Möglichkeit, wenn auch nicht die Beste.  
        
      
      > Es fällt ja öfter das Stichwort "HTML-Template". Ich weiss nicht genau, wie das funktioniert. Aber wäre das eine Lösung dafür? Ich wäre froh, wenn ich auf das zunächst verzichten könnte.  
        
      Es wäre ebenfalls eine mögliche Lösung. Man legt dazu HTML-Vorlagen an, die an den relevanten Stellen Platzhalter für einzufügende Inhalte haben. Dass sich das ausschließlich für Fehlermeldungen lohnt, bezweifle ich aber. Da muss man schon größer rangehen.  
        
      Eine mögliche Herangehensweise:  
        
      template.tpl:  
      `<p class="xy">[%fehlermeldung%]</p>`{:.language-html}  
        
      PHP  
      ~~~php
      # Anlegen der Variable  
      $fehlerausgabe = '';  
        
      # Bei Bedarf Template laden und ausfüllen  
      if (!empty($errormessage)) {  
      $fehlertemplate = file_get_contents('template.tpl');  
      $fehlerausgabe = str_replace('[%fehlermeldung%]', htmlspecialchars($errormessage), $fehlertemplate);  
      }  
        
      # wenn vorhanden: Ausgabe der Fehlermeldung; wenn nicht, dann nicht  
      echo (!empty($fehlerausgabe)) ? $fehlerausgabe : '';
      

      Tschö, Auge

      --
      Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war.
      Terry Pratchett, "Wachen! Wachen!"
      Veranstaltungsdatenbank Vdb 0.3
    3. Hi!

      Ich überlege hin und her und weiss nicht, was die bessere Lösung ist:

      Es gibt keinen goldenen Weg. Alles hat seine Vor- und Nachteile. (Und das Thema ist auch nicht neu.)

      Es wird ja immer wieder dazu geraten die Struktur einer HTML-Seite von dessen Gestaltung (CSS) zu trennen.

      Andere Baustelle.

      Dieses Prinzip möchte ich auch auf die Kombination PHP-HTML anwenden.

      Das Ergbnis eines PHP-Scripts ist eine Ausgabe (HTML) und ein paar nicht sichtbare Nebenwirkungen (Geschäftslogik).

      In meinen Augen sind PHP-Skripte dafür da einen Prozess abzuwickeln, um anschliessend ein Ergebnis zu liefern, dass unabhängig vom Kontext ist und frei von jeglicher Formatierung.

      Wenn du das so siehst, dürftest du nur Daten erzeugen. Aber irgendwer muss diese Daten auch wieder in HTML-Form bringen, doch wer soll das tun, wenn nicht ebenfalls PHP? Das Prinzip HTML-CSS-Trennung ist also ganz so einfach nicht auf PHP anwendbar.

      Ich finde, dass diese Einstellung PHP-Skripte universeller einzetzbar und pflegeleichter macht.

      Das geht nur insofern, als dass du Dinge hast, die wirklich abstrahierbar sind. Diesen Versuch gehen diverse Frameworks. Sie bieten allgemeine Funktionalität ohne ein konkretes Ausgabeergebnis (HTML) oder erzeugen eine generische Ausgabe, die entweder so universell ist, dass sie gut mit CSS angepasst werden kann, oder der Ausgabeteil lässt sich überschreiben, oder sie liefern nur Helper-Funktionen, die man dann von seinem eigenen Template aus aufrufen kann.

      Soweit - sogut. Aber jetzt kommt mein Problem: Ich weiss nicht, wie ich den PHP-Return dynamisch in mein HTML-Dokument einbinden soll?!

      Das kommt nun darauf an, was du vorliegen hast, wenn es zum Ausgabeteil der Anwendung kommt: reine Daten oder vorgefertigte Ausgabemodule oder beides gemischt.

      Das PHP-Skript 'uservalidation.php' gibt bei falscher oder ungültiger Eingabe eine Fehlermeldung aus:

      if (empty($_POST['userid']) && $_POST['check'] == 'true') {

      $errormessage = 'Bitte geben Sie Ihre Kundennummer und das dazugehörige Passwort ein.';
      }

        
      Da ist schon das erste Problem, allgemeiner Natur. Du hast eine Bedingung und legst daraufhin eine Variable an. Trifft die Bedingung nicht zu, existiert die Variable nicht, folgende Lesezugriffe greifen ins Leere und erzeugen Notice-Meldungen (wenn sie bei dir nicht unterdrückt sind).  
        
      Wenn du Daten erzeugt (nicht nur solche, die später ausgegeben werden sollen), sorge dafür, dass sie stets vorhanden sind, und sei es auch nur mit einem Default-Wert. Dann können sie dir außerdem auch nicht von anderen Quellen mit ungewünschtem Inhalt angelegt werden (siehe register\_globals).  
        
      
      > $errormessage soll nun ins HTML-Dokument eingebunden werden:  
      > `<form id="infomaterial" action="[code lang=php]<?php echo $_SERVER['PHP_SELF']; ?>`{:.language-html}" method="post">  
      > .....  
      > <input type="submit" class="submit" value="anmelden" />  
      > <!-- An dieser Stelle könnte die Fehlermeldung kommen -->  
      > <p class="xy">`<?php echo $errormessage; ?>`{:.language-php}</p>  
      > </form>[/code]  
        
      Kontextgerechte Behandlung beim Einfügen von Werten nicht vergessen. Bitte auch in Beispielen nicht! Das betrifft hier dein action-Attribut und den Fehlermeldungstext.  
        
      
      > Aber was, wenn kein Fehler auftrat? Ist das akzeptabel? Wohl eher unvorteilhaft. Denn diese Ausgabe produziert mir einen Abzatz, den ich eigentlich garnicht haben will!  
        
      Ja deshalb gibt es die Möglichkeit der bedingten Ausführung. Wenn keine Fehlermeldungen vorhanden sind, müssen sie weder ausgegeben werden noch die dafür notwendigen HTML-Strukturen.  
        
      
      > Deshalb überlege ich, welche Möglichkeiten ich noch habe. Eine davon wäre, dass ich eine weitere PHP-Datei einbinde, sobald $errormessage gesetzt wurde:  
        
      Ob du dich in Dateien verzettelst oder die Ausgabe für ein Modul[\*] in einer Template-Datei bündelst musst du selbst wissen.  
        
      [\*] Die einzelnen Module beispielsweise können später im grundlegenden Seitengerüst eingebunden werden.  
        
      
      > Wäre das eine vernünftige Alternative? Bei dieser Variante habe ich nur die Befürchtung, dass ich am Ende immer mehr includes bekomme, dass die ganze Angelegenheit unübersichtlich wird. Es fällt ja öfter das Stichwort "HTML-Template".  
        
      PHP ist bereits eine Template-Sprache, die in HTML eingebunden wird. Ob es sinnvoll ist extra noch ein Template-System einzusetzen, kommt auf die konkreten Rahmenbedingungen an.  
        
      Versuch erst einmal deinen Programmablauf nach dem EVA-Prinzip zu strukturieren: Eingabedaten behandeln - Verarbeitung - Ausgabe.  
        
      Immer wiederkehrende Programmteile lagert man beispielsweise in Funktionen aus. Darin verwendete Variablen kommen auch nicht mit anderen gleichnamigen Variablen in anderen Programmteilen in Konflikt. Include-Dateien mit Geradeaus-Code drin hat das Problem, dass dieser letzlich im globalen Scope ausgeführt wird. Du musst also trotz deines Modularisierungsversuchs per Include-Dateien aufpassen, dass sich die Teile nicht ins Gehege kommen.  
        
      Modularisiere / kapsele also erst einmal deine Programmteile mit Funktionen, bevor du daran denkst, sie in Include-Dateien auszulagern.  
        
      Fehlermeldungen fallen mitunter mehrere an. Manchmal sind sie allgemeine Meldungen, manchmal beziehen sich sich auf etwas konkretes. manchmal will man sie gebündelt anzeigen, manchmal direkt neben dem zugehörigen Eingabefeld. Deine Verarbeitung legt sie deshalb besser in einer generellen Struktur an, einem Array beispielsweise.  
        
      $errors = array();  
        
      if (eingabefeldX ist fehlerhaft) {  
        $errors[eingabefeldX][] = meldung1;  
      }  
      if (eingabefeldX ist auch noch anderweitig fehlerhaft) {  
        $errors[eingabefeldX][] = meldung2;  
      }  
        
      if (eingabefeldY ist fehlerhaft) {  
        $errors[eingabefeldY][] = meldung;  
      }  
        
      if (allgemeiner Fehler) {  
        $errors[''][] = meldung;  
      }  
        
      Mehr muss der verarbeitende Teil in Punkto Fehlermeldungen nicht erzeugen. Für die Ausgabe kommt es nun darauf an, welche Art du bevorzugst. Du könntest es so schreiben.  
        
      <?php if (!empty($errors)): ?>  
      <ul class="errors">  
        <?php foreach($errors as $field\_name => $field\_errors): ?>  
        ...  
        <?php endforeach; ?>  
      </ul>  
      <?php endif; ?>  
        
      Du könntest eine Helferfunktion schreiben, die die Ausgabe erzeugt  
        
      function errormessage($errors, $field\_name) {  
        $ausgabe = '';  
        if (isset($errors[$field\_name]))  
          foreach ($errors[$field\_name] as $error)  
            $ausgabe .= sprintf("<foo>...%s...</foo>\n", htmlspecialchars($error));  
        return $ausgabe;  
      }  
        
      und sie beim Eingabefeld aufrufen  
        
      <input name="field\_name" value="...">  
      <?php echo errormessage($errors, 'field\_name'); ?>  
        
      oder, oder, oder.  
        
      Dies ist nur ein Beispiel, wie man es in einer recht einfachen Umgebung machen kann. Andere werden ihre eigene Vorgehensweise haben, mit der sie gut fahren.  
        
        
      Lo!
      
      1. Hi Lo!

        Vielen Dank für Deine umfangreiche Antwort

        Kontextgerechte Behandlung beim Einfügen von Werten nicht vergessen. Bitte auch in Beispielen nicht! Das betrifft hier dein action-Attribut und den Fehlermeldungstext.

        Ja, ich weiss.Kontextgerecht Behandlung ist noch nicht so meine Stärke. Ich habe die Fehler auch schon erkannt. Aber das passiert eben, wenn man aus dem Stegreif heraus etwas bastelt...

        Ob du dich in Dateien verzettelst oder die Ausgabe für ein Modul[*] in einer Template-Datei bündelst musst du selbst wissen.

        [*] Die einzelnen Module beispielsweise können später im grundlegenden Seitengerüst eingebunden werden.

        Eben. Ich glaube, dass ich aus ein include-Wirrwar besser verzichten sollte.
        Ob Tamplates die Alternative für mich ich, weiss ich noch nicht. Dafür müsste ich mich erst einmal damit befassen.

        Immer wiederkehrende Programmteile lagert man beispielsweise in Funktionen aus. Darin verwendete Variablen kommen auch nicht mit anderen gleichnamigen Variablen in anderen Programmteilen in Konflikt. Include-Dateien mit Geradeaus-Code drin hat das Problem, dass dieser letzlich im globalen Scope ausgeführt wird. Du musst also trotz deines Modularisierungsversuchs per Include-Dateien aufpassen, dass sich die Teile nicht ins Gehege kommen.

        Modularisiere / kapsele also erst einmal deine Programmteile mit Funktionen, bevor du daran denkst, sie in Include-Dateien auszulagern.

        Das ist eine gute Idee. Du hast recht. Zurzeit sind die include-Dateien "Geradeaus-Code". Das ist auch noch nicht weiter tragisch.
        Wenn's allerdings an komplexere Projekte geht, könnte es problematisch werden.

        oder, oder, oder.

        Dies ist nur ein Beispiel, wie man es in einer recht einfachen Umgebung machen kann. Andere werden ihre eigene Vorgehensweise haben, mit der sie gut fahren.

        Ich muss mir die ganze Sache erst einmal durch den Kopf gehen lassen. Danach werde ich schlauer sein. Erst einmal vielen Dank für Deine Tipps. Sie haben mir schon geholfen...

        Gruss
        AirMax