Logging.
Ik ben bezig om zelf een 'simpele' CMS te schrijven voor 2 projecten die ik nu heb. Het moet de bedoeling zijn dat dit CMS uiteraard uitgebreid wordt naarmate er de tijd voor is. Het CMS moet nu een aantal simpele taken kunnen doen.
- Een artikel aanmaken
- Een artikel bewerken
- een artikel verwijderen
- WYSIWYG editor voor dit alles (genoeg opensrouce versies beschikbaar)
- Loggen wie er wat doet.
Nu heb ik de eerste 4 punten wel onder de knie, echter wil ik een logging systeem maken waar er bijgehouden wordt wie er wat doet.
Ik
- IP adres van de gebruiker (makkelijk via $_SERVER['REMOTE_ADDR'] lijkt me)
- Welk bericht hij heeft aangemaakt, bewerkt of verwijderd
- Het tijdstip waarop dit is gebeurd
Mijn idee lijkt het om deze informatie in een nieuwe tabel te zetten, voor get gemak even logging gemoemt. Ik heb hier dus het ID van de gebruiker uit het tabel 'users' nodig, waaraan ik deze info koppel.
Mijn vraag is eigenlijk, heeft iemand enig idee hoe dit slim aangepakt kan worden? Het IP adres, datum en ID is geen probleem, echter hoe ik kan zien wat hij nu aangemaakt, bewerkt of verwijderd heeft ligt me wat moeilijker.
Kan ik dit gewoon na een van die drie acties een mysql_affected_rows() gebruiken? Maar hoe kan ik nu zien of er een UPDATE, INSERT of DELETE is uitgevoerd?
Alvast hartelijk dank voor de input.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?
switch($actie){
case 'insert':
//insert code hier
$log = 'insert';
break;
case 'update':
//update code hier
$log = 'update';
break;
case 'delete':
//deletecode hier
$log = 'delete';
break;
}
// en dan maak je hier een functie of iets van
loggin($_SESSION['id'], $artikel_id, $log); //(er bestaat al een php functie log ;p)
?>
switch($actie){
case 'insert':
//insert code hier
$log = 'insert';
break;
case 'update':
//update code hier
$log = 'update';
break;
case 'delete':
//deletecode hier
$log = 'delete';
break;
}
// en dan maak je hier een functie of iets van
loggin($_SESSION['id'], $artikel_id, $log); //(er bestaat al een php functie log ;p)
?>
Gewijzigd op 10/05/2012 08:24:03 door gerhard l
Ik neem aan dat je de code niet in je switch statement zet!? Als ik een swtich gebruik zet ik waar jij //.... code hier neerzet, zet ik bijv insertArticle(); waar ik na de switch de functie insertArticle(); maak.
Maar dank je voor het idee, ik had hier nog niet aan gedacht. Echter een snelle vraag, kan ik de waarde van de switch ($actie in dit geval) ook zonder $_GET doorgeven?
Chris, soms doe ik het wel, maar wat jij doet is wel wat overzichtelijker. Je laatste vraag begrijp ik niet helemaal, het kan wel zonder $_GET maar hoe weet jij dan wat er gebeuren gaat(insert, update of delete), ik doe het zelf ook wel eens via $_POST icm een formulier.
Ja ik vind het wat overzichterlijker, echter heeft iedereen zijn eigen schrijfstyle :D. Er is niet echt een goed of fout want beide werkt namelijk, het is net wat je persoonlijk makkelijker en overzichtelijker vind.
Nou ik zat wat simpeler te denken, aangezien ik voor elke 'actie' een eigen pagina/script ga maken. Ik zelf zat eraan te denken om in het script van bijvoordbeeld INSERT te zetten dat als de query met succes is gedaan er in een array $log het volgende te zetten.
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$log = [
"actie" => "toevoegen",
"IP" => "$_SERVER['REMOTE_ADDR']",
"succes" => "Ja"];
?>
$log = [
"actie" => "toevoegen",
"IP" => "$_SERVER['REMOTE_ADDR']",
"succes" => "Ja"];
?>
En als de query niet goed gegaan is.
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$log = [
"actie" => "toevoegen",
"IP" => "$_SERVER['REMOTE_ADDR']",
"succes" => "Nee"];
?>
$log = [
"actie" => "toevoegen",
"IP" => "$_SERVER['REMOTE_ADDR']",
"succes" => "Nee"];
?>
Dus zodra de INSERT query is afgerond, kan ik nogmaals een INSERT maken waar ik simpelweg de gegevens van de $log in de tabel logging zet.
Gewijzigd op 10/05/2012 08:40:12 door Chris PHP
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mysql_query("
INSERT INTO log (
artikel_id,
user_id,
ip,
date,
actie,
success
)
VALUES(
'".mysql_real_Escape_string($id)."',
'".mysql_real_Escape_string($_SESSION['id'])."',
'".mysql_real_Escape_string($_SERVER['REMOTE_ADDR'])."',
now(),
'toevoegen',
'ja'
)"
);
INSERT INTO log (
artikel_id,
user_id,
ip,
date,
actie,
success
)
VALUES(
'".mysql_real_Escape_string($id)."',
'".mysql_real_Escape_string($_SESSION['id'])."',
'".mysql_real_Escape_string($_SERVER['REMOTE_ADDR'])."',
now(),
'toevoegen',
'ja'
)"
);
Gewijzigd op 10/05/2012 08:43:39 door gerhard l
Ja ik ga even kijken of een 'logging' functie te doen is. Echter als ik gewoon direct zo de query doe, moet ik er 2 maken. Ik vind dan dat mijn code te vol wordt aangezien het makkelijker kan door gewoon 1 query en een array te gebruiken.
Want ik moet dan een INSERT INTO maken zoals jou voorbeeld voor een succes ja, en weer een nieuwe als het fout is gegaan (dus een nee). Vandaar dat ik zelf aan de array dacht, dit scheelt weer een hoop regels in het script :D
Maar zoiezo hardstikke bedankt voor het meedenken!
Graag gedaan, dit kan je trouwens gewoon oplossen met een variabele he, query succes $var = 'ja'; anders $var='nee' en zoiets zet je dan weer in je query.
Gerhard l op 10/05/2012 08:52:59:
Graag gedaan, dit kan je trouwens gewoon oplossen met een variabele he, query succes $var = 'ja'; anders $var='nee' en zoiets zet je dan weer in je query.
Klopt dit kan inderdaad ook met een variabel, maar dan geef ik persoonlijk de voorkeur om gelijk al deze informatie in een array te zetten.
Toevoeging op 10/05/2012 10:38:18:
Wat ik me net bedenk is dat ik alleen aan het artikel_id niet genoeg heb. Uiteraard werkt dit goed met een INSERT of een UPDATE, echter bij een DELETE zal het ID wegzijn en kan ik dus nooit meer zien wat het artikel was alleen een ID.
Wellicht verstandig om de titel en summary er ook bij te vermelden niet?
Of je verwijdert het artikel door een flag kolom toe te voegen, deze kan je dan op 0/1 zetten. Op deze manier kan je bijvoorbeeld het verwijderen van een artikel ongedaan maken.
Echter als de gebruiker hem delete zou hem wel helemaal weg moeten zijn. Anders zou het betekenen dat de gebruiker nooit daadwerkelijk een artikel weg zou kunnen gooien.
De logging is trouwens puur voor de admin/webdesigner en niet voor de gebruiker. Aangezien schuld afschuiven op de ontwerper snel gedaan wordt, kun je dus doormiddel van deze log precies zien wie en wat er gebeurt is.
Tevens door misschien een het artikel te 'moven' van de artikel tabel naar een deleted_artikel tabel, kun je eventuele verwijderde artikelen altijd nog 'recoveren'.
Iemand enig idee of er een 'move' statment is of moet het gedaan worden in een script?
Maar wat is de toegevoegde waarde van een andere tabel? Door gebruik van flags kan je eveneens filteren op verwijderde berichten en ze restoren. Juist omdat je zegt dat het alleen voor de admin is lijkt me dit een nuttige feature.
DELETE FROM artikelen WHERE deleted=1
Met een simpel SQL statament kan je een record uit de ene naar de andere tabel plaatsen, hierna moet je het nog wel deleten uit de artikelen tabel:
Code (php)
1
2
3
4
2
3
4
INSERT deleted_artikel (id, title, content)
SELECT id, title, content
FROM artikelen
WHERE id = 1
SELECT id, title, content
FROM artikelen
WHERE id = 1
Let op: hier gebruik je dus INSERT en niet INSERT INTO (maw, ik ben niet een keyword vergeten...).
De volgorde van de kolommen in INSERT en SELECT bepaalt welke waarde in welke kolom terecht komt. Ga er dus niet vanuit dat het op naam gebeurt, het gaat op volgorde.
Mocht je overigens nog een extra waarde willen toevoegen, bijvoorbeeld de user_id van de gebruiker die het artikel weggooit dan kan dat ook (57190 is dus het fictieve id):
Code (php)
1
2
3
4
2
3
4
INSERT deleted_artikel (id, title, content, user_id)
SELECT id, title, content, 57190
FROM artikelen
WHERE id = 1
SELECT id, title, content, 57190
FROM artikelen
WHERE id = 1
Gewijzigd op 10/05/2012 11:14:27 door Erwin H
Echter zou ik toch voor de manier van Erwin (en mijn originele manier) gaan puur dat de artikel database schoon blijft en alleen artikelen bevat die op de site mogen.
de deleted_artikel is puur als mijn klant een fout maakt en het per ongeluk verwijderd, zodat ik het zelf alsnog kan recoveren voor hem. Dus de deleted_artikel is meer een parkeerplaats voor artikelen die de gebruiker niet meer wil.
Erwin, ik kan als ik je voorbeeld dus goed begrijp dit maken.
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$move = ("INSERT deleted_artikel (id, title, content)
SELECT id, title, content
FROM artikelen WHERE a_id='$a_id'")
$delete = ("DELETE * FROM artikel WHERE a_id='$a_id'")
?>
$move = ("INSERT deleted_artikel (id, title, content)
SELECT id, title, content
FROM artikelen WHERE a_id='$a_id'")
$delete = ("DELETE * FROM artikel WHERE a_id='$a_id'")
?>
En dan uiteraard een if statment maken dat if ($_POST['delete'] == 1) dus de checkbox delete is gemarkeerd voer ik beide queries uit, eerst de $move en daarna de $delete?
Toevoeging: ik heb nu de kolommen dezelfde naam gegeven in de originele tabel en de deleted tabel, dat hoeft natuurlijk niet. Die namen kunnen vanalles zijn.
Klopt je kunt er idd van maken wat je wilt, maar om het 1-op-1 aan te houden met het originele klinkt alleen maar logisch in dit geval :D
Dit is natuurlijk ook een hele mooie oplossing als je ooit gaat mirgeren naar een nieuwe of andere database structuur!
Dank je voor de tip, ik ga er vanavond mee aan de slag.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$logboek = date('Y-m-d H:i:s').' SUCCES: '.$_SERVER['REMOTE_ADDR'].' - gebruiker ingelogd - User: '.$_SESSION['naam'];
// VERWERKEN in security logboek
$logbestand = "/home/gebruiker/domains/domein.nl/logboek/log_security.txt";
if($handle = fopen($logbestand, 'a')) {
fwrite($handle,"$logboek");
fwrite($handle,"\n");
fclose($handle); //bestand afsluiten
}
?>
$logboek = date('Y-m-d H:i:s').' SUCCES: '.$_SERVER['REMOTE_ADDR'].' - gebruiker ingelogd - User: '.$_SESSION['naam'];
// VERWERKEN in security logboek
$logbestand = "/home/gebruiker/domains/domein.nl/logboek/log_security.txt";
if($handle = fopen($logbestand, 'a')) {
fwrite($handle,"$logboek");
fwrite($handle,"\n");
fclose($handle); //bestand afsluiten
}
?>
Als je zelf de site gebruikt werkt dat goed, echter wanneer er mensen achterzitten die er niets vanaf weten gebruik ik liever geen logbestand.
Mijn klanten hebben natuurlijk ook zelf toegang tot hun FTP, en ja ik heb al een aantal keren meegemaakt dat ze onopzettelijk hun hele root leeg gooien. Dan heb je klanten die dit netjes melden en toegeven, echter zijn er ook die regelrecht de schuld in jou schoenen schuiven.
Vandaar dat ik dit het liefst in een database wil opslaan. Tevens bewaar ik al de site's van mijn klanten die ik ontworpen heb, zodat dit soort dingen snel op te lossen zijn. Nog een voordeel om een database te gebruiken, deze gegevens gaan minder snel verloren dan bestanden.
Maar bedankt voor je input, logbestanden hebben in verschillende situaties zeker nut!
Dank je, ik zit er inderdaad aan te denken om dit in OOP te maken. Echter heb ik OOP nog niet zovaak toegepast dus wordt gelijk een mooie uitdaging.
Dank je voor de link, deze pak ik er vanavond even bij!