phpMinAdmin 1.10.0

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

phpMinAdmin 1.10 je možná poslední verze jedničkové řady nástroje pro správu MySQL databáze. Doplňuje některé nedodělané věci a opravuje drobnější věci.

Po podpoře událostí z verze 1.8.0 jsem doplnil také podporu rozdělování tabulek, což je druhá syntaktická novinka MySQL 5.1 (jsem zvědav, kdy se na pořádnou podporu těchto novinek zmůže phpMyAdmin).

Vedle dlouho podporovaného CSV exportu jsem doplnil také CSV import. Ten je k dispozici pod každou tabulkou a očekává soubor v kódování UTF-8 s volitelným BOM (ten se doplňuje při exportu proto, aby s exportem dokázal pracovat např. Excel). Na prvním řádku souboru může být uveden seznam sloupců (v libovolném pořadí), jejichž data obsahují další řádky. Když se obsah prvního řádku neshoduje s názvy existujících sloupců, tak se použije také jako datový.

Při editaci čísel lze používat operátory + a -, což se hodí hlavně u hromadné editace záznamů.

Při zpracování SQL příkazů lze vykonávání volitelně zastavit po první chybě (děkuji Václavu Maříkovi).

U struktury tabulky se zobrazuje odkaz na výpis tabulky a vytvoření nového záznamu, u výpisu tabulky zase odkaz na strukturu. Užitečné jsou hlavně proto, aby nebylo nutné v levém sloupci hledat právě zobrazenou tabulku.

Spolu s Klemensem Häckelem jsme dlouho pátrali po tom, proč na některých serverech nelze editovat strukturu velkých tabulek. Na vině je Suhosin a jeho konfigurační volba suhosin.post.max_vars. phpMinAdmin ji nemůže přepsat, ale může alespoň upozornit na nutnost jejího zvýšení.

Z exportu jsem odstranil nastavování proměnné max_allowed_packet, jejíž nastavení v SQL stejně nefunguje.

Díky Tomáši Jukinovi a jeho alternativnímu stylu jsem přidal detekci existence souboru phpMinAdmin.css. Pokud vedle phpMinAdmin.php tedy nahrajete tento soubor, tak se automaticky použije styl v něm uvedený, hlavní skript není potřeba nijak hackovat.

Juraji Hajdúchovi děkuji za ruský překlad.

Minimalizace kódu

Největší změnou, která ale navenek není vidět nijak jinak než zmenšením velikosti souboru, je minimalizace kódu. Asi to znáte z různých JavaScriptových knihoven – kromě odstranění nepotřebných komentářů a bílých znaků se nově také zaměňují dlouhé názvy proměnných a funkcí za krátké. phpMinAdmin má tu výhodu, že navenek neexportuje žádné API, takže může změnit všechny proměnné a funkce. U knihoven by to bylo o něco složitější, protože veřejné API musí zachovat, takže toto API zkracovače buď vůbec nepřekládají nebo ho přeloží na krátké a pak zase zpátky na dlouhé.

Zkrácení proměnných je jednodušší – pokud kód nepoužívá proměnné proměnné a pole $GLOBALS, tak stačí dát pozor na vlastnosti objektů:

<?php
/** Zkrácení názvů proměnných
* @param array výsledek funkce token_get_all()
* @return null modifikace pole $tokens
* @copyright Jakub Vrána, http://php.vrana.cz/
*/
function shorten_variables(&$tokens) {
    $special_variables = array_flip(array('$this', '$GLOBALS', '$_GET', '$_POST', '$_COOKIE', '$_REQUEST', '$_FILES', '$_SESSION', '$_SERVER', '$_ENV', '$php_errormsg'));
    $short_variables = array();
    
    // frekvenční analýza
    foreach ($tokens as $i => $token) {
        if ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
            $short_variables[$token[1]]++;
        }
    }
    arsort($short_variables);
    foreach (array_keys($short_variables) as $number => $key) {
        $short_variables[$key] = short_identifier($number, implode("", range('a', 'z')) . '_' . implode("", range('A', 'Z')));
    }
    
    $shortening = true;
    foreach ($tokens as $i => $token) {
        if (in_array($token[0], array(T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE), true)) {
            $shortening = false;
        } elseif (!$shortening) {
            if ($token === ';') {
                $shortening = true;
            }
        } elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
            $tokens[$i][1] = '$' . $short_variables[$token[1]];
        }
    }
}
?>

Zkrácením názvů proměnných se ušetřilo 12 kB, tedy asi 10 % velikosti anglické verze. Frekvenční analýza (to znamená největší zkrácení nejčastěji používaných proměnných) ušetřila 1 KB. Dalo by se využít ještě toho, že uvnitř funkcí nejsou vidět globální proměnné, takže parametry funkcí a lokální proměnné by mohly mít vlastní jmenný prostor, pracnost by ale řádově vzrostla a úspora by nebyla tak výrazná.

Zkrácené identifikátory jsou z rozsahu a-z_A-Z, využít by se daly ještě znaky z horní poloviny ASCII tabulky (to by ale soubor nebyl čitelný v UTF-8) a číslice (ty ale nelze použít na první pozici identifikátoru a proměnných je méně než 53^2 a vejdou se tedy do dvou znaků, takže použití číslic by nepřineslo žádnou úsporu). Pro zkrácení se používá jednoduchá funkce, která pro nižší číslo vrátí kratší identifikátor.

<?php
function short_identifier($number, $chars) {
    $return = '';
    while ($number >= 0) {
        $return .= $chars[$number % strlen($chars)];
        $number = floor($number / strlen($chars)) - 1;
    }
    return $return;
}
?>

Zkrácení funkcí je trošku složitější. Je nutné rozlišovat vestavěné funkce od vlastních a také funkce od metod. Je potřeba také nepřepisovat krátké názvy vestavěných funkcí. U funkcí se nerozlišuje velikost písmen, takže identifikátory se vytváří z menšího rozsahu. Zkrácení funkcí ušetřilo 6 kB, dalších asi 6 kB by mohlo ušetřit zkrácení vestavěných PHP funkcí. Při tom by ale došlo ke snížení rychlosti skriptu, protože by se musela volat jedna obálková funkce navíc.

Zvýraznění řádků tabulky

Verze 1.10.1 zvýrazňuje sudé a liché řádky tabulky. Využívá se k tomu jednoduchá funkce:

<?php
function odd($s = ' class="odd"') {
    static $i = 0;
    if (!$s) {
        $i = -1;
    }
    return ($i++ % 2 ? $s : '');
}
?>

Její postupné volání vrací střídavě předaný parametr a prázdný řetězec. Pro případ více tabulek za sebou je možné ji předáním prázdného parametru vynulovat.

Jakub Vrána, Adminer, 29.4.2009, diskuse: 45 (nové: 0)

Diskuse

Juraj Hajdúch:

Nuž, ak to pôjde takto ďalej s tým pridávaním funkcionalít, tak phpMinAdmin už Min asi nebude :-D, ale ja som za! Pre mňa je dôležitá jednoduchosť a rýchlosť a to tento produkt splňuje. Btw milujem jednosúborovky, ale to css ma potešilo, idem to hneď skúšať aj tak v telke nič nedávajú.

Na čo sa máme tešiť vo verzii 2.x?

ikona Jakub Vrána OpenID:

Nechci to ještě veřejně slibovat, tak řeknu snad jen tolik, že jsem rád, že v názvu není "My".

Makeš:

Jestli tím chceš naznnačit to co myslím tak super. Líbilo se mi mít jedno prostředí... :)

Jan Garaj:

Stiahol som, pustil a fatal error pri vytváraní tabuľky. Fatal error: Call to a member function f() on a non-object in W:\phpminadmin\index.php on line 665
A kedže je súbor "kompresovaný" je ťažké nájsť chybu. Odporučil by som vydať aj debug verziu, aby mohli PHP individuá prípadne aj reportovať presnejšie problémy.

A ďakujem za ďalšie vydanie :-)

Juraj Hajdúch:

Mňa nič také v 1.10 nestretlo :-o Všetko mi zatiaľ funguje ako má.
na stroji mám:
# Apache 2.0.63
# PHP 5.2.6
# MySQL 5.0.51b

ikona Jakub Vrána OpenID:

Děkuji za report chyby. Uveď prosím, jakou verzi MySQL používáš a přes jakou extenzi jsi připojen (oboje je uvedeno na stránce po přihlášení). Na daném řádku jsou dva dotazy, které by mohly způsobovat chybu: SHOW ENGINES a SELECT ... FROM information_schema.PARTITIONS (ten se volá jen pro MySQL >= 5.1).

Zdrojové kódy jsou kromě SVN k dispozici i přímo na stránce stažení https://sourceforge.net/project/platformdo…?group_id=199217. Stáhni si prosím tuto variantu, ať můžeš lépe lokalizovat chybu. Pokud si po identifikaci vadného dotazu necháš vypsat $mysql->error, bude to ideální.

Jan Garaj:

Už vidím v čom je problém "MySQL version: 4.0.26-nt through PHP extension MySQLi". V requirements je požadovaná 4.1++.  5.1.30-community na tom istom stroji je v poriadku. Takže nie je to bug, ale planý poplach - ospravedlňujem sa. CREATE a ALTER tabuliek bezproblémov oželiem na tom archaickom mysql ;-)

Martin:

Nová verze mě po nějaké době neaktivity odhlašuje. To je záměr nebo bug? Už jsem kvůli tomu nasadil starší verzi, kter mě nechala přihlášeného i několik dní (do uzavření prohlížeče), což bylo velmi pohodlné. Teď se vrátím za hodinu a musím se znovu přihlašovat. Hrozná otrava :-(

ikona Jakub Vrána OpenID:

Zjisti prosím, jak máš nastavenou konfigurační direktivu session.cookie_lifetime. Ve starší verzi se respektovala tato hodnota, v nové verzi jsem nastavil čas vypršení na 0, což by právě mělo znamenat "do zavření prohlížeče". Takže opačnou změnu chování bych pochopil, tato je podivná. Zjisti také prosím pro jistotu nastavení session.gc_maxlifetime.

Martin:

session.cookie_lifetime: 0
session.gc_maxlifetime: 1440

Hostováno u Český hosting

ikona Jakub Vrána OpenID:

To je tedy zvláštní. Nemůže to být jen náhoda? session.gc_maxlifetime 1440 znamená, že se nepoužívané session soubory můžou každých 24 minut smazat.

Martin:

Schválně jsem poslední phpminadmin nasadil na dva další weby (vše s totožným nastavením serveru jako u prvního) a u všech se problém vyskytuje. Občas to odhlásí (stará verze odhlašovala spolehlivě až po uzavření prohlížeče). Přitom je ale zvláštní, že odhlášení neproběhne vždy po stejné době. Někdy po hodině, někdy po dvou... nemůže se to nějak "hádat" s cookies z původní verze?

Jinak je divné, že by se session soubory měly dle nastavení mazat po 24 minutách, na serveru používám session u jedné aplikace pro přihlášení a vydrží platné určitě přes 10 hodin (večer se přihlásím a ráno jsem ještě přihlášen).

ikona Jakub Vrána OpenID:

S původními session cookies by se to hádat nemělo, obzvlášť když by se ve staré i nové verzi v tvém případě měly nastavovat stejně.

K automatickému mazání nedochází v případě, že session.save_path definuje hloubku zanoření do adresářů.

ikona Jakub Vrána OpenID:

Jen se pro jistotu ještě zeptám, zda "starší verze" je 1.9.1?

Martin:

Ano, starší verze je 1.9.1 nasazená na 10+ webech. Nevím, proč se to takhle chová, jen reportuji chybu, neumím najít příčinu. Zkrátka starší verze neodhlašovala a nová odhlašuje.

Martin:

Jinak možná to něčemu pomůže, ale teď jsem načetl novou verzi na jednom z webů, kde zůstala "otevřená" od včerejška a nové přihlášení nebylo vyžadováno. Chová se to podivně :-)

Jirka:

Dobrý den v nové verzi 10 mi nejde vytvořit ani upravit uživatel v sekci oprávnění.

Cannot redeclare _() on line 985

PS: Jinak díky za takového malého, ale silného pomocníka.

ikona Jakub Vrána OpenID:

Jedná se o kolizi s extenzí Gettext, v SVN jsem to už opravil a vyjde to v nejbližší verzi tento týden.

Hever:

Chtěl bych se přimluvit za to, aby úprava tabulky a výchozích hodnot byla na jednom místě.

pojízdná kočka:

Díky za novou verzi. V té minulé jsem se ptala, jestli jde nad sloupcem tabulky udělat SET DEFAULT "" a odlišit to tak od DROP DEFAULT.
Všimla jsem si, že jsi to udělal, ale zmátlo mě nejdřív, že jsem to neviděla v changelogu. ;-)

ikona Jakub Vrána OpenID:

Drobnější změny jsou jen v SVN logu: http://phpminadmin.svn.sourceforge.net/viewvc/phpminadmin/?view=log.

sirius:

Smažím se vyzkoušet phpMinAdmin 1.10 a mám problém:
pokud si otevřu OPRÁVNĚNÍ a chci vytvořit nového uživatele, nebo editovat stávajícího uživatele, vždy se mi otevře čistá stránka. Na testovací SourceForge to funguje.
(Verze MySQL: 5.0.67 přes PHP extenzi MySQLi, PHP5).
Kde dělám chybu?
Děkuji.

ikona Jakub Vrána OpenID:

Bude to nejspíš stejná chyba jako http://php.vrana.cz/phpminadmin-1-10-0.php#d-8192. V SVN už je opravena, tento týden vydám i novou verzi.

ikona Jakub Vrána OpenID:

Vyšel phpMinAdmin 1.10.1, který mimo jiné opravuje chyby zmíněné v této diskusi.

LuKo:

Nová verze i s novým skinem vypadá výborně! Díky za tento parádní nástroj. PhpMyAdmin přesto ještě využívám, definitivní vale bych mu dal, kdyby PhpMinAdmin zobrazoval i čas zabraný sql dotazem. Kdyby měl pma i jednoduchý formulářík pro testování (viz http://php.vrana.cz/ukazka-pouziti-indexu.php), byl by úplně dokonalý ;-)

ikona Jakub Vrána OpenID:

Přidání času zabraného dotazem zvážím. Nevím přesně, co máš na mysli "jednoduchým formuláříkem pro testování", ale EXPLAIN můžeš spustit v SQL příkazu.

LuKo:

Políčko "počet iterací" a textarea pro testovaný dotaz. Stejně tak Tebou zmíněné tlačítko pro explain. Toto je třeba na phpmyadminu to dobré - nemusím psát explain, jen kliknu a hned mám výsledek. Není to životně důležitá funkčnost, jen je to o lepším komfortu. Za málo peněz (snadno implementovatelné) hodně muziky (vděku minimálně ode mě) ;-)

ikona Jakub Vrána OpenID:

Počet iterací mi nedává smysl. Pro syntetické testy je lepší samotný čas, pro reálné testy zase simulace reálnějšího provozu.

Pro EXPLAIN by se samozřejmě tlačítko udělat dalo (stejně třeba jako pro vytvoření pohledu), ale pro dotazy u výpisu tabulek to málokdy potřebuji (ty jsou většinou jednoduché) a pro složitější dotazy, které se píšou ručně v SQL příkazu, je zase jednoduché to tam dopsat ručně. Smysl by mi to dávalo, pokud by měl phpMinAdmin nějaký sofistikovaný nástroj pro sestavení dotazu nad více tabulkami.

Ještě co se toho času dotazu týče - navrhni prosím uživatelské rozhraní. Teď se zobrazuje dotaz, pod ním buď informace o počtu změněných řádek nebo tabulka s výsledkem. Vymysli, kam informaci o času vypsat, aby pokud možno co nejmíň překážela, a navrhni formátování.

LuKo:

Předně mé návrhy ber jako třešínku na jinak výborném dortu ;-)

Tlačítko EXPLAIN: Typicky ladím dotazy ze slow-logu, takže copy-paste a zde by se hodil klik na explain a zpět. Dopsat explain ručně není takový takový problém, ale tlačítko je lepší 0:-)

Nejsem grafik, takže s návrhem rozhraní to bude horší :-/ Ale myslím, že přidat řádek pod sql dotaz ve tvaru podobném, jako je v konzoli, např. Query OK, 5 rows affected (0.19 sec) nebo 100 rows in set (4.74 sec)

Ad BENCHMARK: Měl jsem na mysli formulářík:
count(textbox): 100000
query(textarea): SELECT MAX(publikovano) FROM clanky WHERE skupina = RAND()
a ten by vytvořil a provedl: DO BENCHMARK(10000, (SELECT MAX(publikovano) FROM clanky WHERE skupina = RAND()))

ikona Jakub Vrána OpenID:

Čas jsem v SVN verzi nechal zobrazovat vpravo za SQL příkazem menším šedým písmem.

Brano:

Dobry den,
mam taky mensi problemik. Na pripojenie k mysql musim pouzit ako server: localhost:/tmp/mysql50.sock

Cez phpminadmin to ale nedokaze prihlasit.. Stale pise, ze Neplatne prihlasovacie udaje, ale pritom su spravne.. Ked ich zadan do mysql_connect(), tak idu v pohode..

Dakujem

Brano:

No, takze som skusil poslednu moznost, a to, ze som spustil phpminadmin pod PHP4 a nie PHP5..
Zaujimave, takto to ide...

ikona Jakub Vrána OpenID:

phpMinAdmin připojení přes nevýchozí socket nepodporuje. Technicky to možné je, protože to podporují všechny tři extenze, takže podporu doplním.

ikona Jakub Vrána OpenID:

Podporu připojení přes socket jsem přidal do SVN verze.

Martin:

To neustálé odhlašování je fakt běs. Nedá se s tím něco udělat? Opakované přihlašování je o nervy. Neověřuje nová verze třeba IP adresu (doma mám jinou než v práci)? Projevuje se to hlavně na firmě, kde je více počítačů. Starší verze to fakt nedělá.

ikona Jakub Vrána OpenID:

IP adresa se neověřuje. Nová verze pouze místo session_set_cookie_params(ini_get("session.cookie_lifetime")) nastavuje session_set_cookie_params(0), což by mělo být s defaultním nastavením totéž, každopádně by cookie měla vydržet až do zavření prohlížeče.

Ověř prosím, zda k odhlášení dojde kvůli zmizení cookie nebo kvůli expiraci session souboru na serveru. Mělo by to jít poznat z HTTP požadavku – pokud se pošle cookie phpMinAdmin_SID, je na vině server.

Martin:

Toto bohužel neumím zjistit. Server však na vině není, protože starší verze phpmin admina na *stejném serveru* neodhlašují. Odhlašování začne až po nahrazení původní verze tou novější.

ikona Jakub Vrána OpenID:

Až dojde k odhlášení, tak do adresního řádku prohlížeče napiš javascript:alert(document.cookie)

Martin:

V JS alertu jsou cookies webu, v jehož rootu je phpminadmin umístěn + PHPSESSID. Cookie phpMinAdmin_SID uvedeno není.

ikona Jakub Vrána OpenID:

To je tedy zvláštní, jako kdyby prohlížeč cookie zahodil. phpMinAdmin přitom nastavuje expiraci na 0, což znamená "do zavření prohlížeče". Můžeš prosím ověřit, jak přesně se cookie nastavuje? Prozradí ti to třeba Firebug. Alternativně mi mailem pošli adresu, kde phpMinAdmin provozuješ (přihlašovací údaje neposílej).

ikona david@grudl.com:

Narazil jsem na takové drobnosti:

- trošku mě překvapilo, že "přidat další" řádek na stránce "Vytvořit tabulku" přidá řádek na začátek a ne na konec

- protože hodně používám InnoDB, působí slovo "přibližně" velmi rušivě. Možná by se dalo nahradit za ≈ nebo ~. A když už slovo, tak s vlastní třídou, aby je bylo možné přes CSS zesvětlit.

- vlastní třída by se hodila pro příkazy "vypsat" v levém sloupci, taky bych si je v CSS odlišil.

ikona Jakub Vrána OpenID:

Díky za tipy.

Tlačítko „Přidat další“ je u každého pole v tabulce, přidá to vždycky za to které pole. Musí být nějaký způsob, jak přidat sloupec i dovnitř tabulky.

„Přibližně“ mě taky štvalo a chtěl jsem to přesunout do titulku, tam by se to ale těžko vešlo, navíc by muselo být nějak vysvětleno, že to je jen pro InnoDB. Díky za tip, commitnul jsem to.

Třídy se mi přidávat nechce (protože zvětšují objem posílaných dat), v moderních prohlížečích se dají použít pokročilé selektory – hodně to používá http://phpminadmin.sourceforge.net/hever/phpMinAdmin.css.

pojízdná kočka:

ke přidávání tříd -
* u odkazu "vypsat" a seznamu tabulek - velmi bych se přimlouvala za to dát je buďto všechny nabízené tabulky do divu a tomu nastavit třídu, respektive to samé s nečíslovaným seznamem. Je to cca 10 bajtů navíc v CSS se to dá lépe 'uchopit' (v současnosti by odkaz "vypsat" v CSS nejblíže odpovídal kvalifikátoru #menu p>a:first, ale ten by zasáhl i odkazy "SQL příkaz" a "vytvořit novou tabulku"; jak z tohodle ven - nevím - prostě je to řádově komplikovanější a vyžaduje to CSS2 nebo 3 za cenu pár znaků navíc)
* měla bych podobnou námitku k několika odstavcům s příkazovými odkazy:
<p>"pozměnit tabulku", "výchozí hodnoty", ...</p> nebo
<p>"vytvořit proceduru", "vytvořit funkci"</p>
, kde odkazy jsou příliš u sebe (oddělené jen mezerou) a opět je to jen (v CSS) "#content>p>a", který zasáhne i odkazy drobečkovém menu.
Souhlasím s tebou, že přidávat styl do nějakého (obecně dlouhého) výpisu (řádků, tabulek..) zvýší velikost výstupu. Ale případy, co jsem uvedla, mezi ně nepatří, zvětší velikost pouze o nějakejch pitomejch 20 bajtů a umožní, aby se toho chopili CSSkáři a mohli lépe realizovat vlastní styly. Jde jen o to, *aspoň trošku* jim vyjít vstříc. Fakt to je jen o tom, doplnit na jednom místě v levém menu <div id="tables">...</div> a v obsahovém divu u příkazových odkazů k <p>...</p> připsat class="commands" (příklad). To tě přece nezabije, ne? :-)
(prosím, prosíím, udělej to...)

ikona Jakub Vrána OpenID:

Na odkaz "vypsat" se podařilo odkázat heverovi: http://www.adminer.org/hever/adminer.css

Přidání tříd zvážím.

ikona Jakub Vrána OpenID:

Přidal jsem <p id="tables">. Ke všem příkazům se mi třídu přidávat nechce, to můžeš vyřešit nastavením stylu pro všechny odstavce a odebráním např. pro ty drobečky.

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-2016 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.