Data opslaan in mysql db vanuit aanpassing PHPGrid.

Status
Niet open voor verdere reacties.

BZilla

Gebruiker
Lid geworden
16 apr 2014
Berichten
170
Beste allen,

Ik heb voor mijn project PHPGrid aangeschaft. Dit is een tool die een tabel bevat.
Je kan ermee exporteren naar excel, tabellen wijzigen en dit wordt dan opgeslagen in de database.

Ook heb ik, bij elke tabel die ik maak, een log tabel.
Ik wil bij elke aanpassing die er gedaan wordt, dat de naam van de aanpasser, de oude waarde, de nieuwe waarde, en de datum+tijd wordt opgeslagen in die log tabel.

Dus, stel ik heb een tabel genaamd test.
dan heb ik ook een tabel genaamd test_logs.

Als ik een aapassing maar in test, moet er in test_logs het onderstaande komen.

Username || oudeWaarde || nieuweWaarde || datumTijd
BZilla ------ Waarde123 ------ waarde321 ---- 2014-05-19 09:23:30

Iemand enig idee? alvast bedankt!

Bzilla
 
Hieruit zet ik de eerste keer de waarde, hoe dit gebeurd wanneer ik een aanpassing maak, geen idee helaas..
PHP:
function sheetData($sheet)
{
	// fill all the rows with data from the excel sheet.
	$fileName = $_POST['name'];
	$x = 2;                                 
	$query = "INSERT INTO `". $fileName ."` VALUES ";
	$values = array();
	array_shift($sheet['cells']);
	foreach($sheet['cells'] AS $row) 
	{
		$rowValues = "(0";
		for($i = 1; $i <= $sheet['numCols']; $i++) 
		{
			if(!isset($row[$i])) 
			{
				$rowValues .= ", NULL";
			} 
			else 
			{
				$rowValues .= sprintf(", \"%s\"", $row[$i]);
			}
		}
		$values[] = $rowValues .")";
	}
	$query .= implode(", ", $values) .";";
	 
	$result = mysql_query($query);
	if($result == FALSE) 
	{
		die('Error: '. mysql_error());
	} 
	else 
	{
		//reload the page index.php when the function is done.
		Header("Location: index.php");
	}
}	

sheetData($excel->sheets[0]);

Van dat Trigger snap ik niet heel veel.. De @iUserId (die er in het voorbeeld gebruikt wordt) is dus de colum name?
OLD.LastChangedBy is dus de oude waarde en NEW.LastChangedBy de nieuwe?
Voor de rest is het nog allemaal vrij onduidelijk bij mij, hopelijk is dit een begin en kun je mij opweg helpen haha
 
Ik refereer naar je *_logs tabel. Je slaat alleen op wie de aanpassing wanneer heeft gedaan en wat de oude waarde was en de nieuwe waarde. Maar wat stelt die waarde voor? Meestal heeft een tabel meerdere velden dus van welk veld komen die nieuwe en oude waarde? ;)

@iUserId is een variabele welke op de eerste regel gedefineerd wordt maar is niet waar ik naar refereer.
Het gaat voornamelijk om de laatste reactie:
[sql]
CREATE TRIGGER upd_check AFTER UPDATE ON SomeTable
FOR EACH ROW
BEGIN
IF (OLD.LastChangedBy <> NEW.LastChangedBy) THEN
INSERT INTO AuditSomeTable(ID, LastChangedBy)
VALUES (OLD.ID, OLD.LastChangedBy);
END IF;
END;
[/sql]
NEW en OLD zijn constanten binnen MySQL welke de nieuwe en oude tabel voorstellen.

Stel je hebt een tabel "mensen" en je veranderd het veld voornaam van user X van "Piet" naar "Kees" dan zal in NEW.voornaam "Kees" staan en in OLD.voornaam "Piet".
 
Oke duidelijk.

Inderdaad, ik heb meerdere velden, en hij moet het per veld opslaan.
Dus stel ik heb een tabel die heet Test en dus ook een die heet Test_logs met in Test:

Veldnaam || veldnaam1 || veldnaam2
Waarde --- Waarde1 ---- Waarde2

En ik verander dat in :
Veldnaam || veldnaam1 || veldnaam2
VERANDER --- Waarde1 ---- Waarde2

Dan is die query genoeg om de oude en nieuwe waarde in de tabel te zetten, van alleen dat specifieke veld wat aanpast is?

[sql]CREATE TRIGGER upd_check AFTER UPDATE ON Test
FOR EACH ROW
BEGIN
IF (OLD.Waarde<> NEW.Waarde) THEN
INSERT INTO Test(Waarde)
VALUES (OLD.Waarde);
END IF;
END;[/sql]
 
Laatst bewerkt:
Even zoeken leerde mij dat het niet zo eenvoudig is de huidige kolom te pakken te krijgen dus de referentie naar de kolom moet je door middel van IF-statements oplossen.

Hier staat een voorbeeld.

Een alternatief is de volledige rij te kopieren naar je *_logs-tabel met een extra kolom met de datum waarop de wijziging heeft plaatsgevonden (en eventueel wie de wijziging heeft gedaan).
 
Wellicht dat de gehele rij ook wel goed is nu je het zo uitlegd, aangezien ik met PHPGrid de gehele rij kan aanpassen, vervolgens op enter druk, en dan wordt die rij aangepast.
In dit geval is dus wat ik in mijn vorige post doe goed?

En ook toevallig enig idee hoe ik dit doe na het drukken van enter?
 
Als er bij elke wijziging een query uitgevoerd wordt dan krijg je dus voor elke aanpassing apart een volledig nieuwe rij in je *_logs tabel. Dat is niet efficiënt, dan moet je er voor zorgen dat het na een klik op een knop doorgevoerd wordt..

Triggers wordt automatisch uitgevoerd op database-niveau, die hebben geen actie nodig.
 
Dus, alles wat ik hoef te doen is de code neerzetten, en dan zou hij reageren op enter?
Ik ga dit eerst doen, en daarna kijken voor die button, dat ligt volledig aan of dit aan de eisen gaat voldoen. iig bedankt voor alle opties.

dit moet ik dus doen?
PHP:
$query = ('CREATE TRIGGER upd_check AFTER UPDATE ON '.$tablename);
FOR EACH ROW
BEGIN;
   IF (OLD.Waarde<> NEW.Waarde) 
   THEN
	 $guery1 = ('INSERT INTO '.$tablename.'(Waarde) 
	 VALUES ('.$name.', OLD.Waarde, NEW.waarde,'.$date);
   END IF;
END;
 
Nee, die query moet je eenmalig op je MySQL server uitvoeren, niet via PHP :)

Je kunt het ook via phpMyAdmin invoeren door middel van het SQL-tabblad
[sql]
CREATE TRIGGER upd_check AFTER UPDATE ON test
FOR EACH ROW
BEGIN
IF (OLD.Waarde<> NEW.Waarde) THEN
INSERT INTO test_logs(Waarde, date)
VALUES (OLD.Waarde, NOW());
END IF;
END;
[/sql]
Let op: Hiermee worden dus alleen wijzigingen op de kolom "Waarde" bijgehouden.
 
Oke maar hoe moet ik dit dan automatiseren?
Ik weet uiteraard niet in welke tabel, en in welke kolom de gebruiker de wijziging gaat doen.

edit:

En kun je in een query ook zeggen dat hierbij de username en de datum+tijd moet worden toegevoegd?
 
Het wordt geautomatiseerd via MySQL. Elke keer als de tabel geüpdatet wordt zal MySQL de trigger uitvoeren.

Je moet dus op elke tabel zo'n trigger zetten wil je alles bijhouden.

Als je bij de tabel in een kolom bijhoudt wie de laatste wijziging heeft gedaan kun je die via NEW meenemen in je trigger. De datum en tijd worden in mijn voorbeeld al meegenomen via de MySQL functie "NOW()" :)

Afhankelijk van je kennis zou je er ook voor kunnen kiezen om een ORM-pakket zoals Doctrine te implementeren. Deze heeft een extensie waarbij het gedrag dat je zoekt eenvoudig te realiseren is: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/loggable.md
 
Ik ben het aan het proberen in een kleine test omgeving maar blijf een error houden, enig idee?

PHP:
CREATE TRIGGER upd_check AFTER UPDATE ON kees
    FOR EACH ROW
    BEGIN
       IF (OLD.Test1 <> NEW.Test1) THEN
         INSERT INTO `kees_logs`(oudeWaarde, nieuweWaarde, datumTijd) 
         VALUES (OLD.Test1, NEW.Test1, NOW());
       END IF;
    END;

Ik heb meerdere kolommen :
id
username
oudeWaarde
nieuweWaarde
datumTijd

Hierbij is ID auto increment, en username sla ik even over.
En uit de melding kom ik niet echt verder..

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 6
 
Ik heb gemerkt dat dat met de delimiter te maken heeft (het scheidingsteken tussen queries)

Deze fiddle werkt: http://sqlfiddle.com/#!2/f672b/1
[sql]
DELIMITER GO

CREATE TABLE kees
(
id int auto_increment primary key,
firstName varchar(20)
)
GO

CREATE TABLE kees_logs
(
id int auto_increment primary key,
username varchar(20) default null,
oudeWaarde varchar(100),
nieuweWaarde varchar(100),
datumTijd datetime
)
GO

CREATE TRIGGER upd_check AFTER UPDATE ON kees
FOR EACH ROW
BEGIN
IF OLD.firstName <> NEW.firstName THEN
INSERT INTO kees_logs (oudeWaarde, nieuweWaarde, datumTijd)
VALUES (OLD.firstName, NEW.firstName, NOW());
END IF;
END;
GO

INSERT INTO kees VALUES
(1, 'Piet'),
(2, 'Kees')
GO

UPDATE kees SET firstName = 'Fred' WHERE id = 1 GO[/sql]
 
Nog een probleempje..
Omdat ik alles moet gaan gebruiken, heb ik elke column name nodig. enig idee hoe ik dit hier uit krijg?
Aangezien ik geen php in de sql mag neerzetten?

Hieruit pak ik de columnnames uit de excel sheets.

PHP:
$y = 1;
$strsql = "CREATE TABLE  `".$fileName."` (id int(10) NOT NULL AUTO_INCREMENT";
while($y <= $sheet['numCols'])
{
	$x = 1;
	$cell = $sheet["cells"][$x][$y];
	$re .= $cell;
	$data = array($cell);
	$x++;
	$strsql .= ", `".$data[0]."` VARCHAR(1000)";
	$y++;
}
$strsql .= ', KEY(id))';
$resultTable = mysql_query($strsql);
 
Dynamisch een tabel laten genereren lijkt mij niet heel verstandig maar goed daar gaat de vraag niet over :)

Je zult dus ook dan de trigger dynamisch moeten maken, voor elke kolom dit stukje aanmaken:
[sql]
IF OLD.firstName <> NEW.firstName THEN
INSERT INTO kees_logs (oudeWaarde, nieuweWaarde, datumTijd)
VALUES (OLD.firstName, NEW.firstName, NOW());
END IF;
[/sql]
Waarbij je dus "firstName" vervangt door de betreffende kolom

Heeft een tabel 3 kolommen dan krijg je binnen de FOR EACH ROW dus 3x deze regels met de verschillende kolommen.
 
Ja klopt, sorry ik was niet duidelijk genoeg.

Ik maak een log tabel aan, en een tabel met alle waardes.
Direct daarna wil ik de trigger uitvoeren, dus kortom ik weet dan nog niet wat de colom namen zijn, die moet ik op een of andere manier zien op te halen..
maar hoe..
 
Als je een tabel aanmaakt moet je ook de trigger voor die tabel aanmaken.

Dus eerst voer je de query uit om de tabel aan te maken, wanneer die is uitgevoerd laat je de query uitvoeren die de trigger op die tabel maakt.

Maar zoals gezegd, door dynamische tabellen te hebben wordt het allemaal redelijk complex en lastig te onderhouden.

In dit geval is een trigger waarschijnlijk niet meer handig en kun je denk ik beter bij de UPDATE een INSERT query op je log-tabel uit laten voeren.
 
En hoe ga ik te werk met update en insert?
Me eerste project met MySQL.. vandaar..
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan