LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> PHP (17) - Dokončujeme kalendář

V této části seriálu o PHP dokončíme kalendář, který jsme začali psát v minulém dílu.

28.6.2004 15:00 | Petr Zajíc | Články autora | přečteno 84662×

Komerční sdělení: Pořádáme Kurzy PHP

Připomeňme jen, že v minulém dílu jsme začali sestavovat kalendář, který bude nakonec vypadat nějak takhle:

červenec 2004
Po   5 12 19 26
Út   6 13 20 27
St   7 14 21 28
Čt 1 8 15 22 29
2 9 16 23 30
So 3 10 17 24 31
Ne 4 11 18 25  

Už jsme vyřešili jak zjistit počet dnů v měsíci a rovněž jak stanovit, který den v týdnu připadne na prvního. Dnes nás čeká napsat kód na zjištění počtu sloupců, kód na sestavení jednotlivých buněk a musíme to celé nějak dostat dohromady.

Počet sloupců

Je zřejmé, že jeden sloupec bude muset být vždy rezervován na názvy dnů. Dále je zřejmé, že vlastní kalednář si může vyžádat čtyři (únor v nepřechodném roce začínající pondělím), pět nebo i šest sloupců pro svoje data. Počet sloupců musíme znát ještě dříve, než budeme tabulku sestavovat.

Sám jsem při psaní kódu podlehl chybě popisované v minulém díle, a sice té, že jsem se pokusil sestavit matematické pravidlo, z něhož by počet sloupců vypadl. Jde to však jednodušeji - postačí nám donutit PHP k tomu, aby nám řeklo, zda daný měsíc zabírá rozmezí čtyř, pěti nebo šesti týdnů. Neboli, v kolikátém týdnu roku je prvního v měsíci a v kolikátém týdnu je posledního. Protože už máme funkci PocetDnu, je zjištění obojího záležitost jednoho řádku kódu:

<? $sloupcu = date("W", mktime(0, 0, 0, $mesic, $PocetDnu, $rok)) - date("W", mktime(0, 0, 0, $mesic, 1, $rok))+2; ?>

Dva sloupce se přičítají proto, že jeden je na názvy dnů, kdežto druhý je kvůli matematickému rozdílu mezi základními a řadovými číslovkami (31. mínus 27. týden je 5 ne 4).

Korektura: To jsem tomu dal! Praxe ukázala, že to v některých případech nebude fungovat. Například první leden roku 2000 má číslo týdne 52, zatímco poslední prosinec roku 2007 spadá do týdne číslo 1 následujícího roku. Je to snad nějaká chyba? Ani ne. Kdybych si přečetl manuál, zjistím, že PHP funkce date se při vracení pořadového čísla týdne v roce chová podle normy ISO-8601. Tato norma specifikuje formáty data a mimo jiné stanoví způsob, jakým se číslují týdny na přelomu měsíců prosince a ledna. jednoduše řečeno je to tak, že pokud více než tři dny přelomového měsíce spadají do ledna, je týden považován za první v novém roce, v opačném případě je považován za poslední týden v roce minulém.

Dlouho jsem přemýšlel, jak to jednoduše ošetřit, aniž bych zjišťování týdnů musel nějak dramaticky od základu přepsat. Výsledek je, že zjišťuji a odečítám ne počet týdnů mezi prvním a posledním dnem v měsíci, ale počet týdnů mezi osmým dnem od začátku a osmým dnem od konce. Vynechané dva týdny sice musím v závěru přičíst, ale zase se úplně vyhnu problémům s prosinci a ledny některých let. Opravený a funkční způsob zjištění počtu sloupců tedy je:

<? $sloupcu = date("W", mktime(0, 0, 0, $mesic, $PocetDnu-7, $rok)) - date("W", mktime(0, 0, 0, $mesic, 1+7, $rok))+4; ?>

Aneb: Člověk se stále učí.

Sestavení buňek

Je zřejmé, že dobrý nápad by byl použít dvě vnořené smyčky a sestavovat tabulku zleva doprava a odzhora dolů (ostatně jinak to ani nejde). Naspišme si tedy funkci, které pošleme řádek, sloupec, který den je prvního a kolik má měsíc dnů - a chtějme po ní jako výsledek obsah buňky kalendáře! Mohlo by to vypadat nějak takto:

<?
function Bunka ($radek, $sloupec, $PrvniDen, $PocetDnu)
{
  
$dny=Array(1=>"Po", "Út", "St", "Čt", "Pá", "So", "Ne");
  if (
$sloupec==1) return $dny[$radek];
  
$chcivratit = ($sloupec-2)*7 + $radek - $PrvniDen+1;
  if (
$chcivratit<1 || $chcivratit>$PocetDnu) return "&nbsp;"; else return $chcivratit;
}
?>

První dva řádky jsou myslím jasné; jestliže je v proměnné $sloupec jednička, nemůže to dopadnout jinak než že vrátíme zkratku dne. Ve třetím řádku zjišťujeme pomocí matematiky, jaké číslo v dané buňce pravděpodobně bude. Pravděpodobně proto, že to není jisté. Neexistují totiž záproné dny a nemůžeme zobrazit víc dnů, než kolik jich daný měsíc opravdu má. Což se testuje na řádku čtvrtém. Pokud jsme "v rozsahu", vrátí funkce dané číslo, pokud ne, vrátí HTML kód neoddělitelné mezery. To proto, abychom se vyhnuli problémům při zobrazování prázdných buněk v tabulkách.

Výsledek

Výsledkem našeho snažení bude funkce, která převezme dvě proměnné (měsíc, rok), sestaví kalendář a pošle jej do prohlížeče. Bude to vypadat takto:

<?
function Kalendar ($mesic, $rok)
{
  
$mesice=Array(1=>"leden", "únor", "březen", "duben", "květen", "červen", "červenec", "srpen", "září", "říjen", "listopad", "prosinec");
  
//kontroly
  
if (!is_numeric($mesic)) return "Měsíc musí být číslo!";
  if (!
is_numeric($rok)) return "Rok musí být číslo!";
  if (
$mesic<1 || $mesic>12) return "Měsíc musí být číslo od 1 do 12";
  if (
$rok<1980 || $rok>2050) return "Rok musí být číslo od 1980 do 2050";
  
// zjištění počtu sloupců
  
$PocetDnu = PocetDnu ($mesic, $rok); $PrvniDen = PrvniDen($mesic,$rok);
  
$sloupcu = date("W", mktime(0, 0, 0, $mesic, $PocetDnu-7, $rok)) - date("W", mktime(0, 0, 0, $mesic, 1+7, $rok))+4;
  
// vlastní kód
  
echo "<TABLE border=\"1\" style=\"border-collapse: collapse\" width=\"",$sloupcu*30,"\">";
  echo
"<TR><TD colspan=$sloupcu width=\"",$sloupcu*30,"\" align=\"center\">".$mesice[$mesic]."&nbsp;".$rok."</TD></TR>\n";
  for (
$radek=1;$radek<=7;$radek++)
  {
    echo
"<TR align=\"center\">";
    for (
$sloupec=1; $sloupec<=$sloupcu; $sloupec++) echo "<TD width=\"30\">".Bunka($radek, $sloupec, $PrvniDen, $PocetDnu)."</TD>";
    echo
"</TR>\n";
  }
  echo
"</TABLE>";
}
?>

Ukázat skript | Spustit skript

Při psaní reálného kódu je potřeba příliš nespoléhat na to, že vstupní parametry budou v pořádku, a proto je hned v úvodu funkce ověřujeme. Je zřejmé, že pokus o zobrazení například kalendáře za třináctý měsíc by skončil chybou, takže to víceméně musíme udělat. Co se týče vlastního kódu, začíná tím, že vypíše záhlaví tabulky. Protože už v té době víme, kolik bude sloupců, můžeme si troufnout i na tabulku s pevně danou šířkou (je to mimo jiné hezčí). Pak se píše záhlaví (například "červenec 2004") a nakonec se ve dvou vnořených smyčkách tvoří jednotlivé buňky; jejich hodnoty jsou zjišťovány opakovaným voláním funkce Bunka().

Pokud Vám nejsou jasné některé souvislosti, podívejte se v prohlížeči na zdrojový kód stránky, která kalendář zobrazuje. Věci, které patří spíše do znalostí HTML než k PHP (jako je třeba použití stylu) tady vysvětlovat nebudeme. Jedna věc by Vám ale přesto mohla vrtat hlavou, a to je způsob použití proměnné $sloupcu jako hodnoty atributu colspan ve druhém příkazu echo. Pokud to tak je, pak vězte, že se jedná o tzv. automatickou expanzi proměnné.

Automatická expanze proměnné

Za tímto strašným názvem se skrývá mechanismus, který nám při psaní kódu v PHP ušetří něco málo času při práci s řetězci. Nejlépe to vysvětlíme na příkladu. Následující kód provede dvakrát totéž:

<?
$uzivatel
="Petr";
$server="Linuxsoft";
echo
"Uživatel ".$uzivatel." je vítán na serveru ".$server."!<BR>";
echo
"Uživatel $uzivatel je vítán na serveru $server!<BR>";
?>

Neboli, pokud píšete řetězec v uvozovkách, můžete v něm použít proměnnou a ona se automaticky expanduje. Není to nic převratného, ale může to ušetřit nějaký čas při psaní kódu.

V dalším díle našeho seriálu se podíváme na fukce, které jsme zatím přeskočili - jsou to funkce pro práci s poli.

Verze pro tisk

pridej.cz

 

DISKUZE

expanze promennych 28.6.2004 20:15 Pavel Kácha
Re: Expanze promennych 28.6.2004 21:42 Petr Zajíc
L Re: Expanze promennych 29.6.2004 02:00 Pavel Kácha
  L Re: Expanze promennych 29.6.2004 14:25 Petr Zajíc
Leden 2005 v kalendari 23.7.2004 21:14 David Macura
|- Re: Leden 2005 v kalendari 24.7.2004 19:57 Petr Zajíc
|- Re: Leden 2005 v kalendari 27.7.2004 19:44 Tomáš Miklík
| L Re: Leden 2005 v kalendari 31.7.2004 09:01 Petr Zajíc
L Re: Leden 2005 v kalendari 15.10.2004 00:49 Filip Novák
  L Re: Leden 2005 v kalendari 12.3.2007 15:04 Jirka Dobrovolny
    L Re: Leden 2005 v kalendari 12.3.2007 15:07 Jirka Dobrovolny
Nefunguje mi to:( 18.3.2005 17:13 Chadas
Preco taky skok??? 12.10.2006 10:42 Jozef Martoncik
L Re: Preco taky skok??? 13.10.2006 08:38 Petr Zajíc
Súhlasím - veľký skok 10.1.2007 16:50 Martin Balaz
L Re: Súhlasím - veľký skok 11.1.2007 09:56 Petr Zajíc
RE: velky skok 6.4.2007 17:14 A.M.
L Re: RE: velky skok 6.4.2007 18:53 Petr Zajíc
oznaceni jaky je den 11.12.2007 19:22 negr
L Re: oznaceni jaky je den 16.12.2007 13:51 Jozef Valo
Odkazy na kalendáři 21.1.2008 20:47 Petr Havel
L Re: Odkazy na kalendáři 21.1.2008 23:43 Aleš Hakl
  L Re: Odkazy na kalendáři 22.1.2008 16:59 Petr Havel
Počet sloupců - korektura 14.7.2009 21:07 Matěj Ošanec




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

27.8.2016 8:55 /Delujek
Dnes po 4 letech komunitního vývoje vyšla diaspora 0.6.0.0
diaspora* je open-source, distribuovaná sociální síť s důrazem na soukromý
Více v oficiálním blog-postu
Přidat komentář

24.8.2016 6:44 /Ondřej Čečák
Poslední týden CFP LinuxDays 2016; pokud byste rádi přednášeli na LinuxDays 2016 8. a 9. října v Praze, můžete svůj příspěvek přihlásit, následovat bude veřejné hlasování.
Přidat komentář

9.8.2016 22:56 /Petr Ježek
Zařazení souborového systému reiser4 do jádra 4.7 znamená konečně konec patchování jádra jen kvůli možnosti použít reiser4.
Přidat komentář

12.7.2016 13:14 /František Kučera
Spolek OpenAlt zve na 130. distribuovaný sraz příznivců svobodného softwaru a otevřených technologií (hardware, 3D tisk, SDR, DIY, makers…), který se bude konat ve čtvrtek 21. července od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

11.7.2016 16:53 /Redakce Linuxsoft.cz
Konference LinuxDays hledá přednášející. Přihlášky poběží do konce prázdnin, v září bude hlasování a program. Více na https://www.linuxdays.cz/2016/cfp/.
Přidat komentář

8.5.2016 17:19 /Redakce Linuxsoft.cz
PR: Dne 26.5.2016 proběhne v Praze konference Cloud computing v praxi. Tématy bude např. nejnovější trendy v oblasti cloudu a cloudových řešení, cloudové služby, infrastruktura cloudu, efektivní využití cloudu, možné nástrahy cloudů a jak se jim vyhnout
Přidat komentář

21.4.2016 8:01 /František Kučera
Spolek OpenAlt zve na 127. distribuovaný sraz příznivců svobodného softwaru a otevřených technologií (hardware, 3D tisk, SDR, DIY, makers…), který se bude konat ve čtvrtek 28. dubna od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

2.3.2016 22:41 /Ondřej Čečák
Letošní ročník konference InstallFest již tento víkend!
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

12.8.2016 11:51 / Josef Zapletal
Jak udělat HTML/Javascript swiping gallery do mobilu?

8.8.2016 14:58 / Adams
fairies for hire

28.7.2016 15:51 / pepan
Re: NetBeans vs Eclipse

10.6.2016 21:10 / pavel riha
FreeBSD 10.3 a virtualizace

8.6.2016 21:56 / Milan Gallas
Nevalidní prefix m

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2016) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze