Archive for the ‘Návody’ Category

Když pracujete s databází, do které ukládáte hodně dat, pak se dřív nebo později dostanete do situace, kdy se v ní nachází nějaké duplicity. Otázka je jak je najít a následně pak smazat. Já na to používám velice jednoduchý SQL dotaz, který ale skvěle funguje.

Všechny duplicity v databázi najdete tímto SQL příkazem:
SELECT * FROM `vase_tabulka` as tab where (select count(id) from ` vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1

Aby vše fungovalo i u vás, musíte změnit 2 věci:

  1. vase_tabulka změňte na název tabulky, kde chcete hledat duplicity.
  2. duplicitni_sloupec změnte na název sloupce, kde chcete najít duplicity.

Pokud máte v databázi hodně dat, tak to může chvíli trvat. Je velice vhodné, aby na sloupci, kde hledáte duplicity, byl index. Dotaz následně vrátí všechny duplicitní řádky tak, že budou vypsané oba dva. Pokud chcete vidět oba dotazy pod sebou, pak použijte toto:

SELECT * FROM `vase_tabulka` as tab where (select count(id) from ` vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1 order by duplicitni_sloupec;

Pokud chcete vypsat vždy jen jeden záznam, použijte klauzuli group by na konci dotazu takto:

SELECT * FROM `vase_tabulka` as tab where (select count(id) from `vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1 group by duplicitni_sloupec;

Bohužel tento dotaz by měl teoreticky fungovat, avšak prakticky někdy nefunguje. Proto je nutné udělat ještě jednu kličku a použít celý dotaz jako vnořený do vnějšího, kde se teprve vytvoří skupinky.

SELECT * FROM (SELECT * FROM `vase_tabulka` as tab where (select count(id) from `vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1) as tab2 group by duplicitni_sloupec;

Odstranění duplicit

Při odstranění budeme postupovat tak, že chceme smazat všechny řádky, které odpovídají prvnímu dotazu, kromě těch, které odpovídají druhému dotazu. Bohužel většině databází není možné mazat ze stejné tabulky, ze které aktuálně čtete, proto není možné použít tyto dotazy jako podmína při mazání:

Musíme to tedy obejít. K tomu abychom mohli duplicity smazat, využijeme dočasné tabulky, do kterých všechna data uložíme a následně přečteme z nich. Celý dotaz pro odstranění duplicit bude vypadat následovně:

1) vytvoříme dočasnou tabulku, do které uložíme id řádků pro smazání.

CREATE TEMPORARY TABLE `smazat_temp` (
`id` INT(255) NOT NULL,
);

2) Do tabulky vložíme data

Insert into `smazat_temp` (id) values (SELECT id FROM `vase_tabulka` as tab where (select count(id) from `vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1);

3) Momentálně jsou uložena v tabulce veškeré duplicitní id, my ale chceme vždy jednu verzi z nich zachovat. Řádky, které chceme ponechat, proto z této tabulky vyjmeme dotazem:

Delete from `smazat_temp` where id in (SELECT * FROM (SELECT * FROM `vase_tabulka` as tab where (select count(id) from `vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1) as tab2 group by duplicitni_sloupec);

4) Na závěr odstraníme data z hlavní tabulky a dočasnou odstraníme.

Delete from `vase_tabulka` where id in (select id from `smazat_temp`);
Drop table `smazat_temp`;

Celý dotaz je nutné spustit během jednoho sezení. Pokud, tedy používáte phpMyAdmin, tak do pole s SQL příkazem musíte napsat vše najednou:

CREATE TEMPORARY TABLE `smazat_temp` (
`id` INT(255) NOT NULL,
);

Insert into `smazat_temp` (id)  (SELECT id FROM `vase_tabulka` as tab where (select count(id) from `vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1);

Delete from `smazat_temp` where id in (SELECT id FROM (SELECT * FROM `vase_tabulka` as tab where (select count(id) from `vase_tabulka` where duplicitni_sloupec = tab.duplicitni_sloupec) > 1) as tab2 group by duplicitni_sloupec);

Delete from `vase_tabulka` where id in (select id from `smazat_temp`);
Drop table `smazat_temp`;

Teď nechte databázi chvíli šrotit a duplicity budou pryč.

Už bylo napsáno mnoho článků o tom, že PR články jsou jen nafouknutá bublina nebo že jde v principu jen o katalogový zápis s větším množstvím textu. A bublina PR článků pomalu splaskává stejně jako kdysi bublina katalogových zápisů. Jak už to tak bývá tak pravda je vždy někde uprostřed. Stejně jako vkládání odkazů do katalogů má význam jen v rozumné míře, tak i psaní PR článků má svá pravidla, kdy mají smysl.

1) Cílení na long tail

Aby byl Váš článek navštěvovaný, tak je třeba spolehnout se na vyhledávače. Na internetu dnes bohužel neexistuje žádný PR web, který by měl takovou přirozenou návštěvnost, aby Váš článek četli lidé, kteří PR web běžně navštěvují. PR weby navštěvují převážně jen lidé, co píší pr články. A za předpokladu, že určitě nechcete věnovat příliš úsilí, abyste Váš PR článek na cizím webu nějak optimalizovali na nějaké hlavní klíčové slovo je jedinou cestou pro úspěch u vyhledávačů cílit na long tail. Lidí, kteří takové dotazy píší do vyhledávacího políčka je podstatně méně než v případě hlavních frází ale jen u nich máte šanci dostat se na první příčky ve vyhledávání.

2) Vkládejte články do tematických webů

Tento bod souvisí částečně s bodem prvním a se SEO optimalizací. Dnes již každý webový vyhledávač pozná, do jakého tématu spadá napsaný článek. Pokud je článek o tabletkách na hubnutí napsán na webu o automobilismu, pak pozná, že zde něco nesedí. Dobře jsou ohodnocené stránky s určitým tématem, které se nachází na tematických webech se stejným zaměřením. Stránky, které svým tématem vybočují z tématu webu, nemají pro vyhledávače takový význam. Navíc na netematických PR webech je taková změť různých článků, že vyhledávač si nebude jistý, k jakému tématu Váš článek patří a ztratíte tak důležité body.

3) Dbejte na originalitu

Články propagující Váš web by měly být na různých PR webech různé. Když webový vyhledávač najde duplicitu, pak si stejně vybere jen jeden článek a ostatní zahodí. Vaše práce s přidáváním do mnoha PR webů přijde v niveč. pr článek nemusí být kdoví jaký copywriterský skvost. Dokonce nemusí ani obsahovat příliš klíčových slov a nemusí být ani gramaticky správně. Stejně cílíte na long tail a i lidé co píší dotazy do vyhledávačů, dělají i gramatické chyby. Váš článek by měl být hlavně na každém webu originální, jedině tak jej budou brát vyhledávače v úvahu.

Já nejčastěji píšu na každý PR web z patra, co mě napadne, a neřeším, co si o tom kdo pomyslí. Svůj účel ten článek splní.

4) Nepřistupujte k pr článkům jen jako k potravě pro vyhledávače

… ale jako k místu odkud k Vám mohou přijít potencionální návštěvníci, kteří Vám přinesou zisk.

Tento bod je v podstatě zobecněním všech předchozích. Obsahuje základní myšlenku, kterou jsem popsal ve článku Optimalizace pro vyhledávače = optimalizace pro lidi. Jde o to, že pokud Váš článek bude přínosný pro lidi, pak jej budou vyhledávače dobře umisťovat, protože je to přínosné i pro vyhledávače.

 

Nedávno jsem řešil přechod z jednoho hostingu na druhý pro můj projekt kečtení.cz, tak aby nevznikla žádná prodleva v dostupnosti. Během toho jsem si vytvořil zálohu databáze, která měla přes 500Mb a setkal jsem se s problémem jak tuto zálohu obnovit. PHPmyAdmin ani Adminer s takovými zálohami pracovat neumí a vlastní parser jsem si psát nechtěl. Naštěstí jej už někdo udělal za mě.

Našel jsem si php skript, který slouží přímo pro import velkých záloh, který naleznete na adrese http://www.ozerov.de/bigdump/. Ten stačilo stáhnout, rozbalit a už byl funkční. Jak vše nastavit si můžete přečíst zde. Skript bigdump je napsán tak, že nepřekročí ani memory limit ani time limit na běh jednoho skriptu. Je totiž na pozadí spouštěn vícekrát za sebou, i když to není na první pohled vidět. Na konci obnovy se pak můžete podívat, kolik sezení zabrala celá obnova.

Dalším problémem, se kterým jsem se setkal, bylo, že při nahrávání 500 megového souboru mi spadl internet a bylo nahráno zhruba 80% souboru. Při mém pomalém připojení se mi nechtělo nahrávat celý soubor znova. Zjistil jsem si kolik bytů souboru je nahráno na serveru a pak jsem si napsal jednoduchý skriptík, který mi vytvořil zbytek souboru a ten jsem nahrál na server.

$adresa_souboru = '../../2011-10-10-09-49-kecteni_857.sql';
$pocet_preskocenych_bytu = 328787456;
// velikost souboru, která se povedla nahrát
$f0 = fopen($adresa_souboru, 'r');
$f = fopen('cast2.sql', 'w');
fseek($f0, $pocet_preskocenych_bytu);
while (!feof($f0)) {
$text = fread($f0, 8192);
fwrite($f, $text, 8192);
}
fclose($f0);
fclose($f);

Po té jsem si napsal další jednoduchý skriptík, který mi soubory opět spojil.

$f0 = fopen('cast1.sql', 'r');
$f1 = fopen('cast2.sql', 'r');
$f = fopen('zaloha.sql', 'w');
while (!feof($f0)) {
$text = fread($f0, 8192);
fwrite($f, $text, 8192);
}
fclose($f0);
while (!feof($f1)) {
$text = fread($f1, 8192);
fwrite($f, $text, 8192);
}
fclose($f1);
fclose($f);

Nemusel jsem tak nahrávat celý soubor znovu ale pouze zbývající část. Před spuštěním jsem si ještě první část přejmenoval na cast1.sql aby vše fungovalo. Výsledný celý soboubor byl vytvořen jako zaloha.sql.

Po té už jen stačilo spustit skript bigdump.php a začala obnova databáze. To nějakou dobu trvalo, ale vše proběhlo úspěšně. Co se ale nezálohovalo, byly uložené procedury v databázi. Ty jsem si musel dodatečně přepsat ale hlavní práce týkající se zálohy struktury databáze a dat byla hotova.

 

Na hostingu Wedos je možné používat více domén v jednom hotingovém programu a je také možné vytvářet libovolné množství subdomén jen vytvořením dalšího adresáře ve výchozí struktuře kořene webu. Směrování do jednotlivých adresářů je zde řešeno pomocí .htaccess, který po vytvoření hostingu obsahuje toto:

RewriteEngine On

# cele domeny (aliasy)
RewriteCond %{REQUEST_URI} !^domains/
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%2 -d
RewriteRule (.*) domains/%2/$1 [DPI]

# subdomeny (s nebo bez www na zacatku)
RewriteCond %{REQUEST_URI} !^subdom/
RewriteCond %{REQUEST_URI} !^/subdom/
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)\.([^\.]*)\.([^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/subdom/%2 -d
RewriteRule (.*) subdom/%2/$1 [DPI]

# aliasy - spravne presmerovani pri chybejicim /
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^domains/[^/]+/(.+[^/])$ /$1/ [R]

# subdomeny - spravne presmerovani pri chybejicim /
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^subdom/[^/]+/(.+[^/])$ /$1/ [R]

Adresářová struktura na hostingu, pak může vypadat třeba takto:

domains -> web1.cz
        -> web2.cz
        -> web3.cz
subdom -> subdomena1
subdom -> subdomena2

Vytvoření nového adresáře ve složce domains vytvoří prostor pro doménu, která bude do tohoto adresáře směrována. Vytvoření nového adresáře v subdom vytvoří nový prostor pro subdoménu.

Veškeré subdomény ze všech domén jsou směrovány do adresáře subdom. Problém nastává, pokud chci mít na adrese subdomena1.web1.cz jeden web a na doméně subdomena1.web2.cz druhý, pak nelze toto nastavení použít, protože obojí si šáhne do adresáře subdom/subdomena1, kde najde jeden a ten samý obsah.

Proto je vhodné použít tuto strukturu, která mi také mnohem víc vyhovuje:

domains -> web1.cz -> www
                   -> subdomena1
        -> web2.cz -> www
                   -> subdomena1
                   -> subdomena2
        -> web3.cz -> www

Pro tuto strukturu používám tento soubor .htaccess:

RewriteEngine On
RewriteBase /

# presmerovani na variantu s www
RewriteCond %{HTTP_HOST} ^([^\.]*)\.([^\.]*)$
RewriteRule (.*) http://www.%1.%2 [L,R=301]

# cele domeny (aliasy)
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^([^\.]*)\.([^\.]*\.[^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%2 -d
RewriteCond %{DOCUMENT_ROOT}/domains/%2/%1 -d
RewriteRule (.*) /domains/%2/%1/$1 [L]

# neexistuje subdomena, pak jdi na www
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^([^\.]*)\.([^\.]*\.[^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%2 -d
RewriteRule (.*) /domains/%2/www/$1 [L]

V první části je vyřešena situace kdy někdo zadá adresu jako http://domena1.cz, pak bude přesměrován na http://www.domena1.cz.

V druhé části je pak řešeno směrování na jednotlivé adresáře. Adresa http://subdomena1.domena1.cz bude směrováno do /domains/domena1.cz/subdomena1/. Z tohoto chování je zřejmé, že adresa http://www.domena1.cz bude nasměrována na /domains/domena1.cz/www/. Adresář www tedy musí vždy existovat.

Ve třetí části je řešen případ, kdy je zadaná adresa http://subdomena1.domena1.cz a adresář /domains/domena1.cz/subdomena1/ neexistuje. V tom případě je vše směrováno do adresáře /domains/domena1.cz/www/, což je taky další důvod proč musí vždy existovat jinak dojde k chybě.

Toto chování také využívám například na webu aclanky.cz, kdy je vše směrováno do /domains/aclanky.cz/www/ a když chci vytvořit nový web na subdoméně, tak aby jej nezachtával hlavní web, pak stačí jen vytvořit patřičný adresář a vše bude směrováno do něj.

 

Poslední dobou vídám na různých fórech na internetu často otázky na mod_rewrite, kdy se tazatel ptá na to jak podstrčit jinou adresu a vytváří kolikrát šílené konstrukty v .htaccess. V tomto článku se nebudu snažit popsat mod_rewrite ani jak fungují regulární výrazy ani nic podobného, to se můžete dočíst zde případně i zde, ale ukážu zde jednoduché a efektivní řešení jak pracovat s adresami aby vypadaly hezky a aby se s nimi krásně pracovalo.

Jak na mod_rewrite?

Pravidla pro mod_rewrite se zapisují do souboru .htaccess a musí být na serveru povoleny. Není potřeba vymýšlet žádné složité konstrukty, pouze stačí vše přesměrovat na index webu zhruba takto:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php [L,QSA]

Tento zápis zajistí, že všechny adresy, které reálně neexistují, budou přesměrovány na index.php. Úvodní podmínky jsou nezbytně nutné, protože pokud by zde nebyly, pak by i požadavky na obrázky nebo css soubory skončily také na index.php a to nechceme.

Momentálně máme zajištěné přesměrování, ale jednotlivé adresy mohou být jak s lomítkem na konci tak bez lomítka na konci, což není příliš dobře. Dále tedy provedeme sjednocení. Následující kód zajistí, že všechny adresy budou přesměrovány na index.php a pokud budou končit lomítkem, pak budou přesměrovány na variantu bez lomítka.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php [L,QSA]

Tím veškerá práce na souboru .htaccess končí. Dále se podíváme na zpracování adres v PHP.

Zpracování v PHP

Stejně jak jednoduché to je se souborem .htaccess, tak jednoduché je to i na straně php. Využijeme serverové proměnné $_SERVER['REQUEST_URI'] pro získání aktuální adresy, ze které separujeme jednotlivé části.

$p = strpos($_SERVER['REQUEST_URI'], '?');
if($p === false){
$patch = explode('/', $_SERVER['REQUEST_URI']);
}else{
$patch = explode('/', substr($_SERVER['REQUEST_URI'], 0, $p));
}
array_shift($patch);

Na začátku zjistíme, jestli adresa obsahuje otazník. Pokud ano, pak jej musíme oříznout, protože požadavky za otazníkem nás v adrese nezajímají. Ty jsou předány klasicky v poli $_GET. Po té adresu rozbijeme podle znaku ‚/‘ do pole $patch, a protože požadavek vždy začíná lomítkem, pak nakonec první položku pole odstraníme.

Nyní již máme v poli $patch jednotlivé části adresy, se kterými můžeme pracovat jednoduše pomocí podmínek nebo příkazů isset apod.

Příklad

Dejme tomu že na web www.examples.tld přijde následující požadavek:
www.examples.tld/dir1/dir2/dir3/
Nejprve dojde k přesměrování na variantu bez lomítka:
www.examples.tld/dir1/dir2/dir3
a v PHP kódu pak získáme v proměnné patch následující části:

$patch[0] == "dir1";
$patch[1] == "dir2";
$patch[2] == "dir3";

S těmi pak je možné snadno pracovat pomocí podmínek a větvit kód dle potřeby. Pokud bychom si chtěli ověřit, jaká část adresy existuje, uděláme to jednoduše takto:

if(isset($patch[2])){
// část adresy existuje
}else{
// část neexituje
}

Závěrem

Vytváření COOL url není žádná věda a není to ani nijak složité. Stačí se zamyslet nad problémem a vyřešit jej tou nejjednodušší a nejefektivnější cestou. Doufám, že tento návod Vám pomůže ve Vašem projektu.