Ik denk dat je het jezelf nogal moeilijk maakt doordat je extra complexiteit toevoegt met een loginsysteem. Daarnaast is een pollsysteem gevoelig voor fraude als je geen gebruik maakt van database-transacties, en hiervoor heb je een relationele database nodig, en hiervoor dien je de tabellen aan te maken met de juiste
database engine.
Laat ik wat codesnippets erbij pakken.
Allereerst dit:
<?php
@session_start();
?>
Op regel 1 ga je al de mist in door "output" te produceren - die twee spaties voor het <
?php blok. Vervolgens onderdruk je op regel 2 eventuele foutmeldingen die bij het starten/voortzetten van een sessie ontstaan. Mogelijk hebben deze twee regels tot gevolg dat de sessie niet succesvol gestart is, dus eigenlijk begin je hier al op de verkeerde voet.
Dan op regel 37 en 42 voer je de volgende twee queries uit:
SELECT * FROM ".$SETTINGS["kandidaat"]
UPDATE ".$SETTINGS["kandidaat"]." SET aantal = aantal+1 WHERE id=".$kandidaat['id']
En dit illustreert het belang van database-transacties.
Op het moment van het opvragen van informatie uit de tabel $SETTINGS['kandidaat'] - ontbreekt hier trouwens niet een argument in de trant van WHERE id = <huidige gebruiker> ofzo? Ik neem aan dat die tabel meerdere records bevat? - op dat moment zouden eigenlijk de gegevens van die tabel vergrendeld moeten worden totdat de mutatie (de UPDATE) afgerond is. Want wat nu als ik dit drie keer snel achter elkaar, en parallel, aanroep? Dan is de volgorde worst case zoiets:
SELECT * FROM <tabel>
SELECT * FROM <tabel>
SELECT * FROM <tabel>
UPDATE <tabel> SET ... WHERE id = <id>
UPDATE <tabel> SET ... WHERE id = <id>
UPDATE <tabel> SET ... WHERE id = <id>
En halverwege worden daar controles uitgevoerd of de UPDATE mag plaatsvinden,
maar op dat moment was alle informatie al binnengehaald nog voordat een andere proces een UPDATE heeft uitgevoerd!
Eigenlijk zouden regel 2 en regel 3 moeten wachten totdat de UPDATE die in wezen geïnitieerd werd in regel 1 klaar is met zijn bijbehorende UPDATE op regel 4 waarna de controles van de tweede en derde SELECT waarschijnlijk falen omdat dan (na afronding van de eerste UPDATE) niet meer voldaan kan worden aan de controles voor de UPDATEs.
Je opzet is ook zodanig dat je niet na kunt gaan wie er dubbel stemt? En als dat hetgene is wat je hierboven hardnekkig probeert te tellen, ook dat is helemaal niet nodig met de juiste voorzieningen.
Een mechanisme die dit waarborgt zijn transacties.
Zoals ik het zie wordt dit pollsysteem in zijn simpelste vorm zoiets (tabeldefinitie):
poll_polls
----------
id
active
name
description
poll_options
------------
id
poll_id
description
order
poll_votes
----------
poll_id
poll_option_id
poll_participants
-----------------
id
email
token
voted
poll_polls - kapstoktabel voor stemrondes
id - een auto_increment id voor unieke identificatie van stemmen
active - geeft aan of de poll "aan" of "uit" staat
name - titel van de poll
description - omschrijving van de poll, hier zou je ook informatie in kunnen zetten als openings- en sluitingsdatum van de poll, waar je later bijvoorbeeld aparte kolommen voor kunt maken
poll_options - bevat de verschillende stemopties voor de polls
id - auto_increment id voor unieke identificatie van de stemoptie
poll_id - de poll waar deze optie bijhoort
description - omschrijving van de optie, bijvoorbeeld de naam van een verkiesbare kandidaat
order - kolom waarmee je de opties een alternatieve sorteervolgorde kunt geven
poll_votes - houdt de stemmen per poll(optie) bij
poll_id - de poll waarop gestemd wordt
poll_option_id - de poll optie waarop gestemd wordt
Aan deze tabel kun je nog veel meer informatie hangen, zoals de datum van stemming en wellicht ook een "witness", dus de persoon die stemde op deze optie; het is dan de verantwoordelijkheid van de beheerder van deze data om deze informatie te strippen op het moment dat deze hierover een rapportage uitbrengt
poll_participants - tabel die minimale informatie bevat van personen die zijn uitgenodigd voor deelname
id - auto_increment id
poll_id - poll waarop je mag stemmen
email - contact e-mail adres
token - activatiecode voor deelname aan stemming
voted - boolean die aangeeft of er gestemd is
Dit is een minimale opzet die alle informatie bevat die je initieel nodig hebt om een eenvoudig pollsysteem te bouwen. Je zult dan dus nog wel op een of andere manier activatiecodes moeten genereren en mailen naar een lijst van gebruikers, maar ook dat is redelijk eenvoudig te bouwen.
Het blijft echter wel zaak dat wat voor aanpak je ook kiest dat er haast een "zero margin for errors" is. Dit is immers een administratief systeem, en het is zaak dat je administratie te allen tijde klopt. Ik denk niet dat dat gaat lukken zonder een opzet met een relationele database of zonder gebruikmaking van eerdergenoemde transacties.