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 84404×

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ů

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ář

14.2.2016 16:39 /Redakce Linuxsoft.cz
O víkendu 5. a 6. března 2016 proběhne na pražském Strahově 8. ročník tradiční konference InstallFest. Celkem za dva dny uvidíte ​30 přednášek​ a ​6 workshopů.
Přidat komentář

5.2.2016 17:38 /Petr Ježek
Utilitka z XFce "xfce4-power-manager" nejen umožňuje nastavení lhůty pro uspání či hybernaci, ale i zapínání a vypínání prezentačního módu pro nerušené sledování videí. Stačí ji nastavit v každém vybavenějším panelu a v jakémkoli nontiled WM/DE.
Přidat komentář

10.1.2016 11:32 /Pavel `Goldenfish' Kysilka
LinuxMarket změnil provozovatele. Nově jej provozuje Marek Pszczolka. Více info a detaily #1 a #2.
Přidat komentář

29.12.2015 11:38 /Ondřej Čečák
Ještě posledních pár dní můžete přidávat příspěvky nebo nápady na Install Fest 2016, který se bude konat 5. a 6. března 2016.
Přidat komentář

8.12.2015 11:36 /Petr Ježek
Logické se stává realitou. LibreOffice a Thunderbird se mají dle článku na Redditu stát protiváhou MS řešení (MS Office a Outlook).
Přidat komentář

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

> Poslední diskuze

10.6.2016 21:10 / pavel riha
FreeBSD 10.3 a virtualizace

8.6.2016 21:56 / Milan Gallas
Nevalidní prefix m

7.5.2016 14:58 / Teodor Komárek
Soubory

20.4.2016 0:07 / Jakub Cleing
Sázkový panel PHP FUSION

9.4.2016 9:43 / jiwopene@gmail.com
Re: problém s dpkg a nemožností instalovat

Více ...

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