cc7162: Mehrere Arrays in PHP übergeben / Rechnungsposten (automatisiert) einfügen

Hallo, ich bin relativ neu in PHP und habe eine Frage zu einem Script, das Rechnungen erstellen soll und hoffe Ihr könnt mir helfen. Es handelt sich hier um eine vermutlich für Erfahrene recht einfache bzw. simple Angelegenheit; ich stehe aber auf dem Schlauch aber bin mir dennoch sicher dass das technisch schöner geht.

Ich habe eine Datei invoicing.php, auf welcher derzeit für vier Artikel Eingabefelder mit je einem Artikelnamen, eine Menge und einem Artikelpreis abgefragt werden. Diese werden mit serialize() in vier separate MySQL-Felder geschrieben und in der Datei invoice.php wieder aus dieser herausgeholt um sie anschließend nach unserialize in ein Array($Items) zu schreiben. $Items stellt dann die unterschiedlichen Rechnungspositionen dar und wird zu einer PDF weiterverarbeitet. Die Dateien habe ich in den betreffenden Ausschnitten unten angehangen.

  1. Kann ich mehrere Items/Rechnungspositionen in einem MySQL-Feld speichern? Bin ich da mit einem Delimiter mit Implode/Explode und den Arrays dazwischen auf dem richtigen Weg?
  2. Wie kann ich in der invoice.php die Anzahl der eingetragenen Items bestimmen wenn wenn ich bspw. mit Javascript bis zu 10 Artikeleingabefelder auf der invoicing.php abbilden würde?

Für jede hilfreiche Antwort vorab vielen Dank!

cc7162

-- invoicing.php –-

<input type='text' name='nameitem1' size='55'>
<input type='text' name='countitem1' size='10'>
<input type='text' name='priceitem1' size='10'>

[usw...]

  if($_POST['countitem1'] > 0 [...]){
    $Item1count = $_POST['countitem1'];
    $Item1price = $_POST['priceitem1'];
    $Item1 = serialize(array($Item1name, $Item1count, $Item1price));
}

[...]

$SaveInvoiceDetailQuery = "INSERT INTO invoices (offerid, item1, item2, item3, item4, address) VALUES  ('$OfferID',  '$Item1', '$Item2', '$Item3', '$Item4', '$CustomerString')";

[...]

-- invoice.php --

  while ($row = mysqli_fetch_array($Invoice, MYSQL_ASSOC)) {
    $OfferID = $row['offerid'];
    $CustomerID = $row['customerid'];
    $Item1 = $row['item1'];
    $Item2 = $row['item2'];
    $Item3 = $row['item3'];
    $Item4 = $row['item4'];
    $Address = $row['address'];
  }

[...]

$Item1 = unserialize($Item1);
$Item2 = unserialize($Item2);
$Item3 = unserialize($Item3);
$Item4 = unserialize($Item4);
$Items = array($Item1, $Item2, $Item3, $Item4);
$rechnungs_posten = array($Items);

[...]

foreach($rechnungs_posten as $posten) {
 $menge = $posten[1];
 $einzelpreis = $posten[2];
[...]
}

akzeptierte Antworten

  1. Hello,

    bevor Du anfängst zu basteln, schau dir mal ein paar Systeme und die Erläuterungen dazu an.

    Suchbegriff bei Google Faktura php mysql Tutorial

    Und dann wäre ein Ausflug in "Relationale Datenbanken" ratsam.

    Liebe Grüße
    Tom S.

    --
    Es gibt nichts Gutes, außer man tut es
    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
  2. Tach!

    1. Kann ich mehrere Items/Rechnungspositionen in einem MySQL-Feld speichern?

    Kannst du, macht man aber nicht. Du hast da eine schöne Datenbank, kannst aber ihre Eigenschaften nicht nutzen, wenn du die Daten so "komprimiert" in ihr ablegst. Warum legst du die Eigenschaften eines Rechnungspostens nicht separat in Felder und jeden Posten in einem eigenen Datensatz ab?

    Bin ich da mit einem Delimiter mit Implode/Explode und den Arrays dazwischen auf dem richtigen Weg?

    Ganz und gar nicht. Selbst wenn du das unbedingt so ablegen möchtest, schachtelt man das lieber Arrays in einem Array und komprimiert das ganze Gebilde. Der Nachteil an eigenen Separatoren ist, dass diese nicht mehr in den Daten vorkommen dürfen. Oder du musst dir was ausdenken, dass es da keine Konflikte gibt. Aber wie gesagt, die ganze Vorgehensweise ist überhaupt nicht empfehlenswert.

    1. Wie kann ich in der invoice.php die Anzahl der eingetragenen Items bestimmen wenn wenn ich bspw. mit Javascript bis zu 10 Artikeleingabefelder auf der invoicing.php abbilden würde?
    <input type='text' name='nameitem1' size='55'>
    <input type='text' name='countitem1' size='10'>
    <input type='text' name='priceitem1' size='10'>
    

    DRY! Don't repeat yourself! Wenn du an einem Feld etwas ändern möchtest, machst du das x-mal. Für sich wiederholende Dinge hat man Schleifen erfunden. Und Arrays statt einzelner Variablen.

    PHP kann mit der Schreibweise ding[] als Feldname umgehen und erzeugt ein Array. Dabei kann man auch den Schlüssel vorgeben ding[key]. Damit kann man dann in einer Schleife die Namen wie folgt vergeben: item[$i][name], item[$i][count], item[$i][price]. Das $i ist deine Schleifenvariable, da muss dann am Ende je Datensatz eine Zahl von 0 bis x drin stehen.

    Und nun schau dir an, was PHP daraus macht. (Vorher ein <pre> ausgeben oder in den Seitenquelltext schauen erhöht die Lesbarkeit): print_r($_POST);

      if($_POST['countitem1'] > 0 [...]){
        $Item1count = $_POST['countitem1'];
        $Item1price = $_POST['priceitem1'];
        $Item1 = serialize(array($Item1name, $Item1count, $Item1price));
    }
    

    Statt hier wieder Wiederholungen eine Schleife:

    foreach ($_POST['item'] as $item) {
        ... serialize($item);
    }
    

    Also vorausgesetzt, du willst unbedingt an dem Serialisieren festhalten. Theoretisch könntest du nun auch gleich mit serialize($_POST['item']) alles in einem Rutsch erledigen, aber du willst sicher die leeren Felder ausklammern. Also würde man die nichtleeren Items erstmal in ein anderes Array legen und am Ende dieses serialisieren.

    $SaveInvoiceDetailQuery = "INSERT INTO invoices (offerid, item1, item2, item3, item4, address) VALUES  ('$OfferID',  '$Item1', '$Item2', '$Item3', '$Item4', '$CustomerString')";
    

    Du hast da ernsthaft einen Datensatz für jeweils bis zu 4 Posten? Nee, mach das weg. Die Wünsche kommen später noch hinzu, da ist ein solches Format, bei dem gleichartige Daten sowohl nebeneinander (in Felder) als auch untereinander (in Zeilen) zu legen kommen ganz ungünstig. Zusätzlich ungünstig zum Serialisieren. Die Rechnung ist bei jedem 4er-Set auch noch mal extra abgelegt?

    Und ganz wichtig ist auch noch der unberücksichtigte Kontextwechsel. Das ist eine der häufigsten Ursachen, warum Unternehmen mit ausnutzbaren Sicherheitslücken in den Nachrichten erwähnt werden. Und warum solche Comics gezeichnet werden: Exploits of a Mom.

    dedlfix.

    1. Hey, herzlichen Dank für eure Antworten. Insbesondere die von dedlfix hat mir sehr weitergeholfen. Mit Ausnahme des Adress-Strings ist das verschachtelte Speichern so wie ich es versucht habe wohl Müll. Ich habe jetzt in jedem Fall einen groben Plan und werde mich gleich nochmal dransetzen etwas daraus zu machen. Die Schleifen waren in jedem Fall ein sehr guter Hinweis.

      Warum legst du die Eigenschaften eines Rechnungspostens nicht separat in Felder und jeden Posten in einem eigenen Datensatz ab?

      Der Grundplan ist nun, an die invoice.php eine RechnungsID zu übergeben, die in der Tabelle invoices die entsprechenden Positionen jeweils mit Name, Menge und Preis anhand dieser Rechnungsnummer nachschlägt und sie dort auflistet.

      Du hast da ernsthaft einen Datensatz für jeweils bis zu 4 Posten? Die Rechnung ist bei jedem 4er-Set auch noch mal extra abgelegt?

      Kennst du den Blick eines Hundes wenn er dir in's Wohnzimmer geschissen hat? So sah ich auch als ich nocheinmal intensiv über meine Herangehensweise nachgedacht hatte.

      Vielleicht muss ich nochmal auf euch zukommen aber aktuell habe ich erstmal einiges um- bzw. neu zu schreiben. Danke und einen schönen Abend euch! cc762