Jag försöker att skapa ett enklare forum, men jag vet inte hur jag får med 'amne_id' till mixtabellen (amne_inlagg).
Just nu har jag bara satt amne_id till '0'.
Detta är koden för att spara ett nytt ämne i databasen:
$amne = db_escape($_POST['amne']);
$av = db_escape($_POST['av']);
$ip = db_escape($_SERVER['REMOTE_ADDR']);
$text = db_escape($_POST['text']);
$fran = db_escape($_POST['fran']);
$sql = "INSERT INTO amnen(
amne,
av,
ip,
datum)
VALUES(
'$amne',
'$av',
'$ip',
NOW())";
mysql_query($sql) or die (mysql_error());
$sql2 = "INSERT INTO inlagg(
text,
av,
ip,
fran,
datum)
VALUES(
'$text',
'$av',
'$ip',
'$fran',
NOW())";
mysql_query($sql2) or die (mysql_error());
$inid = mysql_insert_id();
$sql3 = "INSERT INTO amne_inlagg(
amne_id,
inlagg_id)
VALUES(
'0',
'$inid')";
mysql_query($sql3) or die (mysql_error());
header("Location: posta_amne.php");
}
Tacksam för hjälp.
Uppskattar även tips på hur man kan optimera -och/eller korta ner koden.
Det beror väl på vad amne_id är för något och var vi kan få det ifrån.
Går man in under ett ämne för att skriva ett inlägg, då har du säkert ämnets id i url:en, då kan du spara ned med $_GET i ett "hidden"-input-fält i formuläret för inlägget och skicka med det i postningen av inlägget!
Peter SMedlem sedan dec. 20025 483 inlägg Det finns olika sätt att lösa det på. Ett är att använda samma sätt som du hämtar 'inid' på (om amne_id är ett autonummerfält vill säga). Dock behöver du lägga samtliga dessa operationer i en transaktion, så att du inte riskerar att skapa konstigheter i databasen.
Vilken storage engine använder du?
Peter S skrev:
Det finns olika sätt att lösa det på. Ett är att använda samma sätt som du hämtar 'inid' på (om amne_id är ett autonummerfält vill säga). Dock behöver du lägga samtliga dessa operationer i en transaktion, så att du inte riskerar att skapa konstigheter i databasen.
Vilken storage engine använder du?
Jag använder MyISAM på samtliga tabeller.
Ja, amne_id har "auto_increment".
Löste det såhär:
$amne = db_escape($_POST['amne']);
$av = db_escape($_POST['av']);
$ip = db_escape($_SERVER['REMOTE_ADDR']);
$text = db_escape($_POST['text']);
$fran = db_escape($_POST['fran']);
$sql = "INSERT INTO amnen(
amne,
av,
ip,
datum)
VALUES(
'$amne',
'$av',
'$ip',
NOW())";
mysql_query($sql) or die (mysql_error());
$aid = mysql_insert_id();
$sql2 = "INSERT INTO inlagg(
text,
av,
ip,
fran,
datum)
VALUES(
'$text',
'$av',
'$ip',
'$fran',
NOW())";
mysql_query($sql2) or die (mysql_error());
$inid = mysql_insert_id();
$sql3 = "INSERT INTO amne_inlagg(
amne_id,
inlagg_id)
VALUES(
'$aid',
'$inid')";
mysql_query($sql3) or die (mysql_error());
Finns det ett bättre sätt att lösa detta på?
Peter SMedlem sedan dec. 20025 483 inlägg Ja, du vill ha dem i en transaktion. Men eftersom MyISAM inte gillar det får du använda LOCK TABLES:
lock tables amnen write;
insert into amnen ...
$aid = ...
unlock tables;
lock tables inlagg write;
insert into inlagg ...
$inid = ...
unlock tables;
insert into amne_inlagg ...
Peter S skrev:
Ja, du vill ha dem i en transaktion. Men eftersom MyISAM inte gillar det får du använda LOCK TABLES:
lock tables amnen write;
insert into amnen ...
$aid = ...
unlock tables;
lock tables inlagg write;
insert into inlagg ...
$inid = ...
unlock tables;
insert into amne_inlagg ...
Nu förstår jag ingenting. :r
Varför går det inte att ha det så som jag postade ovan?
För/nackdelar?
Peter SMedlem sedan dec. 20025 483 inlägg Titta på dessa två rader:
$sql = "INSERT INTO amnen(
amne,
av,
ip,
datum)
VALUES(
'$amne',
'$av',
'$ip',
NOW())";
...
$aid = mysql_insert_id();
$aid kommer bara att innehålla korrekt värde om insert_id körs direkt efter INSERT. Men det finns ju faktiskt en möjlighet att det är flera besökare på sidan, och då kan ordningen på frågorna se ut enligt följande:
INSERT INTO //besökare 1
INSERT INTO //besökare 2
$aid = mysql_insert_id() //besökare 1
$aid = mysql_insert_id() //besökare 2
$aid kommer alltså att innehålla samma värde för båda besökarna - det är inte bra.
Hmm, ok...
Hur löser jag då detta på enklaste sätt?
Peter SMedlem sedan dec. 20025 483 inlägg Genom att låsa tabellerna i fråga precis innan skrivning (INSERT) och låsa upp dem igen direkt efter selektering (mysq_insert_id), så hindrar du andra från att skriva till dem under den kritiska tiden. Se inlägg #6.
spangoMedlem sedan juni 20008 205 inlägg
Peter S skrev:
$aid kommer alltså att innehålla samma värde för båda besökarna - det är inte bra.
Nej, det kommer de inte, eftersom last_insert_id fungerar per anslutning.
TypeMedlem sedan mars 20021 239 inlägg hmm. hur är det nu det funkar? Pratar vi mysql_insert_id?
Funkar den per anslutning eller per databas? måste vi låsa tabeller eller ej?
Man vill ju inte gärna missa en sån här grej. det är ju svårt att felsöka...
spangoMedlem sedan juni 20008 205 inlägg PHP-funktionen mysql_insert_id() fungerar på samma sätt som MySQL-funktionen LAST_INSERT_ID() och funkar per anslutning.
TypeMedlem sedan mars 20021 239 inlägg Med andra ord har Peter S fel?
spangoMedlem sedan juni 20008 205 inlägg Ja, angående hur mysql_insert_id funkar. Att låsa tabellerna ger en ganska ond inverkan på skalbarheten, dessutom. Sen stämmer det iofs att du egentligen vill ha dina inserts i en transaktion, om en misslyckas är alla meningslösa, men det kanske varken är sannolikt att någon av dem felar eller dödsviktigt att det funkar klockrent i ett forum (eftersom det bara lär vara under ganska exceptionella omständigheter som några funkar och inte gör det).
Tack för svaret "Spango", misstänkte att det var ok att göra som jag gjorde.
Använder mig av detta:
$amne = db_escape($_POST['amne']);
$av = db_escape($_POST['av']);
$ip = db_escape($_SERVER['REMOTE_ADDR']);
$text = db_escape($_POST['text']);
$fran = db_escape($_POST['fran']);
$sql = "INSERT INTO amnen(
amne,
av,
ip,
datum)
VALUES(
'$amne',
'$av',
'$ip',
NOW())";
mysql_query($sql) or die (mysql_error());
$aid = mysql_insert_id();
$sql2 = "INSERT INTO inlagg(
text,
av,
ip,
fran,
datum)
VALUES(
'$text',
'$av',
'$ip',
'$fran',
NOW())";
mysql_query($sql2) or die (mysql_error());
$inid = mysql_insert_id();
$sql3 = "INSERT INTO amne_inlagg(
amne_id,
inlagg_id)
VALUES(
'$aid',
'$inid')";
mysql_query($sql3) or die (mysql_error());
Går det att korta ner alt. optimera koden ovan?
Tacksam för alla tips/förslag.
Peter SMedlem sedan dec. 20025 483 inlägg Beaten :p
Intressant citat från TFM:
For LAST_INSERT_ID(), the most recently generated ID is maintained in the server on a per-connection basis. It is not changed by another client. It is not even changed if you update another AUTO_INCREMENT column with a non-magic value (that is, a value that is not NULL and not 0). Using LAST_INSERT_ID() and AUTO_INCREMENT columns simultaneously from multiple clients is perfectly valid. Each client will receive the last inserted ID for the last statement that client executed.
spangoMedlem sedan juni 20008 205 inlägg
Guldstrand skrev:
Går det att korta ner alt. optimera koden ovan?
Tacksam för alla tips/förslag.
Tabellen amne_inlagg får mig att fundera lite. Du insertar värdena som strängar när det rimligen borde vara heltal (två ID:n). Sen undrar jag lite varför du öht har den tabellen, alls? Vore det inte vettigare att bara ha ett ämnes-ID i inläggstabellen? Jag misstänker att du inte har ett många-till-många-förhållande mellan ämne och inlägg, så det borde ju räcka med att inläggen pekar på det ämne de är postade i.