Centrala gränsvärdessatsen

Äntligen en ny vecka! Jag har kommit ut på andra sidan av denna helg där jag mest suttit och slipat på Bokarenan. Jag kände att jag hade den tiden över efter att ha gjort en del plugg under den gångna veckan. Mycket tid har gått åt att slipa på CSS och skapa rimliga views (sidor) för de entiteter jag vill presentera. Jag har upplevt det som enklare att ha koll på vad jag skapar och var jag har det, nu när jag skapar mina views manuellt, istället för att låta Symfony skapa dem åt mig. De views som Symfony skapade var i klass med att sitta med phpMyAdmin, men mer begränsad. Så de färdigbakade sidorna motsvarade inte de syften jag hade med dem. Och jag börjar gilla vart åt det barkar.

För närvarande ser sidan ut som nedan. Jag har avvikit lite från hur jag hade skissat den i Adobe XD och gjort den generellt lite ljusare.

Men nog om programmeringen. Denna vecka fortsätter jag med statistik. Denna gång om centrala gränsvärdessatsen.

I förra veckan beskrev jag normalfördelning och hur bra det var att ha en sådan modell. Kortfattat så innebär det att man enkelt kan uppskatta fördelning av befolkning utifrån hur långt från medelvärdet man kollar baserat på standardavvikelse. Denna vecka säger jag att man kommer få en normalfördelning om man tar tillräckligt stora samplar (urval), i princip oavsett hur den verkliga populationen ser ut. Och det är inte helt negativt! Det man vill göra med att ta stora samplar är att komma så nära det verkliga medelvärdet som möjligt med så liten standardavvikelse som möjligt. Om man lyckas med det så har man fått ett urval som har ett medelvärde som ligger där det riktiga medelvärdet ligger, med liten felmarginal.

I sitt urval kommer man ha en standardavvikelse. Och om man vill säga något om 95% av populationen så fångas de inom 2 standardavvikelser från medelvärdet. Detta har jag skrivit om i förra veckan som 68-95-99.7% regeln. Så om standardavvikelsen är stor så kommer det intervall som beskriver 95% av populationen att vara stor. Förhållandet mellan populationens standardavvikelse och urvalets standardavvikelse är s = σ/(√n), där n är urvalsstorlek. Det innebär att man minskar standardavvikelsen med roten ur sampelstorlekens förändring. Vill man halvera standardavvikelsen så får man fyrdubbla urvalsstorleken.

Nästa gång ska jag skriva något om konfidensintervall. Jag misstänker att vi redan har börjat fila på det, men jag får återkomma när jag läst lite om saken.


Kommer i form

Sagan fortsätter. Senast hade jag problem med att uppdatera användares roller. Rollerna avgör vad användare kan göra på hemsidan. I huvudsak gäller det om en användare ska vara administratör eller inte. När jag skrev senaste inlägget så lyckades jag inte med att uppdatera användares roller och någonstans låg problemet i administratörskontrollen (controller) eller i formuläret. Jag visste inte exakt var problemet låg, men det gör jag nu: det var i båda!

Så jag är lite av en härmapa när jag håller på att lära mig nya saker, och när det kom till användare så härmade jag hur upplägget såg ut för att uppdatera till exempel författare. Och här är kruxet: upplägget för författare och användare är olika. För författare så färdiggenereras en formulärklass som man kan skicka till Twig, vilket är en så kallad template engine. Det innebär att utifrån givna parametrar så genererar Twig den html-kod som behövs för att visa givet innehåll. Och jag byggde upp en formulärklass för användare också, men använde inte Twig till att generera den. Istället så skräddarsydde jag html-koden för att motsvara exakt vad som behövs för att uppdatera användare med rätt roller. I ett parallellt spår med detta så byggde jag controller enligt samma sätt som controller för författare. Det innebar att controllern kontrollerade om det färdiggenererade formuläret innehöll någon ny data. Och eftersom jag inte använde mig av det färdiggenererade formuläret så innebar det att controllern inte fick någon uppdaterad data. Lösningen blev därför att uppdatera controllern med att kolla i svarsobjektet istället för i formulärobjektet. Och därmed hade jag på 5 minuter löst ett problem som hållit mig fast i ett par timmer.

Ytterligare utveckling denna veckan har varit att lägga till en aktiveringsprocess när man registrerar sig som ny användare. Det innebär att applikationen kommer kontrollera att den som registrerat sig också är användare av den epost som har angetts. På den fronten har det gått snabbt, men det beror också på att jag kunnat sitta i åtminstone 20 minuter åt gången för att programmera.

På återseende på fredag!


Snubblarmåndag

Så kör vi igång med en ny vecka. Målet för förra veckan var att få igång ett auktoriseringssystem, och till viss del har jag fått igång det. Målet denna vecka är att få klart det.

Varför blev det inte klart förra veckan? Jo, för att jag vet inte vilket problem jag har. Mer exakt vet jag inte varför min kontroll och formulär inte lyckas med att spara när jag ändrar typ av roll som en användare ska ha. Jag kommer återkomma i veckan med var problemet ligger någonstans och hur jag väljer att hantera det. Om jag inte lyckas med detta så återstår att jobba direkt mot databasen.

En annan anledning till att jag inte blivit klar är att jag för närvarande oftast får 10 minuter åt gången när jag kan sätta mig ned och programmera. Det är alldeles för korta stunder för att hinna sätta in mig i vad jag försöker göra. Vad jag istället hinner med är att teckna lite:

”Skakar hand.”

Alltså, det där är vad min hjärna kan göra när den har 10 minuter åt gången.

Nu hoppas jag att jag kan få mer gjort denna vecka, men det beror på sömn och bebisar. Annars blir det fler teckningar.


Auktorisering aktiverad

Så har det visat sig igen att det goda folket bakom Symfony kan göra bra guider. Jag har nu implementerat funktion för att avgränsa ytor av applikation till relevanta roller: så som att man måste vara inloggad som användare för att kunna göra inlägg, och som administratör så finns lite fler verktyg för att hantera entiteter. Det som återstår att göra är att skapa en super-administratör som kan lägga till roller för olika användare.

När jag är klar med super-administratören så finns det lite finlir jag behöver ta hand om. Till exempel behöver jag anpassa kontrollerna för entiteter så att de motsvarar hur jag vill använda dem. I och med dessa anpassningar behöver jag också justera form-klasser och presentationen av formulären.

Jag får se därefter hur mycket tid till övers jag kommer ha framöver. Snart kommer jag att börja en deltids kurs för dataanalys på grundläggande nivå. Det innebär att mina framtida uppdateringar från och med november kommer prata om statistik och att jag redan är inkörd på sömnbrist i och med bebisar.


Användarfunktioner

Vad är nyttan med användare om inte användare har funktioner till hands som inte besökare har? Det är ganska riskabelt att låta vem som helst få skapa innehåll på hemsidan, och därför vill jag avskärma applikationen till att bara kunna användas av folk som går med på lite grundläggande värderingar. Tanken är att Bokarenan är för vettiga och vänliga människor. Dessa medlemmar kan skapa recensioner till böcker som finns i databasen, och om den aktuella boken inte finns så ska de kunna skapa den. Men för att få detta att funka som jag vill så kan jag ta det som jag gjort hittills och avgränsa funktioner till att bara vara tillgängliga för de som loggat in. I tidigare version av Bokarenan så har jag skapat en SESSION COOKIE när användare loggar in, och därmed kan jag i headern för varje sida på applikationen kontrollera att det finns en användare närvarande. I och med att jag använder Symfony så finns det lite andra verktyg jag kan ta hjälp av. Och vilka verktyg är det då som finns? Jag vet inte! Inte än.

Denna vecka kommer jag därför att fokusera på Symfony:s verktyg för att hantera auktorisering. Min förhoppning är att jag kan skapa ett flexibelt system för att hantera olika roller och presentera relevant material och verktyg för användarna. Dessutom hoppas jag på att koden fortsättningsvis kan vara överblickbar och lätt att modifiera vid behov.


Fredagsform

Hur länge ska jag försöka få till formulär? Det kanske märks på mina blogginlägg att utvecklingen inte går snabbt, men det sker åtminstone små steg i rätt riktning varje dag. Det har att göra med konceptet att vara pappa till två bebisar. För när tid finns över till programmering så är frågan om jag är tillräckligt klar i huvudet för det. Men som sagt: det går framåt!

Jag har fått till ett formulär nu, som framgick av föregående inlägg. Den har rätt beståndsdelar, men är inte snygg och har ett blandat språk (på grund av anledningar). Detta kommer justeras längre fram. Det som är av största vikt när formuläret är på plats är att det nu ska finnas en kontroll som kan hantera formuläret och uppdatera databasen med formulär-datan.

Jag har använt mig av en hjälp-klass som jag kallar EntityBasket. Den har beskrivits i tidigare inlägg, men i stort så har den koll på hur formuläret är uppbyggt och kan hämta motsvarande entiteter ur den. Det innebär att en kontrollklass kan hämta en entitet och sedan skicka den till databasen. Det som min kontrollklass gör i detta sammanhang är att den hämtar samtliga relevanta entiteter från formuläret, skapar nödvändiga relationer dem emellan, och sedan sparar dem i databasen.

Det var inte lite förvånad jag blev när jag upptäckte att Doctrine (som är ramverket för databashantering i applikationen) var så lätt att använda som jag trodde. Doctrine gav mig entitets-id som jag kunde använda när jag ville skapa relationer mellan entiteterna, innan jag hade sparat dem mot databasen. Jag kunde ange för Doctrine vilka entiteter jag skulle spara och sedan sparades alla samtidigt när jag använda funktionen flush().

Så när jag nu fått till ”baksidan” av formuläret så tänkte jag härnäst få till att avgränsa funktioner att lägga till mot databasen. Endast användare som är inloggade ska få lägga till entiteter.

Och så går åter en vecka till helg. Den här veckan spelar jag annat än Elite Dangerous. Elite är ett spel som inte går att pausa när man spelar, vilket gör att man håller tummarna att inget händer när bebisar kallar. Och denna vecka har bebisar kallat mer än förr. Som omväxling till detta har jag tagit med dem till biblioteket och kollat på deras spelutbud. Jag fann spelet Control där. Spelet handlar om Jesse som lyckats hitta en hemlig myndighet; Federal Bureau of Control (FDC). Det som lett henne dit är försvinnandet av hennes bror. FDC var de som tog hennes bror ifrån henne när de var små, och hon har sökt efter dem sedan dess. Spelet är i tredje person, vilket utvecklarna Remedy är vana att göra spel i. Tidigare har de gjort Max Payne och Alan Wake, och denna gång är det som en mix av dem. Det är mycket action och mycket berättelse (särskilt i de rapporter som finns att hitta i spelvärlden). Jag gillar vad jag spelat hittills, och uppskattar att det går att pausa var som helst (även i filmsekvenser).

Glöm inte att det är kanelbullens dag denna fredag!

Trevlig helg, allihop!


Grunderna kommer på plats

Nu går det framåt, men är det snyggt? Med hjälp av Symfony så har jag fått formulär som är anpassade mot respektive entitet som jag sparar i min databas. Som jag tidigare beskrivit så vill jag att användaren ska kunna lägga till all relevant data när en recension ska läggas till. Det innebär att flera entiteter kan komma att läggas till när en recension läggs till, så som förläggare och författare. Min första lösning var att lägga till alla förproducerade formulär som Symfony skapat, men det innebar att ett antal fält skapades som förekom flertalet gånger (eftersom varje enskild entitet kunde relatera till en annan entitet). Jag tog därför och gjorde anpassade formulär för respektive entitet som avhandlade just den enskilda entiteten utan dess relation till andra entiteter. Resultatet blev något vackrare.

Så tillbaka till ett tidigare dilemma; hur ska jag implementera funktionaliteten att lägga till fält för fler författare? Ska jag använda min tidigare lösning som exkluderar JavaScript. Detta skulle innebära att sidan laddas snabbare och att jag undviker att använda sådant som jag inte är van vid. Nackdelen är att jag måste i så fall lägga till fält för upp till ett max antal författare för en bok, säg 10 stycken. Oavsett om användaren vill lägga till en författare eller 20. Det skulle kunna i udda fall kunna innebära att användare inte får lägga till så många författare som användaren vill.

Den andra lösningen, så som även beskrivs i en guide från Symfony, är att använda JavaScript och JQuery för att dynamiskt lägga till fler fält. Nackdelen är att källkoden inte blir vacker och sidan kan ta längre tid att ladda. Fördelen är att endast så pass många fält som användaren vill ha finns till hands. Det innebär också något tydligare indelning på ansvarsfördelning vad avser att JavaScript hanterar beteende och låter HTML stå för stommen.

Jag har valt den andra lösning, för att jag vill pröva något nytt och kanske lära mig något nytt. Resultatet nu är som sådant:

Det är tydligt att jag inte jobbat något med utseende, utan endast innehåll och funktion. När jag fått till de grundläggande funktionerna för applikationen så kommer jag ta hand om utseendet.


getData funkade!

Från föregående inlägg så undrade jag om det rätta sättet att komma åt rätt värden från formuläret var att använda Request-objektet eller Form-objektet. I andra projekt hade jag använt ”superglobala” variabler för att komma åt formulär-värden. Då hade jag använt $__POST[”book_name”]. I Symfony finns dessa värden i Request-objektet. Eller så var i alla fall min uppfattning. Men jag upptäckte att jag inte fick det resultat jag väntade för jag fick aldrig värdet från book_name. Därför blev det att jag vände mig till googling:

Det blev helt enkelt ganska många fönster när jag försökte hitta svar på mina funderingar. Jag kollade i Symfonys guider, dess github-sida, PHP:s officiella sida, och så klart Stack Overflow. Jag fick inte riktigt svar på varför det inte funkade att använda Request-objektet. Men däremot fann jag lösningen! Jag kunde använda Form-objektet. Genom $form->getData() så kunde jag extrahera ett bok-objekt. Och därmed kunde jag få detta enkla resultat och jag kände mig så lättad:

Book is set. It's title is Testing.


Att logga in

Jag fortsätter följa guiden från Symfony för hur man sätter upp ett inloggningssystem. Det finns script redo att hjälpa en att komma igång. Med ett enkelt kommando: php bin/console make:auth, så genereras/uppdateras en konfigurationsfil, en kontroller, en autentiserare och HTML-fil för login-sidan. När jag kollar på HTML-filen så finns där ett inloggningsformulär med POST-metod. Detta är jag van vid. Dock så finns det inte angivet vad som ska vara mottagare för formuläret. Det brukar anges av action="". Men detta saknas i HTML-filen där det i formulärtaggen helt enkelt står: <form method="post"> . Istället läser jag: ”When you submit the form, the LoginFormAuthenticator will intercept the request”. Om jag förstår detta rätt så innebär det att formuläret inte behöver en mottagare. Istället kommer denna autentiserare ligga och lyssna efter formulärposter från login-sidan. För att få svar på detta så kan jag pröva mig fram. Jag prövar att registrera en ny användare, et voilà: det funkar*.

* Jo, det funkar som jag föreställde mig, men jag behövde göra lite justeringar då det automatisk genererade registreringsformuläret saknade ett fält för epost.

Hur justerar man då de automatiskt genererade formulären? Det går ju att göra som jag gjorde först: ändra i Twig-filen (det vill säga det som blir HTML-kod). Det var ganska enkelt att lägga till ett fält och få det presenterat för sig. Kruxet är bara det att det fältet ska snappas upp av en kontroller. Det jag behövde göra var att gå in i App\Form\RegistrationFormType och lägga till ett fält i en FormBuilder med funktionen:
->add('email', EmailType::class)
Och därmed var min lycka gjord.

När jag nu fått till inloggningsfunktionen så fortsätter jag med att lägga till entiteter med Symfonys CLI (Command Line Interface), eller vad de kallar för maker bundle. CLI:t gör det hela pinsamt enkelt att lägga till entiteter. Jag får hjälp av det att bestämma fält och typ samt relationer, och då genereras/uppdateras entitets- och förvarar-klasser med rätt information.


Dokumentation som är bra

Jag anpassar för närvarande Bokarenan till att nyttja Symfonys olika komponenter. Det är åtminstone planen men det blir mycket läsande. Jag är ute på nya marker när jag nu utforskar ett framework utan en bok som grund. Men det gör ingenting! Jag tycker dokumentationen är utmärkt. Symfony har guider för att komma igång med grunderna, för att starta med Unit-tester och för att sätta upp ett inloggningssystem. Fler finns det, men detta är så många som jag har gjort just nu. För närvarande går jag igenom Security-guiden. Eller, jag höll på med det, tills den föreslog att jag skulle gå igenom guiden för att sätta upp en inloggningssida. Det blir lite som att hoppa ned i hål efter hål, och hoppas man kommer tillbaka någon gång.

Den här veckan har det gått långsamt att programmera. Det har kanske blivit att jag funnit en timme per dag att programmera eller läsa om programmering. Anledningen: bebisarna växer och behöver mer stimulans, och jag har känt ett ökat behov av att träna mer. Det blir därför fler promenader och ett antal timmar på gymmet under veckan. Men jag känner mig nöjd med programmeringen. Jag är i huvudsak pappa, och programmering är min hobby. Så länge som jag hittar någon tid att sitta ned och programmera så är jag nöjd.

Det jag kommer göra till nästa uppdatering här på bloggen är att sätta upp en enkel front-end och lägga till entiteter och kontroller för att hantera böcker.

Sen så är det ju självklart fredag igen, och med helgen så kommer mina enkla nöjestips. Jag är rätt så bevandrad nu, i och med alla barnvagnspromenader. Och sen en månad tillbaka så ser jag fram emot mina promenader, för då kan jag lyssna på podcasts. Och en av mina favoriter just nu är Linear Digressions. De består av en duo – en webbutvecklare och en datavetare som diskuterar olika tillämpningar av machine learning. Det jag älskar med denna podd är att jag som bara känner till ämnet hyfsat ytligt kan följa med. Och det är alltid trevligt att lyssna på denna duo som har sån bra dynamik sinsemellan.

Så slår jag också ännu en gång ett slag för Elite: Dangerous. Den gångna veckan har jag somnat ett par gånger framför det när jag försökt spela när bebisar varit lugna. Spelet kanske låter något tråkigt nu, men det är mest för att jag varit något utmattad vid slutet av dagen.

Trevlig helg, allihop!