5: Stemmen

Een peiling zonder stemmen is een lijst. In dit hoofdstuk wordt elke optie een formulier, ontvangt een POST route de stem, gaat de telling omhoog, en een omleiding her-render de pagina. Gewone HTTP, nog geen JavaScript: deze versie werkt in elke browser, met alles uit.

5.1: De stemformulieren

In poll.phlo, verander elke knop in de choices view in een klein formulier:

view choices:
<section.card>
<foreach type_poll::records() AS $option>
    <form method=post action="/poll/vote/$option->id">
        <button>$option->option</button>
    </form>
</foreach>
</section>

Elk formulier verstuurt naar zijn eigen URL: /poll/vote/1, /poll/vote/2, enzovoort. De id reist in het pad, dus het formulier heeft geen verborgen velden nodig. Let op de aanhalingstekens rond de action waarde: attributen die variabelen of schuine strepen bevatten, moeten tussen aanhalingstekens staan. De form: display: inline regel uit hoofdstuk 3 houdt de knoppen op één rij.

Herlaad http://localhost/poll: het ziet er identiek uit, maar elke knop verstuurt nu een formulier. Op een klik verschijnt er een 404, omdat de route nog niet bestaat.

5.2: De POST route

Voeg de route toe aan poll.phlo, nabij de GET-route:

route POST poll vote $id {
    if (!$option = type_poll::record(id: (int)$id)) return false
    type_poll::change('id=?', (int)$id, votes: $option->votes + 1)
    location('/poll')
}

Lees het van boven naar beneden:

Herlaad en klik op Phlo. De pagina herlaadt, de telling leest 1, en de balk springt naar 100%. Klik op een andere optie en kijk hoe de percentages zich herverdelen. Controleer data/poll.json om de stemmen op schijf te zien.

5.3: Een payload in plaats daarvan lezen

De id in het pad is één stijl. De andere is een request body, die je leest via %payload. Schakel eerst de resource in data/app.json in:

{
    "resources": [
        "DB/DB",
        "DB/model",
        "DB/JSONDB",
        "DB/JSON.result",
        "payload"
    ]
}

Een payload-gebaseerde versie van dezelfde route ziet er als volgt uit:

route POST poll vote @option {
    $id = (int)%payload->option
    if (!$option = type_poll::record(id: $id)) return false
    type_poll::change('id=?', $id, votes: $option->votes + 1)
    location('/poll')
}

@option valideert de request body: de payload moet precies de sleutel option bevatten, anders komt de route niet overeen. Body-sleutels worden nooit als parameters gebonden; je leest ze via %payload->option. De bijbehorende vorm zou één formulier zijn met <button name=option value="$option->id"> per keuze.

Beide stijlen zijn idiomatisch. Houd de $id variant uit X.2 voor deze tutorial; het maakt een soepele overgang naar de async versie.

5.4: Wat je nu hebt

Voer de controles nogmaals uit:

php www/app.php build::run
php www/app.php build::lint

Beide eindigen op []. Je hebt een complete, werkende poll: server-gerenderd, refresh-veilig, nul JavaScript. Stem een paar keer, kijk hoe data/poll.json verandert, en merk het ene ding op dat nog steeds als 2004 aanvoelt: de volledige pagina herlaad bij elke stem. Dat is het volgende hoofdstuk.

We gebruiken essentiële cookies om deze site te laten werken. Met uw toestemming gebruiken we ook analytics om de site te verbeteren.