fortlaufende Bestellnummern für Onlineshop
bjoern
- php
Hallo Forum.
Bei meinem Onlineshop werden die Bestellungen per Mail versandt. Ich möchte nun bei jeder Mail eine fortlaufende Bestellnummer in den Betreff schreiben lassen.
Meine Frage hierzu wäre, wie ich dies am besten technisch realisiere?
Eine Nummer in einer Datenbank, die immer weiter hochgezählt wird? Oder gibt es eine bessere Möglichkeit? Was ist, wenn zwei Kunden gleichzeitig bestellen? Wie lässt sich hier die Gefahr umgehen, dass beide die Gleiche nummer zugewiesesn bekommen?
Lg Björn
Hi,
Eine Nummer in einer Datenbank, die immer weiter hochgezählt wird? Oder gibt es eine bessere Möglichkeit? Was ist, wenn zwei Kunden gleichzeitig bestellen? Wie lässt sich hier die Gefahr umgehen, dass beide die Gleiche nummer zugewiesesn bekommen?
Ja - am besten in Einer MySQL-Tabelle für jeden Auftrag einen Eintrag eintragen.
Die nächste Nummer lässt sich z.B. feststellen, indem du die Aufträge sortiert nach Auftragsnummer rückwärts ausgeben lässt und dann den ersten nimmst und 1 dazu addierst.
Zwischen dem Auslesen der Nummer und dem speichern der neuen Nummer ließe sich z.B. eine Datei mit PHP für Schreibzugriffe sperren - wenn die gesperrt ist wartet das Programm bis sie wieder öffenbar ist bevor es weitermacht. Du musst ja nichts wirklich in die Datei schreiben sondern kannst sie einfach nutzen, damit PHP das Problem wie oben beschrieben für dich löst.
Es gibt allerdings auch andere Möglichkeiten!
Grüße aus Nürnberg,
Tobias Unger
Hallo Tobias
Speichern eines Eintrages in eine Tabelle mit auto_increment ID. Diese dann mittels mysql_insert_id bestimmen. Auch eine Möglichkeit. Da muss man nicht extra vorher sortieren... ;)
Schönen Gruß
Afra
Vielen Dank für die schnellen antworten.
Ist es nicht auch möglich das gleiche mit einer textdatei zu machen? Zahl in Textdatei und fertig.
Gibt es dabei dann auch die Möglichkeit die txt zu sperren solange eine Person die aktuelle Nummer verwendet bzw. wenn die Datei schon geöffnet ist? Wenn ja, wie und was würde mit dem zweiten Kunden passieren, der eine solche gesperrte DAtei vorfindet?
Gruß Björn
echo $begrüßung;
Gibt es dabei dann auch die Möglichkeit die txt zu sperren solange eine Person die aktuelle Nummer verwendet bzw. wenn die Datei schon geöffnet ist?
Ja, diese Möglichkeit gibt es auch. Dazu muss aber die Webanwendung schreibenden Zugriff auf ein Verzeichnis haben, was meist weniger toll ist. Wenn sowieso schon eine Datenbank vorhanden ist, kann die das gleich mitmachen.
Durch du die Dateivariante holst du dir noch eine weitere Technik in die Anwendung, und hast damit auch wieder eine potentielle Fehlerquelle mehr.
Wenn ja, wie und was würde mit dem zweiten Kunden passieren, der eine solche gesperrte DAtei vorfindet?
Siehe flock() und zahlreiche Postings im Archiv zu diesem Thema.
echo "$verabschiedung $name";
Moin.
Ja, diese Möglichkeit gibt es auch. Dazu muss aber die Webanwendung schreibenden Zugriff auf ein Verzeichnis haben, was meist weniger toll ist. Wenn sowieso schon eine Datenbank vorhanden ist, kann die das gleich mitmachen.
Wenn ich eine Tabelle in einer Datenbank extra hierfür anlege und nur eine Spalte mit einem Datensatz habe der die aktuelle Bestellnummer enthält, wie sperre ich dann die Tabelle während Kunde 1 die Bestellung versendet und was passiert mit Kunde zwei, der ebenfalls im selben Moment bestellen möchte?
Gruß Björn
Hi,
wenn du alles MySQL machen lässt und keine Variablen erst ausliest um sie dann wieder zu speichern kümmert sich MySQL darum und lässt den 2. Nutzer so lange warten, bis der 1. die Nummer hat und das Feld erhöht ist - erst dann kommt der 2. Kunde an die Reihe (da es sich um Sekundenbruchteile handelt sollte das bei einem normalen Onlineshop kein Problem darstellen).
Grüße aus Nürnberg,
Tobias
echo $begrüßung;
wenn du alles MySQL machen lässt und keine Variablen erst ausliest um sie dann wieder zu speichern kümmert sich MySQL darum und lässt den 2. Nutzer so lange warten, bis der 1. die Nummer hat und das Feld erhöht ist - erst dann kommt der 2. Kunde an die Reihe (da es sich um Sekundenbruchteile handelt sollte das bei einem normalen Onlineshop kein Problem darstellen).
Wie kommt Kunde 1 an den gerade erhöhten Wert, ohne ihn mit einem zweiten Statement auszulesen? UPDATE gibt nur die Anzahl der erfolgreich geänderten Datensätze zurück, also immer nur eine 1. auto_increment funktioniert nur bei INSERT, ist also hier unbrauchbar. Wie REPLACE das regelt weiß ich nicht. Um zu garantieren, dass sich niemand zwischen UPDATE und SELECT drängelt, bleibt nur, so schätze ich, LOCK TABLES, UPDATE, SELECT, UNLOCK TABLES.
echo "$verabschiedung $name";
echo $begrüßung;
wenn du alles MySQL machen lässt und keine Variablen erst ausliest um sie dann wieder zu speichern kümmert sich MySQL darum und lässt den 2. Nutzer so lange warten, bis der 1. die Nummer hat und das Feld erhöht ist - erst dann kommt der 2. Kunde an die Reihe (da es sich um Sekundenbruchteile handelt sollte das bei einem normalen Onlineshop kein Problem darstellen).
Wie kommt Kunde 1 an den gerade erhöhten Wert, ohne ihn mit einem zweiten Statement auszulesen? UPDATE gibt nur die Anzahl der erfolgreich geänderten Datensätze zurück, also immer nur eine 1. auto_increment funktioniert nur bei INSERT, ist also hier unbrauchbar. Wie REPLACE das regelt weiß ich nicht. Um zu garantieren, dass sich niemand zwischen UPDATE und SELECT drängelt, bleibt nur, so schätze ich, LOCK TABLES, UPDATE, SELECT, UNLOCK TABLES.
echo "$verabschiedung $name";
Ganz einfach, indem du bei der Erstellung der Seite für den Benutzer (er ruft die Seite auf) in einem hiddenfield zum Beispiel die aktuelle Zeit speicherst (mit "mktime()") und abfragst.
Besser:
Es wird im Insertbefehl direkt die BenutzerID gespeichert (In einer zweiten Tabelle) und bei der Abfrage, die Zeile ausgelesen welche die größte auto_increment ID hat. (Also der letzte Eintrag)
echo $begrüßung;
Ganz einfach, indem du bei der Erstellung der Seite für den Benutzer (er ruft die Seite auf) in einem hiddenfield zum Beispiel die aktuelle Zeit speicherst (mit "mktime()") und abfragst.
Hier verstehe ich nicht, worauf du hinaus willst.
Es wird im Insertbefehl direkt die BenutzerID gespeichert (In einer zweiten Tabelle) und bei der Abfrage, die Zeile ausgelesen welche die größte auto_increment ID hat. (Also der letzte Eintrag)
Hier eigentlich auch nicht, aber ich versuche es mal.
bjoern hat nicht erwähnt, welche Datenbank ihm zur Verfügung steht. Ich kann also nicht mit Gewissheit sagen, welche Datenbanklösung die für ihn geeignete darstellt. Gehen wir mal von MySQL aus, so wäre die einfachste Variante eine auto_increment-Spalte. Beim Insert wird automatisch ein Wert vergeben, der mit LAST_INSERT_ID() abgefragt werden kann. Da diese Funktion verbindungsabhängig arbeitet, und man davon ausgeht, dass sich nicht zwei Anwendungen die gleiche Verbindung teilen, ist das die ungefährlichste Methode. Ein zwischen INSERT und Abfrage der LAST_INSERT_ID() in einer anderen Verbindung eingefügter Datensatz beeinflusst das Ergebnis von LAST_INSERT_ID() nicht.
Steht einem dieser Mechanismus nicht zur Verfügung, und man hat eine Datenbank, die Sequenzen unterstützt, dann wäre dies meiner Meinung nach das beste Mittel der Wahl. Die Sequenz liefert jeweils einen individuellen Wert, den man beliebig verwenden kann und der anderen auch nicht in die Quere kommt.
Ansonsten kann man sich einen eigenen Mechanismus implementieren. Dazu kann man entweder zuerst den aktuellen Wert auslesen und danach hochzählen oder man zählt zuerst hoch und liest dann aus. In beiden Fälle muss man jedoch dafür Sorge tragen, dass zwischen den beiden Vorgängen weder Lese- noch Schreibzugriffe von anderen Anwendungen auf den Wert stattfinden, weil es sonst zu doppelt vergebenen Werten kommt. Wenn sich diese beiden Vorgänge zu einem einzigen, atomaren, ununterbrechbaren Vorgang zusammenfassen lassen, und damit ein Sperrmechanismus überflüssig wird, sollte man das tun.
Das Einfügen eines Datensatzes und anschließendes Auslesen eines Maximalwertes, von dem man annimmt, es sei der Wert des eben einfügten Datensatzes fällt unter das gleiche Szenario.
echo "$verabschiedung $name";
Hi,
Eine Nummer in einer Datenbank, die immer weiter hochgezählt wird? Oder gibt es eine bessere Möglichkeit? Was ist, wenn zwei Kunden gleichzeitig bestellen? Wie lässt sich hier die Gefahr umgehen, dass beide die Gleiche nummer zugewiesesn bekommen?
Ja - am besten in Einer MySQL-Tabelle für jeden Auftrag einen Eintrag eintragen.
Die nächste Nummer lässt sich z.B. feststellen, indem du die Aufträge sortiert nach Auftragsnummer rückwärts ausgeben lässt und dann den ersten nimmst und 1 dazu addierst.
Das kann MySql selber.. einfach nen Primary Key erstellen und auf auto_increment setzen.
Beispiel:
Tabelle d1000Kunden
Spalte1: ID1000 als Primary Key und auto_increment
Spalte2: Name
usw usw
ID1000 wird automatisch hochgezählt.
Tabelle d2000Auftrag
Spalte1: ID2000 als Primary Key und auto_increment
Spalte2: ID1000 (z.b. als BIGINT)
Spalte3: Datum als Datetime
usw usw
der Vorteil in der Konstruktion.. Bestellungen sind einfach einem Kunden zuzuordnen:
(SELECT ID2000, Datum usw FROM d2000Auftrag WHERE ID1000=(SELECT ID1000 FROM d1000Kunden WHERE Name=... usw))
Ausserdem wird die Datenbank kleiner gehalten, als bei jedem Bestellvorgang die Kundendaten zu speichern.
echo $begrüßung;
Eine Nummer in einer Datenbank, die immer weiter hochgezählt wird? Oder gibt es eine bessere Möglichkeit?
Das kommt darauf an, welche Datenbank du verwendest. Manche kennen Sequenzen, manche nicht. Andere kennen auto_increment-Spalten. Was aber immer gehen sollte, ist eine Tabelle mit nur einer Zeile und mindestend einer Spalte, deren Wert durch ein entsprechendes Update-Statement hochgezählt wird. (Die restlichen Spalten lassen sich z.B. für andere Konfigurationswerte verwenden.)
Was ist, wenn zwei Kunden gleichzeitig bestellen? Wie lässt sich hier die Gefahr umgehen, dass beide die Gleiche nummer zugewiesesn bekommen?
Bei Sequenzen und auto_increments sollte das nicht nötig sein. Ansonsten musst du halt die Tabelle während der Änderung sperren (Locking).
echo "$verabschiedung $name";