Permalänk
Medlem

Kalender PHP/MySQL

Hej. Jag ska göra en kalender i PHP/MySQL men jag vet inte hur jag ska lägga upp databas-strukturen. Att fixa så PHP visar alla dagar korrekt och så ska inte vara något problem men hur gör jag så att den kollar vilka dagar som innehåller anteckningar mot en databas? Jag ska väl inte behöva lägga in en tabell med alla årets dagar och sen är det bara vissa som har nåt att visa?

Hjälp uppskattas!

Christian

Permalänk

inte helt hundra på problemet.. Du har ju en tabell med anteckningar där du lägger in ett datum i en datumkolumn. sen kör du "SELECT * FROM Anteckningar WHERE Datum = Idag", typ

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Ja fast jag ska ju inte bara kolla datum för idag. Jag vill ha en överblick över alla månadens dagar och se vart det ligger en anteckning.

Permalänk
Citat:

Ursprungligen inskrivet av kismo
Ja fast jag ska ju inte bara kolla datum för idag. Jag vill ha en överblick över alla månadens dagar och se vart det ligger en anteckning.

Kör samma databasupplägg fast du istället tar bort wheresatsen och därmed läser in alla samtidigt och har dem i minnet? Sen när man klickar till en månad läses dem ut ?

Du behöver inte ha en tabell med alla dagar utan du har bara en kolumn "Datum" som du använder för att bestämma vad som ska visas när!

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Ursäkta om jag är trög men jag fattar inte.
1 Fredag [eventuell anteckning]
2 Lördag [eventuell anteckning]
3 Söndag [eventuell anteckning]
4 Måndag [eventuell anteckning]
5 Tisdag [eventuell anteckning]
...
31 Söndag [eventuell anteckning]

Det är här jag inte kommer längre.
Hur kollar jag om det finns en anteckning på Måndag den 4e t.ex?

Permalänk

Visar du en månad i taget? Hämta då ut från databasen den månaden och skriv sen ut det när du loopar fram din kalender

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Jag vet inte riktigt om vi är på samma linje.
Än så länge har jag inte ens någon tabell för anteckningarna utan jag har bara skrivit ut alla datum med hjälp av en for-loop:

<?php //Årtal t.ex. 2010 $this_year = date('o'); //Siffran för nuvarande månad 1-12 $this_month = date('n'); //Antal dagar det finns på nuvarande månad t.ex. 31 $number_of_days_this_month = date('t'); ?> <table class="calendar" border="1" cellpadding="0" cellspacing="0"> <?php for($i = 1; $i <= $number_of_days_this_month; $i++) { //$day_name = dagens namn på aktuella dagen ($i) på den här månaden t.ex. Fri $day_name = date('D', mktime(0, 0, 0, $this_month, $i, $this_year)); echo "<tr><th>$i</th><td>$day_name</td></tr>"; } ?> </table>

Eller behöver jag ha en tabell som heter exempelvis "calendar" med alla årets dagar som skriver ut dagarna och anteckningen om den finns på den aktuella dagen (i for-loopen) ?

Permalänk
Medlem

Varför inte ha en tabell som ser ut så här?

Primaryid=primärnyckel
day(integer)=vilket datum det är
month(integer)=vilken månad det är
year(integer)= Vilket år det är
anteckningar(text)= anteckningar vad som händer

sen kör då nått i stil med detta

$query="Select * FROM DATABAS WHERE month='vilken månad du vill ha' ORDER BY day";// hämtar inlägg i ordening av vilken dag det är.
$resultat=mysql_query($query);//qury på länkar i sqldatabasen
while($rad=mysql_fetch_array($resultat))//hämtar allt som en array
{
gör nått junk typ

$antecknigar= htmlspecialchars($rad['anteckningar'])
echo $antecknigar

}

nått sånt

du kan säkert andvända php date för att luska fram dagar också.

Visa signatur

Ei bor i stockholm och tar inget ansvar för allt som han säger
i5 2500k, 16 gig ram, radeon 6950
Solna arbetscenter

Permalänk
Citat:

Ursprungligen inskrivet av Ei
Varför inte ha en tabell som ser ut så här?

Primaryid=primärnyckel
day(integer)=vilket datum det är
month(integer)=vilken månad det är
year(integer)= Vilket år det är
anteckningar(text)= anteckningar vad som händer

sen kör då nått i stil med detta

$query="Select * FROM DATABAS WHERE month='vilken månad du vill ha' ORDER BY day";// hämtar inlägg i ordening av vilken dag det är.
$resultat=mysql_query($query);//qury på länkar i sqldatabasen
while($rad=mysql_fetch_array($resultat))//hämtar allt som en array

{
gör nått junk typ

$antecknigar= htmlspecialchars($rad['anteckningar'])
echo $antecknigar

}

nått sånt

du kan säkert andvända php date för att luska fram dagar också.

Det jag sagt hela tiden ju:/

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Ja, det hämtar alla dagar det finns en anteckning på. Om jag vill skriva ut hela månaden inkl. tomma dagar hur blandar jag in det då?

Permalänk
Citat:

Ursprungligen inskrivet av kismo
Ja, det hämtar alla dagar det finns en anteckning på. Om jag vill skriva ut hela månaden inkl. tomma dagar hur blandar jag in det då?

Jag skriver lite pseudokod, detta är inte korrekt syntax och inte php:

int month = 12; List<Note> notes = GetNotesWithMonth(month); for(int i = 0; i < DaysInMonth(month); i++) { //Printa din vanliga dag if(notes.Where(note=>note.Day == i).Count() > 0 { Console.Writeline(notes.Where(note=>note.Day == i).First().Text); } }

Hoppas du förstår vad vi menar

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av KurreKula
Jag skriver lite pseudokod, detta är inte korrekt syntax och inte php:

int month = 12; List<Note> notes = GetNotesWithMonth(month); for(int i = 0; i < DaysInMonth(month); i++) { //Printa din vanliga dag if(notes.Where(note=>note.Day == i).Count() > 0 { Console.Writeline(notes.Where(note=>note.Day == i).First().Text); } }

Hoppas du förstår vad vi menar

Tack så jättemycket. Det hjälpte. Nu är grunden klar. Kom gärna med lite kritik, det går säkert att göra det bättre.

calendar.php:

<?php $year = (isset($_GET['year'])) ? $_GET['year'] : date('o'); $month = (isset($_GET['month'])) ? $_GET['month'] : date('n'); $short_month = date('M'); //Jan $short_last_month = date('M', mktime(0, 0, 0, ($month-1), 1, $year)); //Dec $short_next_month = date('M', mktime(0, 0, 0, ($month+1), 1, $year)); //Feb $prev_month = ($month - 1); $next_month = ($month + 1); $nav_prev_year = $year; $nav_next_year = $year; if($prev_month <= 0) { $prev_month = 12; $nav_prev_year = ($year-1); } if($next_month >= 13) { $next_month = 1; $nav_next_year = ($year+1); } $number_month = date('n'); //1-12 //timme, minut, sekund, månad, dag, år, is_dst(?) $date_text = date('F Y' , mktime(0, 0, 0, $month, 1, $year)); ?> <h1 class="cal_header"><?php echo "$date_text"; ?></h1> <ul class="cal_nav"><li><a href="<?php echo '?year='.$nav_prev_year.'&'.'month='.$prev_month; ?>"><?php echo $short_last_month; ?></a></li><li><a href="<?php echo '?year='.$nav_next_year.'&'.'month='.$next_month; ?>"><?php echo $short_next_month; ?></a></li></ul> <table class="calendar" border="1" cellpadding="0" cellspacing="0"> <?php db_connect(); $sql = "SELECT * FROM calendar WHERE year = '$year' AND month = '$month'"; $result = mysql_query($sql); $days_sel_month = date('t', mktime(0, 0, 0, $month, 1, $year)); //31 days selected this month for($i = 1; $i <= $days_sel_month; $i++) { $day_no = $i; //Dagens namn på den 1:a på den här månaden t.ex. Fri $day = date('D', mktime(0, 0, 0, $number_month, $day_no, $year)); //Om söndag gör siffran för söndag röd if($day == 'Sun') $day_no = "<span>$day_no</span>"; if($row = mysql_fetch_assoc($result)) { $cid = $row['id']; $cyear = $row['year']; $cmonth = $row['month']; $cday = $row['day']; $ctime = $row['time']; $cnote = $row['note']; } if($i == $cday) { echo "<tr><th>$day_no</th><td class=\"day\">$day</td><td class=\"note\">$cnote</td></tr>"; } else { echo "<tr><th>$day_no</th><td class=\"day\">$day</td><td class=\"note\"> </td></tr>"; } } ?> </table>

Permalänk
Testpilot
Citat:

Ursprungligen inskrivet av Ei
Varför inte ha en tabell som ser ut så här?

Primaryid=primärnyckel
day(integer)=vilket datum det är
month(integer)=vilken månad det är
year(integer)= Vilket år det är
anteckningar(text)= anteckningar vad som händer

Det finns fina datumfunktioner man kan använda istället för att ha tre olika heltal för dag/månad/år, mycket bättre att använda det istället.

Visa signatur

Kolla gärna in min RGB-LED-ljusstake i galleriet
[Gigabyte GA-Z97MX-Gaming 5][Intel Core i5 4690K][Corsair XMS3 16GB][Asus GeForce RTX 2060 Super Dual Evo OC]

Permalänk
Medlem

Sant huden, inget jag tänkte på mitt i natten:)

sql

Visa signatur

Ei bor i stockholm och tar inget ansvar för allt som han säger
i5 2500k, 16 gig ram, radeon 6950
Solna arbetscenter

Permalänk
Medlem

För att göra kalendern lite sexigare kan du ju fixa så att du kan ha flera anteckningar uppdelade efter tiden de skrevs in.

Detta gör du ju då bäst genom att ha två tabeller en för årets dagar och en för anteckningarna ex:

calendar
cid (PK)
date osv

Note
nid (PK)
cid (FK)
description
time

Själv skulle jag eventuellt även ha tre tabeller, dvs en för årtalen och en för alla dagar under året och en för anteckningarna.

Visa signatur

AMD Ryzen 9 5900x| Asus ROG Crosshair VIII Dark Hero X570 | G-Skill 32GB DDR4 3600Mhz CL16 Trident | MSI Geforce RTX 3080 10GB Gaming X Trio | Phantek P600S | Creative Sound BlasterX AE-5 Plus | Corsair RM850X 850W | Samsung 980 Pro 1TB M.2 NVME | Kingston A2000 1TB M2. NVME | Corsair H150i Pro XT | Win 10 Home 64
LG 38GN950 | LG Oled 65C1, 65C7 och 55C9
Xbox Series X | Playstation 5 | PSVR 2 | Oculus Quest 2

Permalänk
Medlem

Varför ska man ha separata tabeller för årtal och dagar när du kan hämta ut de direkt i koden? Räcker det inte med att bara spara anteckningar och ett datum och sedan kolla om det finns någon anteckning för ett visst datum och indikera att det finns om så är fallet?

Permalänk
Medlem

Handlar ju i stort om att undvika redundant information, dvs sådan som upprepas, men det är ju lätt att se i en liten exempeldatabas om män är osäker vilket bästa tillvägagångssätt är . I detta fallet kanske det räcker med en tabell för date och en för anteckningar, om man nu tillåter mer än en anteckning per dag, dvs tidsstämplad.

Visa signatur

AMD Ryzen 9 5900x| Asus ROG Crosshair VIII Dark Hero X570 | G-Skill 32GB DDR4 3600Mhz CL16 Trident | MSI Geforce RTX 3080 10GB Gaming X Trio | Phantek P600S | Creative Sound BlasterX AE-5 Plus | Corsair RM850X 850W | Samsung 980 Pro 1TB M.2 NVME | Kingston A2000 1TB M2. NVME | Corsair H150i Pro XT | Win 10 Home 64
LG 38GN950 | LG Oled 65C1, 65C7 och 55C9
Xbox Series X | Playstation 5 | PSVR 2 | Oculus Quest 2

Permalänk
Medlem

Har stött på lite problem. Den hämtar bara en rad ur tabellen. Alltså om jag har flera anteckningar så hämtas bara den första i tabellen...

Jag ska väl ändå inte behöva köra 31 querys per månad (en för varje dag) ? Det kommer ju sega ner så det räcker och blir över...

Permalänk
Medlem

Beror väll på vad du hämtar ut. Men du kan jag tömma hela tabellen med mysql_fetch_array

Visa signatur

Ei bor i stockholm och tar inget ansvar för allt som han säger
i5 2500k, 16 gig ram, radeon 6950
Solna arbetscenter

Permalänk

Edit: Missförstod helt! Ignore!

Permalänk

Menar du att du har flera notes per dag i databasen, eller att for-loopen bara drar ur en rad (dag) ur databasen?

Permalänk
Medlem

Jag menar att jag vill hämta ut alla records för en månad (den månad man är på). Och sen kolla om $i = $databas_dag_variabel där $i loopar dag 1 - 31 (om det är 31 dagar i aktuell månad).

Nu kör den ju:

$sql = "SELECT * FROM calendar WHERE year = '$year' AND month = '$month'"; $result = mysql_query($sql); for($i = 1; $i <= 31; $i++) { if($row = mysql_fetch_assoc($result)) { $cid = $row['id']; $cday = $row['day']; $cnote = $row['note']; } if($i == $cday) { /* skriv ut tabell med db info */ } else { /* skriv ut tabell utan db info */ } }

Förstår ni?

Permalänk
Medlem

Det kan gå snett på några håll i det där. Till att börja med finns det ingen garanti för att du har 31 dagar i din databas, eller att din result-set returnerar dem i ordningen 1 till 31. Ponera att du har det men att du får dem i ordningen [3, 4, 5, ... 31, 1, 2]. Då kommer $i aldrig att vara == $cday.

Ditt problem är alltså att du har en fast loop som går från 1 till 31, och en obestämd storlek på din data som dessutom kan vara osorterad: första mysql_fetch_assoc kan mycket väl returnera dag 5.

Ett alternativ är att skapa en array som du sedan fyller med innehållet i din result set.

$calendarData = array(); $result = mysql_query($sql); while($row = mysql_fetch_assoc($result)) { $day = $row['day']; $note = $row['note']; $calendarData[$day] = $note; }

Något i den stilen kanske? Programmerar inte PHP..

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

Ja. Att loopen går till 31 vet jag, jag skrev om den nu bara för att visa hur jag kodat. Först kollar jag antal dagar för aktuell månad och sen loopar jag från 1 till $antar_dagar så det e lugnt. Så du menar att jag ska lägga till en ORDER by day i min SELECT-sats kanske? Det skulle jag ju kunna göra...

Ja, det fungerar kanske att lägga till i en array så där... Får testa när jag kommer hem.

F.ö så står hela koden längre upp. Nu har jag ändrat lite grejer men det e fortfarande samma grej...

Permalänk
Medlem

Spelar ingen roll vad den går till för nummer eller om du kör en SORT BY. Om du ska kolla Januari och det bara finns tre datum i databasen, vad händer då? Säg att du har data för 5, 8 och 13 januari:

Loop 1: i = 1, $cday = 5. Match? nej.
Loop 2: i = 2, $cday = 8. Match? nej.
Loop 3: i = 3, $cday = 13. Match? nej.
Loop 4: i = 4, $cday = null, alternativt 13 igen eftersom if ($row = ...)-satsen skippas då din result set är uttömd.

edit:
Tycker egentligen att $cday borde vara null i alla lägen eftersom den definieras inuti ett eget block. Fast PHP kanske fungerar så..

Visa signatur

Kom-pa-TI-bilitet

Permalänk

Du får nog göra på det här viset:

Första gången loopen körs, hämtar den värdet på dagens nummer som hämtats ur databasen (cday). Säg att den första raden som dras ut är cday=5, och i=1. Då lägger du en if-sats i slutet av for-loopen som loopar cid-i gånger och lägger ut tomma rutor med incrementing datum, och sedan sätter i = cday. Sedan fortsätter for-loopen, nästa värde hämtas ur db, säg att det då är cday=10 och i=6, så görs samma sak igen. Det kan väl funka.

Hängde du med?

Permalänk

$row = mysql_fetch_assoc($result);

$cday = $row['cday'];

if ($i != $cday) {
while($i < $cday) {
*printa datum med tomma notes*
$i++;
}
}
else {
*printa innehållet i $row-utdraget*
}

ps. Självklart måste du köra order by day ASC i queryn...

Permalänk
Medlem

Förstår inte riktigt vad du menar med att loopa cid i gånger.. Det lättaste måste väl vara att fylla en array och se vilka dagar som finns representerade. Ska det in flera notes i samma dag så lägger man en array i arrayen.

$notes = array(); $result = mysql_query($sql); while($row = mysql_fetch_assoc()) { // vi har data $day = $row['day']; $note = $row['note']; $notes[$day][] = $note; }

Nu innehåller $notes alla anteckningar. För att plocka ut en viss dag kör

if ($notes[$enVissDag]) { foreach($notes[$enVissDag] as &$note) { // använd $note } unset($note); } else { // dag $enVissDag finns inte i kalendern }

Visa signatur

Kom-pa-TI-bilitet

Permalänk

Jag menade loopa tills i "Kommer ifatt cid". Alltså loopa cid minus i gånger... Fast arrays är kanske lättare!

Permalänk
Medlem

Ok. Nu har jag gått igenom allt sjukt noga och detta är felfritt. Har skrivit lite kod och kommenterat det noga. Detta fungerar nu:

<table border="0" cellpadding="0" cellspacing="0"> <?php $year = 2011; //sätts annars beroende på om $_GET['year'] finns annars är lika med nuvarande året $month = 1; //samma grej här, detta är nu januari db_connect(); //egen funktion för att ansluta till databasen $sql = "SELECT * FROM calendar WHERE year = '$year' AND month = '$month' ORDER BY day ASC"; $result = mysql_query($sql); //mktime returnerar [timme], [minut], [sekund], [månad], [dag], [år] $days_sel_month = date('t', mktime(0, 0, 0, $month, 1, $year)); //tar fram date('t'), alltså antal dagar på vald månad for($i = 1; $i <= $days_sel_month; $i++) //loopa ett till exempelvis 31 om månaden har 31 dagar { $day = date('D', mktime(0, 0, 0, $month, $i, $year)); //samma som $days_sel_month fast tar fram dagarna Mon - Fri if($row = mysql_fetch_assoc($result)) //om det finns data { $cday = $row['day']; //$cday = siffran på dagen ifrån databasen (kan vara t.ex. 1 för fredag eftersom fredag är första dagen i månad 1 ($month - januari) $cnote = $row['note']; //noteringen som finns på t.ex. dag 1 (fredag den 1a jan) } //dagens datum 1-31 | dagens dag Mon-Fri | om $i (1-31) är samma som databasens $cday, skriv ut noteringen annars ett blanksteg | snyggare html ?><tr><th><?php echo $i; ?></th><td><?php echo $day; ?></td><td><?php echo ($i == $cday) ? $cnote : '&nbsp'; ?></td></tr><?php echo "\n"; } ?> </table>

Det sjuka är att förut med samma kod (fast lite fulare) skrev den ibland ut bara EN record från databasen och ibland FLERA. Och detta uppstår när jag använder mitt javascript. Tanken är att databashanteringen ska köras med ajax så det blir fint och smidigt utan massa omladdingar av sidan. Och när jag använde ajax så uppstod mina problem, och varför kan jag inte svara på. Det enda jag kan göra nu är att börja koda om såhär grundligt från början och hoppas på det bästa.

Några tankar om koden eller något annat? Jag tar gärna emot lite tips om hur jag på bästa sätt kan bygga upp användarhanteringen av kalendern med ajax. Tidigare hade jag en input på alla rader och om det träffar mot databasen så blir value="$cnote" annars ingenting. Sen körde jag INSERT på aktuell dag vid onblur() (alltså när inputen avmarkerades) men detta känns av nån anledning ganska instabilt. Skulle vilja ha så få knappar så möjligt men det kanske behövs några ändå. Jag vet inte. Va tror ni?

Och tack för all uppmärksamhet i den här tråden förresten.

PS. Jag har en tendens till att skriva en jävla massa när jag väl sätter igång, sorry om ni får läsa onödigt mycket text DS.

/C