Jochen: zweiter Wert speichern

Schönen guten Tag,

ich bin echt am verzeifeln, ich schaff es einfach nicht zwei Werte in eine Tabelle zu speichern, mein Code sieht derzeit wie folgt aus:

  
// Daten in die DB speichern  
if (!empty($_POST))  
{  
 echo '<pre>' , print_r($_POST) , '</pre>';  
  
 if(is_array($_POST)){  
  $_counter = 0;  
  $_data = array();  
  foreach($_POST as $prefix => $post){  
   if(is_array($post)){  
    $_data[$_counter][] = $prefix . " = '".$post[$_counter]."'";  
   }  
  
   mysql_query("Insert into entfernung set ef_in_ID = '".$Id."', ".implode(',',$_data[$_counter]));  
  
   echo "Insert into entfernung set ef_in_ID = '".$Id."', ".implode(',',$_data[$_counter]);  
  $_counter++;  
  }  
 }  
  
 echo '<pre>' , print_r($_data) , '</pre>';  
//header("Location: /advertise-step5.html&id=$loc_ID_ex");  
}  

Mein HTML Formular so:

  
         <form id="form1" class="contact" name="form1" method="post" action="">  
           <p>  
                Bezeichnung  
                 <input name="ef_bezeichnung[]" value="" />  
                 Entfernung  
                  <input name="ef_entfernung[]" value="" />  
                  <br /><br />  
                    <input type="button" id="umgebung" value="Feld hinzufügen" />  
           </p>  
           <p><br />  
             <input type="submit" name="weiter" id="weiter" value="Weiter zu Schritt 4" />  
</p></form>  

und mein JavaScript so:

  
<script>  
$(document).ready(function(){  
   var count = 1;  
   $("#umgebung").click(function(){  
       $(this).before('Bezeichnung' +' <input name="ef_bezeichnung[]' +'" value="" /> Entfernung' +' <input name="ef_entfernung[]' + '" value="" /><br /><br />');  
       count++;  
   });  
});  
</script>  

Im Live Betreib sieht das ganze so aus:

http://s7.directupload.net/images/130618/tf9r24cr.png

Meine Kontrollausgabe ergibt folgendes:

Array
(
    [ef_bezeichnung] => Array
        (
            [0] => Bezeichnung1
            [1] => Bezeichnung2
        )

[ef_entfernung] => Array
        (
            [0] => Entfernung 1
            [1] => Entfernung 2
        )

[weiter] => Weiter zu Schritt 4
)

In meiner Datenbank kommt folgendes an:

http://s7.directupload.net/images/130620/7lqsywi6.png

Komme an dieser Stelle einfach nicht weiter! Hoffe Ihr könnt mir helfen!

Gruß
Jochen

  1. hi

    echo "Insert into entfernung set ef_in_ID = '".$Id."', ".implode(',',$_data[$_counter]);

    dachte immer Update und set - insert mit felder und value

    ralphi

    1. Tach!

      echo "Insert into entfernung set ef_in_ID = '".$Id."', ".implode(',',$_data[$_counter]);
      dachte immer Update und set - insert mit felder und value

      Besonderheit in MySQLs Dialekt: INSERT. ganze Sätze Mangelware - schwer verständlich

      dedlfix.

  2. Tach!

    ich bin echt am verzeifeln, ich schaff es einfach nicht zwei Werte in eine Tabelle zu speichern,

    Schaffst du doch. Du meinst jedoch, beide Werte in denselben Datensatz zu speichern.

    if(is_array($_POST)){

    $_POST ist immer ein Array, wenn du es nicht gewaltsam geändert hast. Diese Bedingung ergibt also üblicherweise immer true.

    foreach($_POST as $prefix => $post){
       mysql_query("Insert into entfernung ...);
      }

    Das weniger wichtige mal weggelassen, und die Kontrollausgabe dazu mal angeschaut ...

    Array
    (
        [ef_bezeichnung] => Array
            (
                [0] => Bezeichnung1
                [1] => Bezeichnung2
            )

    [ef_entfernung] => Array
            (
                [0] => Entfernung 1
                [1] => Entfernung 2
            )

    [weiter] => Weiter zu Schritt 4
    )

    ... zeigt einen überflüssigen Eintrag für den Submit-Button (der braucht kein name-Attribut, wenn du sein value nicht auswerten willst) und dass die zusammengehörigen Daten in zwei Unterarrays verteilt sind. Mit dem foreach arbeitest du sie getrennt ab. Kein Wunder, dass sie in getrennten Datensätzen landen.

    <form id="form1" class="contact" name="form1" method="post" action="">
                     <input name="ef_bezeichnung[]" value="" />
                      <input name="ef_entfernung[]" value="" />

    Es ist besser, die Bezeichnung anders zu wählen: ef[0][bezeichnung] und ef[0][entfernung]. (Die Bedeutung des ef erschließt sich mir nicht, ich habs einfach mal genommen.) Weitere Feldpaare bekommen statt der 0 dann einen anderen eindeutigen Wert, den du dir irgendwo merken musst, damit das Javascript ihn für jedes neue Feldpaar inkrementieren kann.

    Mit dieser Umstrukturierung kannst du nun besser die zusammengehörigen Werte abfragen. Lass es dir mit einer Kontrollausgabe anzeigen, dann siehst du das (hoffentlich).

    Außerdem ist noch zu sagen, dass du den Kontextwechsel missachtest und damit Platz 1 der Top-10-Webanwendungsfehler eingebaut hat.

    dedlfix.

  3. mysql_query("Insert into entfernung set ef_in_ID = '".$Id."', ".implode(',',$_data[$_counter]));
    echo "Insert into entfernung set ef_in_ID = '".$Id."', ".implode(',',$_data[$_counter]);

    Bei solchen Konstrukten merkst du spätestens bei debuggen, dass sie schöner geschrieben werden sollten. Gerade wenn du einen String hast, denn du immer wieder manipulierst, solltest du den String in eine Variable packen bzw. den Code auf mehrere Zeilen aufteilen. Dann kannst du zwischen jede Zeile ein echo (oder andere Ausgabe Mechanismen) packen und gucken wie die Variable gefüllt wird.

    $strInsert = "Insert into entfernung set ef_in_ID = '".$Id;  
    $strInsert .= "', ".implode(',',$_data[$_counter]);  
    mysql_query( $strInsert );
    

    Das kostet natürlich ein wenig mehr Arbeitsspeicher, da man das ganze aber sauber in eine Funktion kapseln sollte, wird dieser nach Aufruf der Funktion wieder Frei gegeben.

    Wenn dein Code etwas mehr aufgeräumt ist (wobei das natürlich geschmacksache ist) würdest du vielleicht das hier sehen:
    foreach($_POST as $prefix => $post)

    Du gehst das $_POST Array durch. Soweit nichts schlimmes, wäre da nicht der obige mysql_query Befehl in dieser Schleife. Du speicherst also pro $_POST Key einen Datensatz in die Datenbank. Richtig wäre natürlich, erst die Daten zusammeln um sie nach der Schleife gemeinsam ab zu speichern.

    Anhand deiner ID in der Datenbank (siehe Bild). Sehe ich auch dass du nicht lange testest. Das beste ist immer bei Problemen deinen Code mit Ausgaben zu zerrupfen, damit du genau siehst wann was passiert.

    Gruß
    Neuland Erkunder
    T-Rex

    1. Tach!

      Bei solchen Konstrukten merkst du spätestens bei debuggen, dass sie schöner geschrieben werden sollten. Gerade wenn du einen String hast, denn du immer wieder manipulierst, solltest du den String in eine Variable packen bzw. den Code auf mehrere Zeilen aufteilen. Dann kannst du zwischen jede Zeile ein echo (oder andere Ausgabe Mechanismen) packen und gucken wie die Variable gefüllt wird.

      $strInsert = "Insert into entfernung set ef_in_ID = '".$Id;

      $strInsert .= "', ".implode(',',$_data[$_counter]);
      mysql_query( $strInsert );

        
      Ich plädiere für sprintf(). Da notiert man die festen Bestandteile des Strings übersichtlich am Stück, mit ein paar kleinen Platzhaltern drin, Die variablen Teile kommen dann als Parameter hintendran (oder zeilenweise untendrunter, wenns der Lesbarkeit dient). Dass der Statement-String stückweise nachvollziehbar entsteht, halte ich nicht für wichtig. Wichtig ist nur, dass man im fertigen String die Stellen mit den Syntaxfehlern erkennt und dem dazugehörigen Erzeuger zuordnen kann. Es ist entweder im feststehenden Teil, der ja (hoffentlich) übersichtlich notiert ist, oder einer der Platzhalter, den man anhand der Position des Fehlers leicht finden sollte.  
        
      
      > Das kostet natürlich ein wenig mehr Arbeitsspeicher,  
        
      Es kostet noch deutlich mehr, nämlich im Falle eines Falles auch mal echtes Geld, wenn man die Sicherheit vernachlässigt und das kontextgerechte Behandeln der Werte beim Einfügen in das SQL-Statement unterlässt (und auch nicht auf Prepared Statements setzt).  
        
        
      dedlfix.
      
    2. Moin!

      $strInsert = "Insert into entfernung set ef_in_ID = '".$Id;

      $strInsert .= "', ".implode(',',$_data[$_counter]);
      mysql_query( $strInsert );

      
      >   
      > Das kostet natürlich ein wenig mehr Arbeitsspeicher, da man das ganze aber sauber in eine Funktion kapseln sollte, wird dieser nach Aufruf der Funktion wieder Frei gegeben.  
        
      Nein, das kostet dynamisch weniger Arbeitsspeicher. PHP benutzt intern zum Stringzusammenbau sowieso eine Speichervariable, die dann von dem Funktionsaufruf implizit verwendet wird. Baut man den String zweimal identisch zusammen, dauert das einerseits länger, andererseits wandern zweimal dieselben RAM-Häppchen in den Bauprozess, werden hinterher nicht mehr benötigt, aber freigegeben und dann neu benutzt werden sie erst, wenn die Garbage Collection den ganzen größeren Variablen-Block im Speicher aufräumt.  
        
       - Sven Rautenberg
      
  4. Moin

    mysql_query("Insert into entfernung set ef_in_ID = '".$Id."', ".implode(',',$_data[$_counter]));

    Dir wurden ja schon viele Tipps gegeben. Nur eins noch: die mysql-Erweiterung für PHP wurde auf DEPRECATED gesetzt und ist in irgendeiner der zukünftigen PHP-Versionen nicht mehr verfügbar. Besser ist Mysqli oder noch besser PDO. (beide Persistente Verbindungen (ja, mysql erst am PHP 5.3, ich weiß, Prepared-Statements und objektorientiert)

    Dies nur als Hinweis am Rande. ;)

    Gruß Bobby

    --
    -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
    ### Henry L. Mencken ###
    -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
    ## Viktor Frankl ###
    ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
  5. Guten Morgen,

    vielen Dank an euch allen für die Hilfe, ich habe es so hinbekommen

      
     $counter = count($_POST['ef_bezeichnung']);  
      
      for ($i = 0; $i < $counter; $i++) {  
        mysql_query("Insert into entfernung set ef_in_ID = '".$Id."', ef_bezeichnung = '".$_POST['ef_bezeichnung'][$i]."', ef_entfernung = '".$_POST['ef_entfernung'][$i]."'");  
      }  
    
    

    ich weiß nicht ob dieses die beste Lösung ist, aber sie geht.

    Gruß
    Jochen

    1. Tach!

      $counter = count($_POST['ef_bezeichnung']);

      for ($i = 0; $i < $counter; $i++) {
          mysql_query("Insert into entfernung set ef_in_ID = '".$Id."', ef_bezeichnung = '".$_POST['ef_bezeichnung'][$i]."', ef_entfernung = '".$_POST['ef_entfernung'][$i]."'");
        }

      
      >   
      > ich weiß nicht ob dieses die beste Lösung ist, aber sie geht.  
        
      Ist sie nicht. Zum einen ist sie, wie schon dein Ausgangsocode, immer noch anfällig für SQL-Injections. Da fehlen mindestens zwei Verwendungen von mysql\_real\_escape\_string(). (Beim $Id ist es eventuell entbehrlich, das kann man aber aus dem gezeigten Code nicht mit Sicherheit erkennen.)  
        
      Du hast dich entschieden, das HTML so zu lassen und stattdessen die Zugehörigkeiten über einen gemeinsamen Indexwert wiederherzustellen. Kann man so machen. Trotzdem kann man den Code noch optimieren. Den $counter braucht es nicht, wenn du eine foreach-Schleife verwendest:  
        
      ~~~php
      foreach ($_POST['ef_bezeichnung'] as $i => $bezeichnung)  
        mysql_query(  
          sprintf("Insert into entfernung set ef_in_ID = '%s', ef_bezeichnung = '%s', ef_entfernung = '%s'",  
            mysql_real_escape_string($Id),  
            mysql_real_escape_string($bezeichnung),  
            mysql_real_escape_string($_POST['ef_entfernung'][$i])));
      

      dedlfix.

      1. Moin

        foreach ($_POST['ef_bezeichnung'] as $i => $bezeichnung)

        mysql_query(
            sprintf("Insert into entfernung set ef_in_ID = '%s', ef_bezeichnung = '%s', ef_entfernung = '%s'",
              mysql_real_escape_string($Id),
              mysql_real_escape_string($bezeichnung),
              mysql_real_escape_string($_POST['ef_entfernung'][$i])));

          
          
        Auch hier noichmal der Hinweis (falls es untergegangen ist), das die normale MySQL-Erweiterung auf DEPRECATED gesetzt wurde und somit in naher ZUkunft nicht mehr verfügbar sein wird! Ich bitte um freundliche Beachtung :p  
          
          
        Gruß Bobby  
        
        -- 
        -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-  
        ### Henry L. Mencken ###  
        -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-  
        ## Viktor Frankl ###  
          
        ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
        
        1. Hallo,

          Auch hier noichmal der Hinweis (falls es untergegangen ist), das die normale MySQL-Erweiterung auf DEPRECATED gesetzt wurde und somit in naher ZUkunft nicht mehr verfügbar sein wird! Ich bitte um freundliche Beachtung :p

          wie würde hier denn der Code aussehen, wenn man den mit der neueren Form schreiben würde? und müsste ich dann alles umschreiben oder kann man das mit dem alten auch mischen?

          Gruß
          Jochen

          1. Tach!

            wie würde hier denn der Code aussehen, wenn man den mit der neueren Form schreiben würde? und müsste ich dann alles umschreiben oder kann man das mit dem alten auch mischen?

            Mischen sollte man gar nicht erst versuchen. Es sind jedoch im Wesentlichen nur die mysql_*-Funktionen zu ersetzen. - - - So einfach wirds aber nicht werden, denn es gibt dann doch noch ein paar Unterschiede in der Handhabung. Alle drei Varianten (mysql seit neuestem deprecated, mysqli und PDO mit Zukunft) sind bei Choosing an API in ganz kurzer Form dargestellt.

            Die bisherigen 08/15-Anwendungen gehen fast 1:1 auf mysqli umzusetzen. mysqli ist nicht nur ein Ersatz sondern auch eine Erweiterung. Die alte mysql-Erweiterung ist im Funktionsumfang bei ungefähr MySQL 4.1 stehengeblieben. Seit der Zeit gibt es allerdings auch schon das im Funktionsumfang erweitere mysqli (i wie improved). Damit können all die neuen Dinge, wie Prepared Statement, Stored Procedures, Mehrfach-Statements und -Ergebnissets bedient werden. Doch damit kommt der 08/15-Anwender kaum in Berührung. Üblicherwiese sind nur noch Prepared Statements für ihn interessant, besonders auch aus sicherheitstechnischem Aspekt, den damit sind wesentlich schwerer SQL-Injection-anfällige Statements zu schreiben. Allerdings ist die Benutzerschnittstelle dafür in mysqli nicht sonderlich anwenderfreundlich, das hat PDO besser hinbekommen. PDO ist eigentlich angetreten, alle DBMSe einheitlich zu bedienen. Ansonsten war die Unterstützung in PHP für jedes DBMS sehr verschieden ausgefallen - in Bedienung und Leistungsumfang. Diese Multi-DBMS-Fähigkeit von PDO braucht man jedoch eher selten, ebenfalls die (Experten-)Funktionalität die mysqli kann, PDO aber nicht. Eine Entscheidung zwischen PDO und mysqli wird daher wohl eher darauf hinauslaufen, welches sich besser handhaben lässt. - Ach ja, PDO ist nur objektorientiert zu haben, mysqli in beiden Varianten, objektorientiert und wie mysql funktional. Das heißt aber nicht, dass man nun komplett Neuland betreten muss, wenn man bisher die OOP unbeachtet gelassen hat. PHP kann sehr gut OOP und herkömmliche Programmierung mischen. Und man muss das sogar tun, weil nur weniges objektorientiert zur Verfügung steht. Das heißt, man kann seine Datenbankfunktionen objektorientiert in PDO oder mysqli schreiben, den Rest aber problemlos herkömmlich lassen.

            dedlfix.

      2. Moin,

        Du hast dich entschieden, das HTML so zu lassen und stattdessen die Zugehörigkeiten über einen gemeinsamen Indexwert wiederherzustellen. Kann man so machen. Trotzdem kann man den Code noch optimieren. Den $counter braucht es nicht, wenn du eine foreach-Schleife verwendest:

        könntest du mir vielleicht an einem Beispiel zeigen, wie ich es auch anderes machen hätte können und mir sagen was die Vor bzw. Nachteile sind?

        Gruß
        Jochen

        1. Tach!

          Du hast dich entschieden, das HTML so zu lassen und stattdessen die Zugehörigkeiten über einen gemeinsamen Indexwert wiederherzustellen. Kann man so machen. Trotzdem kann man den Code noch optimieren. Den $counter braucht es nicht, wenn du eine foreach-Schleife verwendest:

          könntest du mir vielleicht an einem Beispiel zeigen, wie ich es auch anderes machen hätte können und mir sagen was die Vor bzw. Nachteile sind?

          Das Ohne-$counter/foreach-Version hab ich ja schon in meiner vorigen Antwort beschrieben. Der Vorteil ist "nur" eingesparter Code. Meiner ist tatsächlich sogar länger, dafür bringt er aber schon die für den korrekten Kontextwechsel nötige Funktionalität mit, die deinem Code noch fehlt.

          Die Variante mit dem umgebauten HTML hatte ich in meiner ersten Antwort aufgeführt. Der Vorteil wäre, dass du nicht zwei Teil-Arrays parallel und synchron befragen musst, sondern in einem Durchlauf mit nur einem Zugriff beide Werte zusammen in einem Array stehen hast. Zugriff ungefährt so:

          foreach ($_POST['ef_wasweißich'] as $eintrag) {  
            echo $eintrag['bezeichnung'];  
            echo $eintrag['entfernung'];  
          }
          

          Dein HTML muss dazu dann so aussehen:

          <input name="ef_wasweißch[0][bezeichnung]" value="..." ...> und  
          <input name="ef_wasweißch[0][entfernung]" value="..." ...>
          

          Nachteil ist, dass du selbständig nummerieren muss. Die beiden 0 hier müssen für den nächsten Datensatz 1, dann 2 und so weiter sein. Es können auch andere Werte sein, Hauptsache sie sind pro Datensatz gleich und verschieden zu den anderen. Diese Felder tauchen in obigem foreach nicht auf, weil sie nicht benötigt werden. Wenn du sie sehen willst, dann muss das foreach so aussehen:

          foreach ($_POST['ef_wasweißich'] as $key => $eintrag)  
          
          

          Die 0, 1 etc. stehen dann in $key.

          dedlfix.