Vytvoření přátelského URL

Školení, která pořádám

Především kvůli vyhledávačům, ale zčásti i kvůli uživatelům je populární používat přátelská URL. Místo clanek.php?id=12 se tedy používá např. kde-nas-najdete/. Přepis URL může zajišťovat např. mod_rewrite, vytváření správných URL je vhodné nechat na zkušeném uživateli, často se ale generují jednoduše z nadpisu – nejsou pak sice tak úderné, jak by mohly být, ale zase s tím je nejméně práce.

Přestože URL může obsahovat znaky s diakritikou (což používá např. Wikipedia), bývá zvykem ji odstranit a v URL nechat jenom písmena, čísla a oddělovač. Pro ten se nejčastěji používá pomlčka, protože podtržítko Google chápe jako spojovník (mysql_fetch_assoc bere jako jedno slovo, mysql-fetch-assoc jako tři).

Odstranění diakritiky se obvykle provádí vytvořením funkce obsahující výčet znaků s diakritikou a jejich varianty bez diakritiky. Následný převod zajišťuje např. funkce strtr. To není příliš elegantní – převodní tabulku jednak musíme ručně vytvořit a pokud se nechceme spokojit se znaky obvyklými v češtině, ale chceme převádět např. i cizí jména, bude poměrně obsáhlá a dá hodně práce, aby počítala se všemi znaky.

Mnohem elegantnější řešení nabízí funkce iconv sloužící k převodu kódování. Pokud k cílovému kódování připojíme //TRANSLIT, budou se nepřevoditelné znaky aproximovat (při použití //IGNORE se ignorují, jinak převod při nalezení prvního nepřevoditelného znaku skončí). Pro spolehlivou funkčnost je potřeba nastavit proměnnou LC_CTYPE funkcí setlocale na kódování UTF-8, např. tedy cs_CZ.utf-8.

<?php
/** Vytvoření přátelského URL
* @param string řetězec v kódování UTF-8, ze kterého se má vytvořit URL
* @return string řetězec obsahující pouze čísla, znaky bez diakritiky, podtržítko a pomlčku
* @copyright Jakub Vrána, http://php.vrana.cz/
*/
function friendly_url($nadpis) {
    $url = $nadpis;
    $url = preg_replace('~[^\\pL0-9_]+~u', '-', $url);
    $url = trim($url, "-");
    $url = iconv("utf-8", "us-ascii//TRANSLIT", $url);
    $url = strtolower($url);
    $url = preg_replace('~[^-a-z0-9_]+~', '', $url);
    return $url;
}
?>

V řetězci nahradíme každou posloupnost znaků jiných než podtržítko, číslo nebo písmeno (\pL) pomlčkou, kterou ze začátku a konce řetězce následně odstraníme. Řetězec převedeme do kódování us-ascii a na malá písmena. Na závěr odstraníme všechny znaky kromě povolených (protože např. á se při transliteraci převede na 'a).

Podotýkám, že sekvence \pL, která je pro převod také podstatná, je k dispozici až od PHP 4.4.0 a 5.1.0 a funguje pouze se řetězci v kódování UTF-8 při použití modifikátoru u.

Pokud bychom stejný problém chtěli vyřešit už na straně klienta v JavaScriptu, tak se musíme spokojit s primitivnějším postupem:

<script type="text/javascript">
var nodiac = { 'á': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'ě': 'e', 'í': 'i', 'ň': 'n', 'ó': 'o', 'ř': 'r', 'š': 's', 'ť': 't', 'ú': 'u', 'ů': 'u', 'ý': 'y', 'ž': 'z' };
/** Vytvoření přátelského URL
* @param string řetězec, ze kterého se má vytvořit URL
* @return string řetězec obsahující pouze čísla, znaky bez diakritiky, podtržítko a pomlčku
* @copyright Jakub Vrána, http://php.vrana.cz/
*/
function make_url(s) {
	s = s.toLowerCase();
	var s2 = '';
	for (var i=0; i < s.length; i++) {
		s2 += (typeof nodiac[s.charAt(i)] != 'undefined' ? nodiac[s.charAt(i)] : s.charAt(i));
	}
	return s2.replace(/[^a-z0-9_]+/g, '-').replace(/^-|-$/g, '');
}
</script>

Viz také Transliterace azbuky.

Jakub Vrána, Řešení problému, 13.3.2006, diskuse: 177 (nové: 0)

Diskuse

Marek Prokop:

Mohu se zeptat, proč je URL kde-nas-najdete/ lepší pro vyhledavače než clanek.php?id=12? Mně to z hlediska vyhledavačů připadá úplně stejné.

Tim:

Vyhledavacum je to asi jedno, ale pro uzivatele byva mnohem prijemnejsi, kdyz ma v url treba /clanky/z-domova/zase-snezi/ nez nejake zobraz.php?katerie=1&sekce=23&polozka=3456.

neki:

Vyhledavačům je to asi stejně putna, jako uživatelům.

Vyhledavače na obsah URL v současné době více-méně kašlou, uživatelé taktéž.

Vyhledavač si hezké adresy nepamatuje o moc lépe než ty nehezké, uživatel stejně tak.

Mírná podobnost by tu byla.

Birkof:

Vyhledavacum je to jedno, ale ne uzivatelum, kteri hledaji treba na google a pouziji operator inurl: napr.: "inurl:vytvoreni-pratelskeho-url". Jinak je to asi sumak, neda se ani moc oponovat s tim, ze se to lepe pamatuje, protoze si stejne nikdo nepamatuje, jak se jednotlive stranky jmenuji.

mekele:

nezertuj... uzivatelu, kteri dokazi parametrizovat google query znam ve svem okoli asi 3

Ivan:

Autor mal zrejme na mysli, ze lepsie je mat v URL klucove slova ako id=12 a pochybujem, ze na to kaslu, ako pise Tim.

Rejpal:

A k cemu je SEO? Jistí třipísmenkoví odborníci na tom vydělavají a říkají, že je lepší mít cool url atd...

Nebo je SEO na prd a pár lidí na něm jen vydělává?

pojízdná kočka:

Na Intervalu vyšel rozhovor se třemi předními (jak ty říkáš třípísmennými) odborníky na SEO (jsem líná to hledat) a vypadlo z nich, že pouze 9 % toho, jak vyhledávače vyhodnocují, je o vnitřních faktorech, a přátelská URL tvoří jen zlomek z oněch 9 %.

ondrej:

protoze jsou v tom klicova slova, ze by SEO?

ikona Jakub Vrána OpenID:

Opravdu to nebyl nejšťastnější příklad. Lepší příklad by byl třeba obrana-proti-sql-injection VS ?id=120.

kriplozoik:

stránku "kde nás najdete" má skoro každá firma, organizace nebo společnost. Kdybych to zadal do Googlu, vyběhne jich dva a pul milionu, z čehož to, co hledám, bude nějakej 1'985'429tej odkaz.

A vůbec, zadávat do Googlu "kde nás najdete" je blbost.

Aleš Halfar:

Pane Prokop, web na který tady odkazujete má lidsky čitelná url a vím, že se v této oblasti pohybujete více než dobře.. Nechtěl byste nám k tomu napsat něco více..? Díky

Jan Bažant:

Osobní názor: Já url, ze které rámcově poznám o čem stránka je, vítám. A co je dobré pro uživatele, je dobré i pro vyhledávače ;-)
Ale samozřejmě je důležitější to, co je v článku psáno, než to, jakou má url.

Trupík:

K čemu? Mít v url klíčová slova ne? Neřelk bych, že na to vyhledávače kašlou.
BTW, v ASP.NET to jde taky
http://trupik.aspweb.cz/programovani/csharp-…-aspnet.aspx

Tomas Hodbod:

Re: Marek Prokop:
URL ../kde-nas-najdete/ z hlediska klic.slov lepsi nez URL ../clanek.php?id=12 prilis nebude. O hodnote URL ../zdravi-vyziva/ oproti ../clanek.php?id=12 asi lze jenom polemizovat.

Ale z vlastni zkusenosti bych rekl, ze friendly-url (ktere se tvari jako staticke) maji vyhledavace radeji predevsim z toho duvodu, ze je lepe (rychleji) indexuji nez adresy dynamicke s parametry v URL.

Marek Prokop:

Ano, Tomáši, to jsem tím chtěl říci. URL kde-nas-najdete má přínos jen pro uživatele, z hlediska SEO je k ničemu. Je dost nešťastné, že se SEO často redukuje jen na technické prostředky, a zapomíná se, že mnohem důležitější je obsah -- i v případě URL.

ondrej:

no ale zrovna seznam.cz mam pocit hraje hodne na hezka url a posouva je vyse

ikona spaze:

A kdo bude hledat klicova slova "kde", "nas", "najdete"?

ondrej:

no a vsechny ostatni hledat budou ("vysavace", "pocitace")
je videt ze seznam ukazuje nahore ty co maj slovo v url

a asi ne jen seznam

adrive:

Mne ta transliterácia nič nerobí. Môžete ma nakopnúť, kde by mohla byť chyba? žiadne á sa nenahradí za 'a, ale úplne sa vynechá.

Díki

ikona MISHAK:

No jedno to není, těžko ale posoudit jestli je výhodnější při změně struktury webu přeindexovávat z indexů článků na názvy nebo naopak.

Varianta s CoolURL mi příjde lepší i z hlediska bezpečnosti a přehlednosti.

Ještě jedna věc: V době "rychlého internetu/TeleComu" je stále nejdůležitější tag title resp. titulek a adresový řádek je hned pod ním ;-)

S tou indexací bych si tak jist nebyl rychleji není lépe a naopak. A jak expert(i) z H1 tvrdí, že se má v CoolURL slovo oddělovat znakem - (mínus) a ne _ (podtržítkem), což je vlastně spojovací znak (odkojenci pascalu máme jiný názor). Takže je to buď chytrý marketingový tah, nebo pravda (jinak by to nemělo smysl... i když co má...)

ikona Jakub Vrána OpenID:

Nechápu část začínající "A jak expert(i) z H1 tvrdí". V článku je přeci uvedeno totéž, proč to je i v komentáři?

ikona MISHAK:

To je jen osobní ftípek narážející na jejich poučování :)

Leo:

Muzu pridat vlastni zkusenost s pouzitelnosti URL pro lidi. Potreboval jsem si zapamatovat adresu konkretniho clanku na intervalu, driv tam bylo cislo (asi id, uz nevim), a ted je tam dlouhatansky nazev clanku se slovy oddelenymi pomlckami. Sice hezky, ale nezapamatovatelny. Osobne se mi libi kombinace, kdy se na zacatku objevi cislo (a staci pro zadani URL) a za nim je teprve to kecani pro vyhladavace, neco jako

www.example.com/1345-jsou-dlouhe-url-k-necemu

pricemz funguje i

www.example.com/1345

Leo

l:

to se povazuje za chybu, protoze pak je mozne vytvorit silene adresy typu:

www.example.com/1345-karel-gott-je-gay

ikona Jakub Vrána OpenID:

www.example.com/1345-cokoliv je v tom případě samozřejmě nutné následně přesměrovat na www.example.com/1345-spravne-url. Ale např. Novinky.cz to mají špatně.

uzivatel:

Cislo je vseobecne lahsie pamata.
415-nazov-clanku je jedna z najlepsich moznosti tvorenia odkazu, pretoze sa velmi lahko z toho da zistit cislo clanku pouzitim funkcie intval(). ak narazi na prvy znak nevyhovujuci ciselnej hodnote tak dalej pokracovat nebude.
cize hned dostanem cislo 415 a nemusim to robit cez zlozite regularne vyrazy alebo rozdelovanim na polia.
toz moj prispevok :)

uzivatel:

a samozrejme. cisla clankov sa nemenia. pricom nazvy ano. a to je najvacsia chyba pri pouziti SEO. ak premenujem nazov clanku  tak vsetko co uz zaindexoval vyhladavac alebo mam v pamati prehliadaca mozem poslat viete kam ;)
ale ID clanku tazko budem menit

kriplozoik:

A kde přesně použiješ tu intval()? V php kódu? Asi sotva.
Navíc, adresa "/123-cokoli" to není tak úplně jednoznačná (resp. není jednoznačné, že je nejlepší). Představ si, že jsi v cizím internet café a máš do adresového řádku vyťukat chtěnou URL. Možná si zapamatuješ nadpis článku, možná budeš schopen ho přepsat do "cestiny" a mezery nahradit pomlckama, ale pamatoval si i to dlouhý číslo? Těžko, Anežko.

ikona Jakub Vrána OpenID:

Pokud se přepis realizuje přes mod_rewrite, což je obvyklá volba, tak jsou "složité regulární výrazy" v ceně. Zbytek URL je navíc potřeba taky získat kvůli zmíněné kontrole nesmyslného URL.

kriplozoik:

tak je jde vytvořit - no a co? pokud občas nějakou takovou adresu známý známému předá v mailu nebo v icq (a pokud se i tak přesměruje správně), kde je problém?

Hever:

iconv se, mám pocit, musí nějak přiinstalovávat, nemám pravdu? http://www.php.net/manual/en/ref.iconv.php

Hezká URL opravdu nepomahají k SEO? Já myslel, že ano.

I kdyby něměly v SEO smysl, myslím, že uživateli mohou pomoci, například teď se mrknu do adresního řádku a hned vím, k jakému článku vlastně ten komentář píšu. Další výhoda se jeví u ruzných indexovacích udělátek .. když vím, že lidé hodně klikají na ?id=452, moc mi to ke štěstí nepřidá.

A ještě: například v němčině by se měly některé znaky přepisovat do bezdiakritické verze do dvou znaků (např. "a s dvojtečkou nahoře" by se mělo v případě německého jazyka přepisovat jako "ae") ... a tím si iconv předpokládám neporadí ..?

ikona Jakub Vrána OpenID:

Hezká URL SEO pomáhají, Marek Prokop asi narážel na nevhodně zvolený příklad (lidi nehledají "Kde nás najdete").

ä se přepíše na "a, celá tabulka je třeba na http://cvs.sourceforge.net/viewcvs.py/libiconv/…?view=markup.

PD:

Tak se koukni o 2 centimetry výš na horní okraj okna prohlížeče - máš tam TITULEK stránky, který by měl jaksi z principu být ještě lepším vodítkem, "kde jsi", než debilní URL.

Pubso:

K tým adresám...
http://vyhledavace.info/seo-faq/16/seo-url

Vita:

Mohl byste sem dat priklad jak prevest url clanek.php?id=12 na kde-nas-najdete/? Nejak jsem to z toho mod_rewrite nepochopil. Dekuji

ikona Jakub Vrána OpenID:

Do tabulky s články přidáte další sloupec `url`, mod_rewrite nastavíte tak, aby kde-nas-najdete/ převedl např. na clanek.php?url=kde-nas-najdete a v clanek.php získáte článek podle tohoto parametru.

Vita:

Mohl byste dat jeste kousek kodu porad me to nejak nemuze nakopnout ;-). Proc tam musim pridavat ten dalsi sloupec? Na co je mi teda ta funkce na odstraneni diakritiky, kdyz uz to muzu do databaze zadat rovnou v tom formatu v jakem chci tzn. bez diakritika a s pomlčkama.

ikona Jakub Vrána OpenID:

Funkce slouží pro automatické vytvoření URL z nadpisu. Výhody a nevýhody ručního řešení jsou popsány na začátku článku.

Vita:

Aha tak to jsem nejak prehledl omlouvam se. Je tedy mozne mod_rewrite nejak nastavit primo v kodu PHP? Co kdyz mam stranky na hostingu a tam nemam pristup na nastaveni Apache.

ikona Jakub Vrána OpenID:

Ne. mod_rewrite je modul Apache a je nutné ho nastavit v konfiguraci Apache (např. v .htaccess). Pokud vám hosting mod_rewrite zapnout nedovoluje, zvolte jiný, nabídka je široká.

Problém s přepisem URL se dá vyřešit i přes chybovou stránku, takže pokud vám hosting dovoluje nastavit alespoň tu, tak to řešitelné je.

Vita:

Mohu Vás tedy jeste pozadat jaky kod mam zadat do .htacces jeste jsem ho nepotreboval pouzit tak nevim jak nato. Chtel bych se pokusit o pratelska url a jinak se mi to asi nepodari :-). Dekuji za veskere informace.

Vita:

Neco jsem nasel. Myslim ze to pomuze i ostatnim. Kazdopadne diky za info.
http://seky.nahory.net/2004/12/staticke-stranky/

Lukas Mach:

Pokud nekomu pripada pozadavek na PHP 4.4.x prilis omezujici a pritom se mu opravdu nechce sestavovat konverzni pole pro strtr, muze se podivat do zdrojoveho kodu textpatternu na funkci dumbDown() v souboru txplib_misc.php a na ini soubor i18n-ascii.txt, oboji v adresari lib.

Osobne povazuji za pekne, kdyz jsou ze zkratek odstraneny pomlcky. Vetsinou se z "firma s.r.o." stane "firma-s-r-o", pritom "firma-sro" je asi hezci.

Fak:

zajímalo by mě co s takovým vietnamským řetězcem, protože tahle funkce funguje dokud tam nepřijde něco jako toto:
"đạo của Khmer Đỏ"
to bohužel vyhodí jen "d" :(
při použití //IGNORE to vyhodí dokonce už "o-ca-Khmer-"
to znamená, že si budu muset sehnat celou vietnamskou abecedu?:((

Díky za rady

ikona Jakub Vrána OpenID:

Problém je v tom, že ạ a další vietnamské znaky nemají v libiconv transliteraci. Zkusil bych poslat patch třeba na bug-gnu-libiconv@gnu.org, ale je to běh na dlouhou trať.

Fak:

to asi opravdu nemá cenu, pokud by už nějaký release vydali, tak bych musel čekat, než ho aplikují na hostingu...

Už jsem si našel - snad - všechny takové vietnamské znaky a hurá do pole...

kriplozoik:

Ale no dobře. Abych zase nebyl tak neurvalý, tak bych se místo toho mohl podělit o druhé řešení -

URL sice automaticky ukládat, ale v administračním rozhraní ho nabízet k editaci. Přidaná agenda odkazů bude v podstatě nulová (administrátor ho může ignorovat), dokud generované URLs vypadají pěkně. V případě jánevim tradiční čínštiny pak nastává ještě starost o zvolení latinkové URL.

(I když podle mě, v případě tradiční čínštiny, bych řekl, že by byly skoro lepší adresy typu /?article=12345, co myslíte?)

kriplozoik:

V kolika procentech případů je v názvu článku "ạ"?
Statisticky bezvýznamné.

p.s. mimochodem, nevím jak je to u exploderáků, ale uživatelům firefoxu stačí napsat jedno dve písmena adresy serveru a vybrat si z nabídky ten správný článek, který v minulosti načetli, tím, že se dívají do pravé části vysouvacího menu, kde se jim vypisuje to, co odpovídá <title> stránky. No nevím, ale myslím, že (zvlášť pokud něco takového má i M$ Exploder, tak) tím friendly URL podstatně ztrácejí na tom argumentu, že se dají lépe zapamatovat (protože si je stejně nikdo nesnaží pamatovat a vybírá je výše zmíněným způsobem)

ikona Jakub Vrána OpenID:

Statisticky bezvýznamné to je jen do té doby, než zprovozníš vietnamskou verzi webu.

kriplozoik:

Zkus z hlavy vyjmenovat 5 jakýchkoli českých stránek s vietnamskými lokalizacemi...

zbynek riha:

to s tim ale nema nic spolecneho :D

kriplozoik:

Ale má. (ale to už je jiná bitva - (akademické vs. praktické)) :]

Btw. v článku to je naznačeno, ale ne na plná ústa řečeno, že v případě JavaScriptu to primitivnější řešení zřejmě nikdy pokryje všechny případy. Ať se koukám, jak se koukám, např. ono "ạ" tam nevidím.

onge:

to sice nepokrije, ale zase se to dela v momente, kdy pises nazev clanku a mas moznost pripadne nesrovnalosti opravit. JavaScript nema byt spasne reseni, ma ulehcovat praci, no a to tohle bezpecne dela:)

kriplozoik:

Tak to si tedy nerozumíme. Nevidím nikde v Jakubově příspěvku, že javascriptové řešení něco dělá, "když píšeš název článku." A i kdyby ano, tak to opět nebude dělat dokonale, protože ono vietnamské ạ přeloží blbě (resp. vůbec). V takovém případě mi přijde lepší provést (pořádnou) transliteraci na straně serveru, a nedrbat se ještě navíc s nedokonalým nahrazováním v javascriptu. V takovém případě javascript práci neulehčuje ale naopak přidělává :-(

uzivatel:

Zdravim.
Tak mam este jeden problem.
ako vyriesit prevod do ASCII ak je u iconv() pouzita kniznica glibc, ktora to nejako nedokaze
pricom co mam na locale libiconv tak tej to nerobi problem

ikona Jakub Vrána OpenID:

Zkus před převodem zavolat <?php setlocale(LC_CTYPE, "cs_CZ.utf-8"); ?>.

David Grudl:

Podotýkám, že tohle nefunguje vždy.

ikona dgx:

> Podotýkám, že sekvence \pL, která je pro převod také podstatná, je k dispozici až od PHP 4.4.0 a 5.1.0 a funguje pouze se řetězci v kódování UTF-8...

Jakube, když už provádíš transliteraci na ASCII přes iconv, není lepší vkládání pomlček umístit až za iconv a vyhnout se tak použití \pL? Padlo by tak nepříjemné omezení na PHP 5.1.0

ikona Jakub Vrána OpenID:

Problém je v tom, že transliterace do řetězce vloží nadbytečné znaky, které je následně potřeba odstranit. Např. "bá" se převede na "b'a" a následný převod na pomlčky z toho udělá "b-a", což je samozřejmě špatně.

Ve starších verzích PHP by se dal udělat výčet znaků, které se při transliteraci používají, nahradit je za pomlčky předem a po převodu je odstranit.

ikona dgx:

Pravda, pravda.

Řešívám to tak, že pomlčkama nahrazuji pouze mezery a ostatní "bordel" odstraním, což pak funguje i s transliterací před zpracováním. Ale nejde o tak obecné řešení.

Paces:

Myslím, že přáteslká url jsou vždy lepší pro uživatele. Třeba když citujete (např. v diplomce) z weborých stránek, tak lépe v seznamu literatury vypadají smysluplné url než jen stejná url s rozdílnými ID.

PD:

Asi tak stejně jako v seznamu literatury budou hůře vypadat

Sborník LŠ 2005, s.237
Sborník LŠ 2006, s.246
Sborník LŠ 2007, s.112

??

Možná to v seznamu vypadá lépe, když jsou tam "friendly URL", ale pokud už nějaký chudák bude mít tištěnou verzi a bude z ní muset ta URL opisovat, tak

web.cz/?id=135
naťuká rychleji a s méně překlepy, než
web.cz/historie-integrace-romskeho-entika-do-majoritni-spolecnosti-p3y

Kapiš?

kozotoč:

pokud to píšeš na počítači a ne na psacím stroji, tak adresy napíšeš stylem Ctrl+C, Ctrl+V. Bez překlepů, úplně stejně rychle. A opravdu to vypadá lépe.

PeTa:

Měl bych prosbičku, spíš se týkající samotného mod_rewrite:

na localhostu (winxp,apache2.2.0(+php+mysql)) se mi těžce nedaří rozběhnout mod_rewrite (paradoxně na webhostingu je vše OK)

modul je správně načten a funkční (ověř. např. pro ErrorDocument 404 / missing.html), ale pokud provedu RewriteRule (syntakticky snad v pořádku?):

RewriteRule ^(.*)\.html$ /index.php?wiev=$1 [L,QSA]

vyflushne mi to jen prázdný dokument. Čiže podstrkovaný dokument to najde, ale nezobrazí. Pokud odkážu na neRewritovaný soubor, hodí to správně 404. Předpokládám, že mám něco špatně v lokálním httpd.conf, ale už jsem s rozumem v koncích. Jo a krom toho se někam ztratí REFERER.

Dík, pokud někdo víte, kde mám chybu. PeTa

ikona dgx:

1) Zkus si do index.php vložit <?php phpinfo() ?> a ověř, zda máš všechny parametry předané správně (wiev má být asi view, ne?)

2) Zkontroluj cesty, pokud nastavuješ pres .htaccess, aby by nemělo být použito /index.php ale index.php.

PeTa:

tak jsem z toho phphinfo() nezmoudřel:
REDIRECT_QUERY_STRING     wiev=faq
REDIRECT_URL     /Pages/h-xl/faq.html
QUERY_STRING     wiev=faq
REQUEST_URI     /Pages/h-xl/faq.html
SCRIPT_NAME     /Pages/h-xl/index.php
_REQUEST["wiev"]    faq
_SERVER["REDIRECT_QUERY_STRING"]    wiev=faq
_SERVER["REDIRECT_URL"]    /Pages/h-xl/faq.html

-  jasně, mělo tam být správně "vjú", musím to opravit ve všech skriptech. Lomítko před indexem už v rewrite nemám. Stejně je ale nadále výstupem prázdný list.

ikona dgx:

V tuto chvíli máš jistotu, že se skutečně načítá skript /Pages/h-xl/index.php s parametrem wiev=faq, a tedy problém v mod_rewrite není. Tedy je na čase hledat problém jinde.

PeTa:

To dgx:
Dík za radu. Už mi to maká. Máš pravdu, že v mod_rewrite chyba nebyla. Problém byl úplně někde jinde (i když stejně tak nepochopitelný). Stránka index.php obsahovala někde ve struktuře reklamní banner reprezentovaný skriptem: <script type='text/javascript'>/* <![CDATA[ */
bla bla bla //]]></script>, který buď způsoboval zacyklení mod_rewrite, nebo nějakou jinou neplechu. Každopádně výstupem byl buď prázdný list, nebo shozený Apache. Jakmile jsem CDATA vyhodil, pracuje vše OK. Jen jsem to hledal 3 dny a důvod proč se to tak chovalo mi uniká dosud.

Peter Kytlica [www.pixo.sk]:

A čo takto radšej napísať článok ako jednoducho napísať mod_rewrite ??

Hľadám to na webe celú noc a konečne keď som si myslel, že to mám, kecá sa tu o blbosti.

ikona dgx:

No, Jakube, šup, napiš článek. Že se nestydíš psát o takových blbostech, když Péťa celou noc hledá něco jiného?

Ján Koštial:

Celkom by ma zaujímalo, ako uspokojivo vyriešiť generovanie priateľského URL na multijazyčných stránkach, kde sú texty uložené v DB a stránky sa generujú podľa zvoleného jazyka. Prevádzkujem stránky, kde generujem obsah cez jediný skript http://www.mojadomena.sk/index.php?stranka=…_parameter=yyy,...]). O tom, či ten spôsob je vhodný alebo nie sa diskutovalo v inej téme, ale teraz o inom.
Povedzme, že predávam lietajúce stroje a chcem generovať priateľské URL. Takže stránku pomenujem http://www.domena.org/lietadla-bezmotorove-jednomiestne.php.
Stránky prevádzkujem napr. v šiestich jazykoch - teda by mala existovať aj stranka http://www.domena.org/aeroplanes-sailplanes-single_seater.php. (A ďalšie štyri v ďalších jazykoch.)
Bolo by dosť od veci aby tie skripty fyzicky existovali aj ako súbory na disku, aj keby len volali nejaký spoločný skript. Totiž otázka znie: Čo keď chcem pridať jazyk? Čo keď chcem rozšíriť sortiment o lode? Ako zabezpečiť, aby tie priateľské URL v rôznych jazykoch spracovával stále ten istý skript? (.htaccess?)

ikona Jakub Vrána OpenID:

Nejjednodušší řešení nabízí mod_rewrite, který slouží právě k přepisu URL. Stačí cokoliv přepsat na index.php a původní URL předat v parametru. Článek o tom vyjde v pondělí.

ikona dgx:

Ne, Jakube, původní URL je nejlepší získat z $_SERVER['REQUEST_URI']. Nemusíš tak vůbec narušit parametry, nedojde ke kolizi atd.

Jinak více než "přepisovat vše" je elegantní "přepisovat vše neexistující". Aby se legalizovaly požadavky na obrázky, styly, skripty atd. Tedy třeba takto:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule . controller.php [L]

ikona Jakub Vrána OpenID:

$_SERVER['REQUEST_URI'] je druhé možné řešení, jen je potřeba nezapomenout na to, že skript musí při zkoumání URL uříznout původní parametry.

Pokud se přepisuje vše neexistující, je potřeba zabezpečit skripty proti přímému spuštění. Proto raději přepisuji vše a to, co se přepisovat nemá (favicon.ico, robots.txt, static/) explicitně vyjmenuji.

kozoslon:

můžete uvést příklad (kus kódu v .htaccess)?

Tomas:

Pouzivam smerovani vsech .html stranek na index.php pres mod_rewrite preposilam na index.php url jako parametr kde jej
pres explode('/',$_GET['page']); ulozim do pole.

tim muzu mit jazykove mutace s url napr.: www.domena.cz/cz/letadla/bezmotorova-jednomistna.html
www.domena.cz/en/aeroplane/engineless-single.html

neni pak tezke si z mysql vytahnout id stranky plus url pro vsechny jazykove verze tak, ze okdaz na jiny jazyk me hodi stejnou stranku jen v jinem jazyce.

Osobne si myslim ze hezka URL muzou mit vyznam pro vyhledavace pokud vnich uvedete spravna klicova slova.
navic si myslim ze pro SEO je vyhodnejsi mit .html stranku nez .php

Honza:

Zrovna jsem si takovy web napsal. Mám jednu tabulku se "systémovými" údaji o všech článcích, pak pro každý jazyk zvlášťní tabulku (podle mě je to rozumnější řešení než na to mít sloupce v jediné tabulce) a nakonec tabulku pro přepisování adres, kde je PK(id_clanku, jazyk), adresovy_retezec.

Onecar:

Dneska jsem na intervalu četl, že google velmi špatně url, které mají v osbě více než 2 parametry. Proto je lepší vytvářet hezké friendly URL.

jann:

mam problem s iconv("utf-8", "us-ascii//TRANSLIT", $url);
Nepřevede mi to znaky s diakritikou na apostrov a bez diakritiky, ale misto toho to da otaznik (3f hexa)

ikona dgx:

Na některých hostinzích se to stává. V takovém případě je lepší k transformaci použít převodní tabulku (viz http://www.dgx.cz/trine/item/odstraneni-di…-ruznych-kodovani)

jann:

Aha, takže to je chyba hostingu jo? Jsem to právě chtěl na převod nadpisu ve fóru na url a celkem se mi hodilo že to obsahovalo všechny znaky a převyprávělo to třeba & atd... Nikdy člověk neví co zadá uživatel jako nadpis tématu...

Andrew:

Myslím, že tento "problém hostingů" se dá ve většině případů vyřešit nastavením locale na utf8, na což Jakub v článku upozorňuje.
A když jsme u těch převodních tabulek, tak můžeme převést rovnou celé utf8 - tabulky jsou k dispozici. Zabavilo mě to na dlouho si pročítat přepisy všech možných čínských, arabských a já nevím jakých znaků. Soubor je ale kapánek větší. ;-)

jann:

Zjistil jsem v nejakem foru, ze tento problem je pri pouziti knihovny glibc a ze pry s libiconv to funguje spoleglive. Napsal jsem na hosting jestli to vymeni, ale chteli by nejaky odkaz na buglist nebo neco takoveho, nemate nekdo?

vazba:

Pokud máš hosting s glibc, lze to vyřešit tak, že před voláním friendly_url() zavoláš ještě funkci cs_win2ascii() od DGX, viz. http://latrine.dgx.cz/odstraneni-diakritiky-z-ruznych-kodovani

ikona Jakub Vrána OpenID:

Viz http://php.vrana.cz/vytvoreni-pratelskeho-url.php#d-5672.

Gioel:

Chcel by som sa opytat mne ta funkcia nefunguje.. a nesprava sa tak ako by som chcel...
Ukazka:
http://www.powerplaymanager.com/test/test_seo_url.php
Prvy je nazov stranky druhy je URL vytvorena mojou fukciou:
pozriet je mozne tu:
http://diskuse.jakpsatweb.cz/index.php?action=…&topic=43493

abysser:

"Pěkné URL" je především taková hezká "standardizační" forma odkazování. A i když původním záměrem mohla být přehlednost, bezpečnost nebo SEO, určitě je to dobrý návyk a z hlediska lidského myšlení přirozenější předávání parametrů hierarchickým ergo logickým stylem, než psat všude ampersandy, středníky či jiné oddělovače a vyjmenovávat čtenáři všechny názvy GET proměných, které časem třeba změníme, ale naše pěkné "adresářové" URL už tu bude na věky věkoucí ;)...

Já bych uvítal článek spíše psychologicko-filosofický a to takový, který by se věnoval především tedy z toho uživatelského hlediska nejlepší technice potvrzování komentářů proti spamům. Osobně totiž nesnáším rozpoznávání mnohdy nerozpoznatelného textu v obrázku, doplňování rovnic a vyplňování nospam ;). 1. něco vypňovat? 2. kontrolovat v pozadí (keyword/IP blacklist) 3. sekundární potvrzení kliknutím? Jaké je nejlepší z uživatelského hlediska a zároveň bezpodmínečné pro spam toť otázka.

ikona Jakub Vrána OpenID:

Zatím docela dobře funguje automatické vyplňování kontrolní otázky JavaScriptem. Někdo si taky pochvaluje odeslání ve dvou krocích (náhled, dokončení).

dawid:

Warning: preg_replace(): Compilation failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 3

Dobry den nemohl by mi nekdo poradit s touto chybou.... nebo nejake jine reseni.. dekuji

ikona Jakub Vrána OpenID:

Pravděpodobně používáš starou verzi PHP, resp. knihovny PCRE.

ikona SUK:

Aby to vypadalo lepe, je vhodne aby se znaky ani neopakovaly (hlavne ty pomlcky)
<?php
  $title
=preg_replace("/(.)\\1{0,}/","\\1",$title);
?>
//pokud uz to tu nekdo psal, tak se omlouvam ze to opakuji

ikona Jakub Vrána OpenID:

Kde se v kódu ty pomlčky podle tebe budou opakovat? Kód <?php preg_replace('~[^\\pL0-9_]+~u', '-', $url); ?> přeci nahradí jakoukoliv posloupnost nepísmenných znaků jednou pomlčkou.

Tvůj kód naopak třeba z Google udělá Gogle, což jistě nechceš.

ikona SUK:

No jo pravda, sorry.
A uz stejne pouzivam jiny kod :)

Uncode:

Jak muzu prevest retezec "DĚLAT" na "dělat"? S ceskymi znaky je problem.

ikona Jakub Vrána OpenID:

Viz http://php.vrana.cz/prevod-na-velka-pismena.php.

darkcraft:

Dobry den,
predem bych chtel podekovat za kod, ktery mi velmi pomohl, takze - dekuji.
Nasel jsem v nem vsak jeden maly nedostatek. Treba ja delam SEO na webu, ktery pouziva v nadpisech ceska znamenka. Pouzitim vaseho kodu mi tedy vznikl napriklad z retezce "Mapování struktury webového serveru" retezec "mapovn-struktury-webovho-serveru", coz neni moc vhodne, proto jsem si vas kod dovolil vylepsit, uprava je v tom, ze pred vlastnim replacem podle regexpu nahradim diakriticke znaky za nediakriticke. Takze na zacatek vlozim tento kod:

$cz = array("ě", "š", "č", "ř", "ž", "ý", "á", "í", "é", "ť", "ú", "ď", "ů", "ň");
$noncz = array("e", "s", "c", "r", "z", "y", "a", "i", "e", "t", "u", "d", "u", "n");
$url = str_replace($cz, $noncz, $nadpis);

pak mi z jiz zminovaneho prikladu vznikne retezec "mapovani-struktury-weboveho-serveru", coz je podle me mnohem prijatelnejsi..

ikona Jakub Vrána OpenID:

Hlavní náplň kódu je právě v odstranění diakritiky. Stará se o to řádek <?php iconv("utf-8", "us-ascii//TRANSLIT", $url); ?>. Pokud ti nefunguje, máš nejspíš něco špatně (řetězec není v kódování UTF-8 nebo není správně nainstalované iconv). Tvůj kód má tu nevýhodu, že funguje pouze pro české znaky a třeba slovenské ľ mu proklouzne.

darkcraft:

Aha, no mate pravdu, ale potom tedy bude asi chyba v nainstalovanem iconv, protoze retezec samozrejme v UTF8 je..

naco:

melo by pomoci zadat setlocale(LC_CTYPE, 'cs_CZ')

naco:

Rad bych se zeptal, proc pouzivate $url = preg_replace('~[^\\pL0-9_]+~u', '-', $url), kdyz iconv vsechny znaky krome .-_ pismen a cislic ignoruje. Sam pouzivam jednodussi:
$url = ereg_replace('[ ]+', '-', $url);
$url= iconv('UTF-8', 'ASCII//TRANSLIT', $url);
a zatim jsem nenarazil na problem. Ma nekde moje reseni slabinu?

ikona dgx:

iconv utf-8 -> ascii nefunguje správně na řadě (ze zkušenosti spíš většině) hostingů. Do řetězce vkládá znaky jako - ' apod. Ne vždy je to akceptovatelné.

naco:

jasny, diky za odpoved. asi mam stesti na hosting :-)

ikona Čuga:

mel bych drobny dotaz...

nemam text v utf-8... lze funkci upravit pro jine kodovani??? nebo spis jak prevest z Win-1250 na utf-8???

diky za odpovedi

ikona Čuga:

pomoci prevodnich fci od dgx sem prevedl z win-1250 na utf-8...

ovsem dalsi problem :) necekane... ě presoupnul na 283, tak stejne u ř a č (samozrejme s jinymi kody)...

Štěpán Svoboda:

Ještě by možná stálo za doplnění do článku že se musí nastavit locale, jinak při použití TRANSLIT budou akcentovaná písmenka vynechána bez jakékoliv chyby a při použití IGNORE bude vyhozeno notice Ilegal character.

ikona Jakub Vrána OpenID:

Na co by se podle tebe mělo nastavit locale? Mě vše korektně funguje i bez jakéhokoliv nastavování a nevím, že by to s tím mělo co do činění. Uveď nějaký příklad.

Štěpán Svoboda:

heh :) omlouvám se za delší interval...
Pokud nejsou nastavené locale např:

setlocale(LC_ALL, 'cs_CZ.UTF-8');

ale je to fuk - mohou být třweba německá - funguje to stejně. Potvrdilo se mi to po delší době na zcela jiném počítači: Jak jsem psal: Pokud nejsou nastavena locale české a zřejmě i jiné znaky jsou vynechány bez jakéhokoliv varování.

Štěpán Svoboda:

Transliterace totiž závisí na použitých locales. Zkuste si převést "Bürgerlich" s českými locales a s německými.

ikona Honza:

Ahoj, mám problém s preg_replace na jednom hostingu. Např z 'H13a' preg_replace('~[^\\pL0-9_]+~u', '-', $url); vytvořil '13-' . Je to pouze na jednom hostingu, nevíte, kde by mohla být chyba (PHP Version 5.1.6)

ikona Jakub Vrána OpenID:

Příčina bude pravděpodobně v použití knihovny glibc místo libiconv. Řekne ti to phpinfo().

ikona Honza:

Je to glibc. Je tedy nějaká možnost toto napravit?

ikona Jakub Vrána OpenID:

Požádat hosting o změnu. Pokud nevyhoví, tak změnit hosting. Pokud se ti nechce, budeš muset funkci napsat ručně (podobně jako ve verzi pro JavaScript).

ikona Honza:

No s hostingem to právě řešíme a i oni zatím neznají řešení:
"Bohuzel mam k dispozici na
vyzkouseni jiny stroj kde je u iconv take glibc a tim to neni, jelikoz mi ten
vas preg_replace normalne funguje.
Rozdil tam vidim pouze v PHP - 5.1.6 vs. 5.2.0 a v knihovne na regularni
vyrazy PCRE - 6.6 vs 6.7"

Vypadá to, že problém nastává ještě před tím, než se skript dostane k knihovně iconv - ted již v preg_replace... ???

ikona Jakub Vrána OpenID:

No jistě, omlouvám se za zmatení. Nějak jsem si špatně přečetl první příspěvek a místo preg_replace() četl iconv(). S tímhle problémem použitá knihovna samozřejmě nesouvisí.

\pL by nicméně mělo být k dispozici od PHP 5.1.0 a mezi PCRE 6.6 a 6.7 jsem také žádnou opravu související chyby nenašel, takže bych si na to nevsadil. Ale vyloučit to nemohu.

ikona Honza:

Díky Jakube, tak lidé z hostingu už na to přišli:"Problem byl v uvozovkach. Kazde PHP se k
tomu muze stavet jinak, u nas funguje nize uvedena verze."

$url = preg_replace("'~[^\\pL0-9_.]+~u'", '-', $url);

ikona Honza:

Aha, tak zřejmě to sice řeší problém s vymazáním znaků, ale funkce je poté nepoužitelná

ikona Jakub Vrána OpenID:

Uvedený kód je bohužel nesmyslný. Apostrof v tomto výraze slouží jako oddělovač modifikátorů a hledá se tedy regulární výraz ~[^\\pL0-9_.]+~u. S verzí PHP to nijak nesouvisí.

iguana007:

Taky jsem měl problém s regulárním výrazem... pouzil jsem fci takto:
<?php
function prevod_textu_na_url ($url) {
    $url = preg_replace('~[^\\pL0-9_]+~u', '-', $url);
    $url = trim($url, "-");
    $url = iconv("utf-8", "us-ascii//TRANSLIT", $url);
    $url = strtolower($url);
    $url = preg_replace('~[^-a-z0-9_]+~', '', $url);
    return $url;
}
$foo = "Testovací sktipt ěščřžýáíé!?.:.-";
print
prevod_textu_na_url($foo);
?>

coz mi vracelo pouze písmeno p ... pomohla změna fce na toto:
<?php
function prevod_textu_na_url ($url) {
    $url = iconv("utf-8", "us-ascii//TRANSLIT", $url);
    $url = strtolower($url);
    $url = preg_replace('~[^a-z0-9_]+~', '-', $url);
    $url = trim($url, "-");
    $url = preg_replace('~[^-a-z0-9_]+~', '', $url);
    return $url;
}
?>
v podstatě jde jen o změnu pořadí ... ale vyřešilo to můj problém.

Zdraví
LG

Jakub Hejda:

Mám stejný problém, takže používám Vaše řešení.
Snad nemá Vaše řešení nějaké jiné skryté vady :-)

ikona Qwerty:

Já jsem měl ten stejný problém a vyřešil jsem ho prostě IFem, který zajistí použití správného pořadí na hostinzích s libiconv či glibc:

<?php
function friendly_url ($str)
    {
      setlocale(LC_CTYPE, "cs_CZ.utf-8");
      if (ICONV_IMPL=="libiconv"){
        $str = preg_replace('~[^\\pL0-9_]+~u', '-', $str);
        $str = trim($str, "-");
        $str = iconv("utf-8", "us-ascii//TRANSLIT", $str);
        $str = strtolower($str);
      }
      if(ICONV_IMPL=="glibc"){
        $str = iconv("utf-8", "us-ascii//TRANSLIT", $str);
        $str = strtolower($str);
        $str = preg_replace('~[^a-z0-9_]+~', '-', $str);
        $str = trim($str, "-");
      }
      $str = preg_replace('~[^-a-z0-9_]+~', '', $str);
      return $str;
    }
?>

Hexim:

Trochu jsem ji zdokonalil i na prevod z win1250 :-)
<?php
function furl($nadpis) {
$url = StrTr($nadpis, "áäčďéěëíňóöřšťúůüýžÁÄČĎÉĚËÍŇÓÖŘŠŤÚŮÜÝŽ", "aacdeeeinoorstuuuyzAACDEEEINOORSTUUUYZ");
$url = preg_replace('~[^\\pL0-9_]+~u', '-', $url);
$url = trim($url, "-");
$url = iconv("utf-8", "us-ascii//TRANSLIT", $url);
$url = strtolower($url);
$url = preg_replace('~[^-a-z0-9_]+~', '', $url);
return
$url;
}
?>

ikona Jakub Hejda:

V čem spočívá to zdokonalení ?
Na windows-1250 stačí přeci jen první řádek.

korny:

"Přestože URL může obsahovat znaky s diakritikou (což používá např. Wikipedia), bývá zvykem ji odstranit a v URL nechat jenom písmena, čísla a oddělovač. Pro ten se nejčastěji používá pomlčka, protože podtržítko Google chápe jako spojovník (mysql_fetch_assoc bere jako jedno slovo, mysql-fetch-assoc jako tři)."

mam delej web s podtrzitkama..a nasel jsem tohle
http://www.news.com/8301-10784_3-9748779-7.html
ma to tedy nejaky vyznam..(myslim ti pomlcka NEBO podtrzitko)??
Diky za info

TheSorrow:

Není jednodušší převést URL přímo v .htaccess ?

ikona Jakub Vrána OpenID:

Je nesmysl pro každý nově vydaný článek nebo každý nově nabízený výrobek měnit .htaccess.

cucací potřeby:

Inu,
převést přátelská URL na .htaccess (tedy generovat tento soubor skriptem, po každé změně a/nebo periodicky) mi přijde jako řešení:
* neelegantní,
* složitější (zbytečně),
** mimochodem, nerealizovatelné tam, kde skript nemůže vytvářet soubory v daném adresáři
* pravděpodobně s trochu větší režií,
* zřejmě i s méně pohotovou reakcí na změny,
* Pro opravdu mnoho URL (řádově tisíce a víc):
** mod_rewrite na to není stavěný (nepoužitelné)
** je možné, že bude zatěžovat (a ohrožovat) Apache jako takový
** a toto je tedy slabé místo a zneužitelné pro záměrné vytvoření velkého množství URL
* nesystémovost
** je to (zbytečně) závislé na (aktuální) verzi .htaccess
** míchají se tady dvě úrovně: skriptu a webserveru
* dost možná je to i potenciálně nebezpečné (záleží na konkrétním využití, např. přeuložením URL řetězcem obsahujícím \n bude mod_rewrite vše za odřádkováním interpretovat jako další příkaz(y)).

Jako výhody vidím:
* to, že se část výkonu deleguje na Apache (tedy jeho modul mod_rewrite) a
* to, že se při každém požadavku nemusí přistupovat k databázi (to je docela velká výhoda).

Celkově ale nevýhody převažují.
Nedokážu si představit případ, kdy by toto zůstalo jako jediné řešení. Pokud takový případ najdeš, napiš ho sem ;-)

michal:

dnes som to chcel ísť vyriešiť sám, ale akosi sa mi nechcelo, čítal som si blogy, až som sa náhodou dostal sem. idem vyskúšať tento spôsob, dúfam, že bude fungovať.

Gifi:

Dobrý den, již pár dní špekuluji nad jistým problémem. Ani kamarad google mě nedokazal poradit, tak tedy prosím o radu ostřílených vývojářu.

Problém je následující:
mam index.php v documentroot kde pouzivam dotaz kde si pri kazdem vygenerovani banneru provadim dotaz Update tabulka set zobrazeno=zobrazeno+1 where id_vygenerovaneho baneru...s tím by nebyl až takový problém. dotaz a vše kolem funguje.
problém nastává při použití mod_rewrite. kdyz obnovím stránku pri vygenerovani se přičte dva namisto jedna, když jdu na index.php ve složce admin přičte se opět dva... Kdyz vypnu modrewrite tak uz se v adminu nic nepricita. z toho všeho jsme nabil dojmu, kdykoliv volam index.php jak v rootu tak v podadresari admin tak to vzdy projde pres index.php v rotooo.  neslo by zase tak o to pricinani,ale docela si myslim ze to spomaluje cely server dost vyrazne,protoze se nejdrive provedou skrypty z index.php root a pak teprv v adminovi, pokud v adminovi pracuji.

pro ukazku modrewrite:

RewriteEngine On

RewriteCond %{HTTP_HOST} ^tvorime\-web\.cz
RewriteRule ^(.*)$ http://www.tvorime-web.cz/$1 [R=301,QSA]

RewriteCond %{REQUEST_URI} .admin.*
RewriteBase /admin
RewriteRule ^(.*)$ - [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?url=$1 [L,QSA]

Zatím sem se s ničím takovým nesetkal po dvou letech co s phpckem delám..

Jan Mička:

Dnes jsme přešli na verzi PHP 5.2.7 a vaše funkce přestala fungovat... Nedokázal byste poradit prosím?

Warning: preg_replace() [function.preg-replace]: Compilation failed: unknown property name after \P or \p at offset 4

PHP: 5.2.7.
PCRE Library Version: 7.8 2008-09-05

ikona Jakub Vrána OpenID:

Mě to v PHP 5.2.7 funguje. Máte PCRE knihovnu zkompilovanou s podporou UTF-8? Nevím bohužel, jak se to dá zjistit. Slouží k tomu nicméně volba --enable-utf8 při kompilaci pcrelib.

Jan Mička:

No, ale ve verzi predtim to fungovalo i tak jak to bylo - PCRE knihovna se nemenila, jen PHP.

Jan Mička:

PCRE je kompilovano jako --enable-utf8 --enable-unicode-properties ... takze kde jinde by mohla byt chyba?

Michal Orlik:

Mel jsem stejny problem s verzi 7.8...po downgradu vse ok

btx:

stacilo po upgradu na libpcre-7.8 prekompilovat PHP a problem byl pryc (pouzivam gentoo)

ikona Karel Dytrych:

Zkuste třeba toto:

<?php
function tourl ($str)
{
  setlocale(LC_CTYPE, "cs_CZ.utf-8");
  $str = iconv("utf-8", "us-ascii//TRANSLIT", $str);
  $str = preg_replace("~[^\w\d]+~", '-', strtolower($str));
  $str = trim($str, "-");
  $str = preg_replace('~[^-\w\d]+~', '', $str);
  return $str;
}
?>

pojízdná kočka:

chtěla bych se podělit o praktickou zkušenost s "přátelským URL" (pro návštěvníka stránek - ne zas tak přátelské pro programátora).

Komplikace začínají, pokud si správce stránek může URL zvolit (nabídli jsme tu možnost jednomu našemu klientovi) a on ji několikrát využil (některé zboží, které prodává, má lomítko ve svém názvu). V ten moment při načtení stránky zmizely všechny obrázky a stránka se zobrazila bez stylů, nefungovaly externí skripty atd. (Důvod: další lomítka zkonstruovala dodatečné 'virtuální adresáře'.) Jedna cesta by bylo odkazovat všechny zdroje v HTML absolutně, ale to jsem vyhodnotila jako jako špatné řešení, protože např. se změnou domény by na x místech najednou vznikly chybné odkazy.

Jako řešení mě tedy napadlo na začátku skriptu zanalyzovat $_SERVER["REQUEST_URI"], zjistit počet lomítek a tolikrát přidat za sebe řetězec "../", který pak vkládám před každý odkaz (href u <a>, src u <img>, atd) v HTML. Antagonicky k tomu, php funkce pro práci se soubory se samozřejmě 'adresáři', které vznikly přidáním lomítka do adresy, "zblbnout" nenechají (resp. takto vzniklé pseudo-adresáře jsou vůči jejich práci irelevantní).

(snad to pomůže těm, co s tím zrovna zápasí ;-))

ikona Karel Dytrych:

Adresy ještě můžete psát ve tvaru /cesta/s-lomitky.html ... Odkaz je poté absolutní a nezávislý na doméně.

ikona david@grudl.com:

Naopak bych velmi doporučil používat vždy a bez výjimky všechny odkazy absolutní. Vtip je ale v tom, že kromě absolutního URL existuje ještě absolutní cesta. Tedy odkaz bez uvedení domény začínající lomítkem. Takže stačí href="/css/style.css" a je jedno, na jakém místě se stránka nachází.

pojízdná kočka:

a když klient řekne "ty současné stránky hoďte do adresáře 'old'"? V ten moment se historie opakuje a pak bych opět musela projít celý projekt a na desítkách až stovkách místech nahrazovat dopisovat před absolutní cestu tento adresář. To je jeden příklad ze tří (aneb pozor, ještě jsem neskončila ;)). Ten druhý je případ, kdy nějaký projekt, co normálně bude na /index.php testuju a mám (u sebe, na localhostu) na /projekt001/index.php (neboť podobných projektů dělám hafo, i více najednou a ne každý může mít to privilegium být na kořeni). Třetí případ, který mě napadá, je shodou okolností na Jakubových stránkách - a sice možnost stažení webu jako archiv html stránek. Když si je někdo stáhne a rozbalí do nějakého adresáře, např. do /resources/jakub_vrana/*.* , tak by asi též nebyl potěšena, že styly nefungují, protože se tahají ze souboru /css/style.css, kterýžto neexistuje.
Jinými slovy, moc jste mě, pánové, nepřesvědčili ;-)

ikona Karel Dytrych:

A co vam brani provozovat u sebe na "localhostu" vice virtualnich serveru? http://projekt1/, http://projekt2/ apod.? Take ty soucasne stranky muzete hodit treba na subdomenu old... ne?

ikona david@grudl.com:

To se nestává :-)) Stará URL se přece zachovávají.

Ale dobře, zůstaňme u relativních adres. Jak vyřešíte, tento výpadek kaskádových stylů? http://hovnovbotach.wz.cz/index2.php/ahoj/

ikona Jakub Vrána OpenID:

To by v první řadě mělo skončit 404. V daném případě by stačilo vypnout AcceptPathInfo.

Ich:

No, páč u toho nepřemýšlíš...
1) proste v mod_rewrite nastavíš, že když je v ceste /old/, tak se css, img a další, dle potřeby, přepíše na /neco_kde_mam_old/img/ - a podobně. A máš po starostech...
2) stačí si na localhostu pořádně nainstalovat server, tedy i s virtuál-hostama, pak neřešíš problémy typu "nám to nejdede, protože jsme to tesovali na localhost a tam se to chovalo uplně jinak než na produkčním serveru"
3) když dám možnost stahovat na lokál (skoro)celý web, tak buď pro generování archivu vytvořím pravidlo, nebo napíšu návod, jak "nainstalovat" lokální kopii tak, aby fungovala... (tj. nakopírovat css adresář na root disku, odkud prohlížím archiv..

Prostě jen u toho trošičku přemýšlet a ono to už půjde samo.

ikona Jakub Vrána OpenID:

1. Když odkazy vedou na /css/, tak /old/ v cestě není.

3. Opravdu se nedá označit za unobtrusive řešení říkat někomu, ať si zasere root disku.

Než někomu začneš říkat, že nepřemýšlí, měl bys přemýšlet sám.

pojízdná kočka:

2. OK, uznávám (pro úplnost)

Franta:

Zdravim, s USER FRIENDLY URI se peru teprve par dni... pekny clanek... ale unika mi co s vysledkem, ktery FCE vyhodi? Kam s nim, aby to zmenilo URL? Diky L.

pojízdná kočka:

Zaprvé - toto řešení je pro dynamické weby, které mají předem neznámý počet (někdy stovky až tisíce) samostatných stránek (detailních stránek produktů u e-shopů, článků u zpravodajských serverů apod.).

Ta funkce představuje způsob, jak každé této stránce automaticky (strojově) přidělit část URL za doménou, kterou má být skript později schopen najít. Předpokládá se, že se název URL odvíjí od názvu dané stránky, který je někde uložen (typicky v databázi).

Při ukládání záznamu stránky se dá uložit i takto upravená URL; při (jak to říct?) "lokalizaci" stránky na serveru mod_rewrite přesměruje požadavek na defaultní skript (typicky index.php), který si stránku už umí najít (databázovým dotazem na stránku, jejíž pole určené pro uložení této části URL se shoduje s tím, co je v $_SERVER['REQUEST_URI']).

Franta:

děkuji za odpověď, hlavně bod ZAPRVÉ je skvělý ;-) ale jen jsem chtěl vědět, jak dál použít upravený řetězec (přívětivé URL) v praxi. Upravit string, je myslím na celé problematice to nejjednodušší... F.

blizz.boz:

http://ipremiere.eu/davov%C3%A1-psych%C3%…-adresy.html

pojízdná kočka:

Zajímalo by mě, jestli by se funkce jako make_url() dala udělat přímo v prostředí databáze jako databázová funkce..

ikona Jakub Vrána OpenID:

Na Daily WTF jsem kdysi viděl funkci, která funkci REPLACE() volala asi 15x zanořenou. Sloužila pro vyhledávání v dlouhých textech bez diakritiky, na což se opravdu moc nehodila, ale na krátký řetězec by to nijak zvlášť nevadilo (když pominu obludnost kódu).

pojízdná kočka:

Teprve teď jsem se k tomu dostal.
http://thedailywtf.com/gsearchresults.aspx?…=Search#1033
Ale odradil mě název rubriky - Stupid Coding Tricks ;-)

Václav Vaník:

A co třeba http://pecl.php.net/package/translit ?

ikona v6ak:

Nebo webalize v Nette.

cucací potřeby:

to by mělo být principiálně to samé jako tady

Alex:

Dekuji. Hledal jsem na podobnu funkce.
Diakritika porovano lehko dala se transliterovat.
Azbuka musi byt s strstr.

majo:

jj staci jedno pismenko azbuky a cely prevod zlyhava :(

pojízdná kočka:

Na Intervalu vyšlo takové kolokvium "předních expertů na SEO"

http://interval.cz/clanky/google-search-engine-…-url-stranky

a v jeho závěru se došlo k tomu, že "relevance na klíčová slova" představuje pro Google cca 9 % ze 100.
Z těchto 9 % "přátelské URL" podle mého skromného odhadu mohou zabírat takových 5 % (tedy 5 % z vnitřních faktorů).
Z výše uvedeného vyplývá, že čisté URL mají vliv 0,09 * 0,05 = 0,0045 - tedy 4,5 promile na optimalizaci pro vyhledávače.
Prvek z vnitřních faktorů, který má asi největší význam, je <titile>. Nezřídka je ale vidět weby s přátelským URL a titulky "NONAME001.HTM", "Untitled". To je čistá dmnc, ale toť už jiná kapitola...

Otto:

Funkce je fajn.

Jak ale řešit v .htaccess výstup ze search form (search engine) s get parametrem, když napíšu ŠKODA? Jak naladit, aby ve výstupu při přesměrování zůstala česká diakritika a nikoliv procenta a přehozený nesmysle místo českých znaků? Těžko vnutím nějakou funkci PHP při předávání get parametrem do URI :-P
Prolezl jsem za poslední dva tři dny mraky zdrojů a nikde nic.

Tady přikládám to vlastní přesměrování.

RewriteCond %{QUERY_STRING} ^string=(.*)
RewriteRule ^search\.php /hledani/%1.html? [R=301,L,E]

RewriteRule ^hledani/(.*)\.html$   search.php?adv_text=$1   [QSA]

ikona Jakub Vrána OpenID:

Přesměrování může provést přímo PHP skript, nemusí to dělat mod_rewrite.

Otto:

Jakube, děkuji za radu. Jakmile to vyřeším, pošlu to sem.

O.

Otto:

Přes Htaccess nebo v nastavení Apache.

Holmistr:

Jestli jsem pochopil problém správně, tak ti vadí to, že do adresy zadáš skript.php?promena=škoda a v proměnné (např.) $_SERVER['QUERY_STRING'] máš ahoj=%9Akoda.

Řešení bych měl jednoduché. Prohnat $_SERVER['QUERY_STRING'] funkci urldecode().

Opravte mne prosím, pokud se mýlím :-)

Pur:

Zdravím, potřeboval bych poradit.
Používám Mod_rewrite pro generování přátelských URL:

RewriteRule ^(.*)/$ index.php?rw=1&stranky=%{REQUEST_URI} [R=301,L]

Do proměnné "stranky" se mi načte vlastně cesta na webu s lomítky, v PHP si z ní udělám pole a čtu z něj. Bohužel si zatím moc nerozumím s regulárními výrazy a nedaří se mi provést následující: pokud bych měl adresu v prohlížeči
www.example.com/uroven1/uroven2/, vše je v pořádku a do proměnné "stranky" se mi načtou úrovně. Ale chtěl bych upravit pravidlo přesměrování, abych mohl použít například také url
www.example.com/uroven1/uroven2/?hledat=hledany_text

Nevím si s tím rady :-(

Pur:

mám to, stačí příznak QSA :)

Ján Žitniak:

Chcem sa opýtať - keď si vygenerujem pomocou Tvoje funkcie friendly_url() priateľskú adresu, napr. v tvare najlepsia-fotka-na-slovensku tak ako tom mám na strane kódu ošetriť, aby k URL bol priradený konkrétny obsah?

Jedná sa mi o to, že niekto zadá www.mojaadresa.sk/najlepsia-fotka-na-slovensku a teraz ku akému skriptu to bude priradené? Cez .htaccess by som to riešil cez RewriteRule v PHP si to viem predstaviť, že bude mať pole, kde sa budú priateľské url odkazovať na skutočné url, je to tak správne?

Tomáš Vojtášek:

V PHP 5.3.1 mi hlásí:
iconv(): Detected an illegal character in input string

Dano:

Zdravim, super vec...ale napr. ked to pouzijem na premenovanie suborov, aby neobsahovalidiakritiku a podobne znaky, odstrany to aj priponu, je to mozne nejako osetrit? aby nezmizla bodka pred priponou? Súbor.jpg zmeni na suborjpg :((

Morellato:

Řekl bych, že udělat hezké URL byl správný krok, je fajn, že už je to tak dlouho. A je zpětně zábavné pozorovat dřívější reakce některých odborníků:)

Šimon:

Jsem velký amatér, ale když prohlížím příklady stránek na netu,
a vidím http://example.com/silenynazev.php?jestesilenej…=123925876249 tak si řeknu že je pro mě příjemnější /skripty/pocitadlo/.
Ale mnozí si toho podle mě dnes už nevšimnou protože je zajímá jen obsah stránek né adresa, a že když se na ni chtějí vrátit mají Windowsowskou schránku nebo prohlížečové záložky,
a o víc se nestarají, pokud to tedy vysloveně nejsou odborníci na zapamatovatelnost URL... Mě je to při prohlížení upřímně jedno, hlavně když najdu co očekávám, nebo hledám.

Kuba:

Dobrý den, mám dotaz, co když při vytváření článku narazím na článek, který má úplně stejný název jako článek, který je již v DB, jakým způsobem byste toto ošetřil? Díky.

ikona Jakub Vrána OpenID:

Obvykle se to řeší přidání nějaké přípony – pořadového čísla nebo datumu.

VelbloudiNotace:

Dobrý den. Jsem úplný začátečník, a tak vůbec nevím jak to použít. Napadlo mě že bych ten kód vložil na začátek stránky, ale nejsem si tím jist. Jestli to chápu špatně, tak prosím o nějaký příklad.

J.:

Když obchodnímu partnerovi pošlu odkaz na www.neco.cz/cenik, tak to má rozhodně větší úspěsnost než www.neco.cz/?page=5

Rozdíl asi jako mezi profi vytištěnou vizitkou a vizitkou vytištěnou na ušmudlaný kancelářský papír?

M:

Tak "á" se mi určitě nepřevádí na "a", vynechá to. Zkusím něco jiného. :)

v6ak:

Já bych řekl, že to funguje:

[6] boris> friendly_url(file_get_contents("php://stdin"));
řčžčřžščžčřžýéíáýžřčšě+áx
→ string(25) "rczcrzsczcrzyeiayzrcse-ax"

Používáš tu funkci přesně tak, jak je zde uvedena?

Vložit příspěvek

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2014 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.