PHP od začátku: dynamické skládání stránek funkcí include

 |  PHP: Základy  |  16 224x
PHP od začátku: dynamické skládání stránek funkcí include

V dnešním článku bych odbočil od středně pokročilých PHP skriptů a návodů, a vrátil se na chvíli k samotným začátkům většiny z nás, a to prvnímu použití funkce include. Existuje mnoho konstrukcí, kterými můžeme stránky poskládat z více souborů, a já vám popíši všechny jejich výhody a nevýhody. Pokusím se jít úplně od začátku, od prvního neandrtálského řešení až po šikovnou sekvenci podmínek s ošetřením všech potencionálních chyb a nedostatků.

Nezapomeňte se podívat na druhý díl

Předpokládejme includování stránek podle proměnné $_GET['page'] a odkazy například ve tvaru index.php?page=kontakt. Jako nejjednodušší řešení lze vytvořit posloupnost několika podmínek :

if ($_GET['page'] == 'kontakt') {
    include "./inc/kontakt.php";
} else if ($_GET['page'] == 'kniha-navstev') {
    include "./inc/kniha-navstev.php";
} else {
    include "./inc/uvod.php";
}

Jako první nedostatek bych zmínil absenci chybové stránky. Při zavolání adresy například index.php?page=tohle-neexistuje je načtena úvodní stránka. Lepší, než kdyby se zhroutil celý vesmír, ovšem my se chceme posunout dál. Proto můžeme vytvořit podmínku, která bude hned jako první, postará se o načtení úvodu při nulové hodnotě proměnné a chybovou stránku 404 zavolá až pod else. Nesprávně bývá uváděno porovnání if ($_GET['page'] == '') předcházející dalšímu testování proměnné $_GET['page'], a právě zde narážíme na další chybu : nedefinovaná proměnná totiž nemá hodnotu empty nýbrž null, tudíž musíme porovnávat s hodnotou null. Upravený zápis by mohl vypadat nějak takto :

if ($_GET['page'] === null) { // špatně : if ($_GET['page'] == '') 
    include "./inc/uvod.php";
} else if ($_GET['page'] == 'kontakt') {
    include "./inc/kontakt.php";
} else if ($_GET['page'] == 'kniha-navstev') {
    include "./inc/kniha-navstev.php";
} else {
    include "./inc/404.php";
}

Tohle řešení je ovšem stále čiré zlo. Jestliže máme například 20 podstránek, neustálé opakování if / elseif … je cesta do pekel. A zde přichází konstrukce switch, kterou implementujeme namísto zbytečných podmínek. Nezapomeneme ani na hodnotu false a chybová stránka 404 zůstane pod default.

switch($_GET['page']) {
    case false :
        include "./inc/uvod.php";
    break;
    case 'kontakt' :
        include "./inc/kontakt.php";
    break;
    case 'kniha-navstev' :
        include "./inc/kniha-navstev.php";
    break;
    default:
        include "./inc/404.php";
    break;
}

Mnohem lepší řešení než předchozí uvedené, ale to stále nestačí. Zde zmíním další nedostatek, který první a třetí zápis obsahuje : jestliže nastavíme úroveň výpisu chybových hlášek  error_reporting(E_ALL), zmíněné konstrukce vypisují chybu typu notice. Navíc stejně jako sekvence podmínek musíme i ve switchi neustále přidávat další řádky, tři s každou novou podstránkou. Naštěstí ale přichází v pravou chvíli spásná funkce file_exists, díky které zkrouhneme desítky zbytečných řádků do jednoho if / else. Hodnotě proměnné přidáme koncovku *.php, zkontrolujeme, zda-li daný soubor existuje, pokud ano, includujeme :

$filename = $_GET['page'].".php";
if (file_exists("./inc/$filename")) {
    include "./inc/$filename";
} else {
    include "./inc/uvod.php";
}

Jako základ stačí, ale my se přece nebudeme spokojení s žádným ořezaným řešením, že =o) Výše uvedená konstrukce opět nemyslí na chybová hlášení typu notice: undefined index, stejně tak na error 404 při nesmyslné hodnotě proměnné. Také cesty k souborům, které jsme do teď uváděli relativní konečně zapíšeme absolutními cestami. Zapomněl jsem ještě zdůraznit umístění všech includovaných souborů v podadresáři, čímž ošetříme zacyklení typu index.php?page=index.

Nejdříve otestujeme proměnnou funkcí isset, v případě hodnoty false načteme úvodní stránku. Až uvnitř bude kontrola přes file_exists, načteme požadovaný soubor nebo 404ku. Vnořenou podmínku můžeme jednoduše zapsat pomocí ternárního operátoru, a tak bude dynamické načítání stránek vypadat ve finále třeba takto :

if (isset($_GET['page'])) {
    include file_exists("./inc/{$_GET['page']}.php") == true ? 
        dirname(__FILE__)."/inc/{$_GET['page']}.php" : 
        dirname(__FILE__)."/inc/404.php";
} else {
    include dirname(__FILE__)."/inc/uvod.php";
}

Unikátní titulek pro každou stránku, řešení problémů

Bohužel, dynamická změna obsahu nestačí, je také vhodné tisknout každé podstránce unikátní titulek, keywords či description. Jestliže i hlavičku a patičku stránek máme v dalších souborech, můžeme předpokládat strukturu stránek podobnou následující:

include dirname(__FILE__).'/header.php';

if (isset($_GET['page'])) {
    include file_exists("./inc/{$_GET['page']}.php") == true ? 
        dirname(__FILE__)."/inc/{$_GET['page']}.php" : 
        dirname(__FILE__)."/inc/404.php";
} else {
    include dirname(__FILE__)."/inc/uvod.php";
}

include dirname(__FILE__).'/footer.php';

Pro náš účel použijeme asociativní pole, kde každé hodnotě proměnné přiřadíme řetězec, který následně vytiskneme do titulku respektive do keywords / description. Podmínka bude stejná jako pro funkci include, akorát bude jen vypisovat konkrétní položky pole. Funkci definujeme ještě před načtením souboru header.php, ve kterém ji zavoláme.

function titulek() {
    $title = array(
        'kontakt' => 'Kontakt',
        'kniha-navstev' => 'Kniha návštěv'
    );

    if (isset($_GET['page'])) {
        echo file_exists("./inc/{$_GET['page']}.php") == true ? 
            "Můj web | ".$title[$_GET['page']] :
            "Můj web | Soubor nenalezen";
    } else {
        echo "Můj web | Úvod";
    }
}
echo '<title>';
titulek();
echo '</title>';

To by bylo snad vše, co jsem na srdci měl, a pro ty z vás, kteří by si chtěli stáhnout těch pár souborů, na kterých jsem toto testoval nabízím zip archív ke stažení.

Ukázka: download

Facebook Twitter Google+

Komentáře k článku "PHP od začátku: dynamické skládání stránek funkcí include"

Gravatar
Tomas 27. 1 2008, 21:00
1/15 Neděle 27. Ledna 2008, 21:00  |  Firefox, Windows XP

super článok :)
Ale
&quot;Můj web | &quot;.$title[$_GET['page']] :
nemá byť
&quot;Můj web | &quot;.$title[$_GET['page']] ;
%2

Gravatar
Mike 27. 1 2008, 21:06
2/15 Neděle 27. Ledna 2008, 21:06  |  Opera, Windows XP

dikec, ale dvojtečka je tam správně %5 jedná se o ternární operátor, ten samý zápis pomocí if / else by vypadal takto :

if (file_exists("./inc/{$_GET['page']}.php") == true) {
echo "Můj web | ".$title[$_GET['page']];
} else {
echo "Můj web | Soubor nenalezen";
}

Gravatar
Tommy 28. 1 2008, 17:21
3/15 Pondělí 28. Ledna 2008, 17:21  |  Firefox, Windows XP

Já pro titulek používám trochu odlišnou funkci (načtu první řádek includovaný stránky a z toho vyberu nadpis), ale tohle je asi pro začátečníky lepší%1

Gravatar
Mike 28. 1 2008, 18:06
4/15 Pondělí 28. Ledna 2008, 18:06  |  Opera, Windows XP

[3] Tommy: také dobrý nápad, mě by tohle nenapadlo. dík %5

Gravatar
vasava 9. 3 2008, 11:00
5/15 Neděle 9. Března 2008, 11:00  |  Firefox, Windows Vista

Možno to sem nepatrí, ale napr. na zmenu <title> bez potreby indexácie možno použiť toto:

var titulok = window.document.title;
function titulok(nazov){
novy = nazov+ " - " +titulok;
window.document.title = novy+" ";
}

a niekde v includovanom súbore bude:

<script>
titulok('Gbook');
</script>-;

Gravatar
Mike 9. 3 2008, 13:28
6/15 Neděle 9. Března 2008, 13:28  |  Opera, Windows XP

[5] vasava: patř :) také dobrý nápad, jenže to má jedno velké ALE : titulek, jako jeden z nejdůležitějších elementů pro vyhledávače je vhodné mít 100% přístupný. uživatel může mít vypnutý js, robot to nepřečte vůbec. dynamická změna v php titulek vytiskne vždy, všude %0

lze vyřešit např. jako v šablonovacím systému :

&lt;% TITULEK='Gbook' %&gt;

&lt;?php
function replace_title($arg, $replace) {
return $arg = ereg_replace(&quot;&lt;% TITULEK='(.*)' %&gt;&quot;, $replace, $arg);
}

$file = implode(file(&quot;./inc/$_GET[page].php&quot;));
$titulek = replace_title($file, &quot;1&quot;);

echo replace_title($file, &quot;&quot;);
?&gt;



další možnost (snad mám ten regulár dobře...) %0

Gravatar
nesro 17. 8 2008, 22:03
7/15 Neděle 17. Srpna 2008, 22:03  |  Firefox, Linux

Ahoj, chtěl bych se zeptat, jak je to vyřešený na webu s titulkami, češtinou a databází. Dělá mi problém, že v URL bude např. "neco.cz/clanek/jak-kun-pel-ody/" a pak titulek bude "Jak kůň pěl ódy." a pak třeba jakým způsobem to ukládat do databáze. Děkuju moc %0

Gravatar
Mike 18. 8 2008, 21:27
8/15 Pondělí 18. Srpna 2008, 21:27  |  Opera, Windows XP

[7] nesro: ahoj, no musíš mít v tabulce další sloupec, kde bude uložený ten pěkný řetězec co se zobrazi v url. takze další sloupeček s řetězci typu "jak-kun-pel-ody".

ty vygeneruješ automaticky z titulku, můžeš použít funkci, kterou jsem už za tímto učelem napsal a prezentoval :

http://mike.treba.cz/vesele-vanoce-a-spoustu-funkcnich-skriptu-pod-stromecek/

Gravatar
nesro 19. 8 2008, 07:59
9/15 Úterý 19. Srpna 2008, 07:59  |  Firefox, Linux

[8] Mike: Děkuju moc %5

Gravatar
Pavel 12. 5 2009, 22:02
10/15 Úterý 12. Května 2009, 22:02  |  Firefox, Ubuntu

[3] Tommy:
A jak by se to pak dalo do zde prezentovaného příkladu? Rád bych to použil. Díky

Gravatar
Mike 20. 5 2009, 08:27
11/15 Středa 20. Května 2009, 08:27  |  Opera, Windows XP

[10] Pavel:

$file = file_get_contents('tady je soubor, co se má includovat');
$nadpis = ereg_replace("<h1>([^</h1>]+)</h1>", '\1', $file);



Takhle nějak, možná ten regulár nemám z hlavy správně, ale řešil bych to tímto způsobem. Ne první řádek, ale vzít prostě H1.

Jinak první řádek je jednoduchý :

$file = file('soubor k nainkludování');
echo $file[0]; // první řádek

Gravatar
Petr 2. 6 2009, 13:45
12/15 Úterý 2. Června 2009, 13:45  |  MSIE, Windows XP

Ahoj, jak můžu ještě includovat ke každé stránce, pokud má, například css styly? Nemůžu na to za boha přijít%0

Gravatar
Mike 6. 6 2009, 17:18
13/15 Sobota 6. Června 2009, 17:18  |  Opera, Windows XP

[12] Petr: podmíněnému inkludování stylů bych se z principu vyhnul. Obrovským způsobem to znepřehlední budoucí editaci html a stylů. Raději si podstrany označ unikátním identifikátorem například pro <body> a následně ve stylech piš definice pro body#podstrana div { } atd.

Pokud je to ale nutné, pak můžeš zkopírovat pravidlo pro tištění titulku, akorát tedy s tou změnou, že se bude tisknout odkaz na css soubor.

Gravatar
Ondra 20. 9 2015, 02:30
14/15 Neděle 20. Září 2015, 02:30  |  Firefox, Windows

Ahoj, zajímalo by mě jestli by šlo nějak jednoduše vyřešit include, když bych měl ve složce "inc" více podsložek a teprve v nich jednotlivé stránky. Předem děkuji za odpověd.

Gravatar
Mike 21. 9 2015, 12:16
15/15 Pondělí 21. Září 2015, 12:16  |  Opera, Windows 8.1

ahoj, samozřejmě ano, akorát ukázkový systém, co tu mám by se musel hodně upravovat : v GET proměnné by pak byla částečná cesta, tedy např. www.neco.cz/kategorie/dalsi/ by referovalo na soubor "inc/kategorie/dalsi.php"

ale řekl bych k tomu asi tohle: jakmile máš tak obsáhlý web, že už potřebuješ v INCu podadresáře, je lepší na to povolat silnější kalibr: databázi.

Přidat komentář







Nevím, kolik to je
Parak simati, Muballit mitte, Nergal allatu mellamu mesaru, La tapallah Annuaki, Kettu Puluthu qillatua