PHP_03 - Soubory a MySQL databáze
1. Obsah
- Obsah
- Úvod
- FOpen
- File_Exists
- FGetS
- FClose
- FPuts
- Další souborové funkce
- Ukázky práce se soubory
- MySQL - připojení
- MySQL - operace nad databází
- Úkol
- Zdroje a citace
2. Úvod
Protože většina z vás bude v projektu pracovat s nějakým souborem (obrázek, uploadovaný textový soubor a pod.), ukážeme si základni funkce a způsoby jak pracovat se soubory uloženými na server. Kompletní nápověda k práci se soubory v PHP je v kapitole Filesystem Functions v PHP manualu.
Jelikož součástí vašeho projektu také musí být využítí datového uložište s podporou dotazovacího jazyka SQL, tak si v kapitolách 10 a 11 ukážeme základní prácí s MySQL databází. Budeme používat MySQL rozšíření, které používá funkce z kapitoly MySQL Functions - opět v PHP manuálu, ale samozřejmě můžete použít i natiní objektovou nádstavbu v PHP a to MySQLi. MySQLi je v PHP již od verze PHP 4.1.3 a je jí funkčně velice podobná. Dokonce se zvažuje zrušit podporu staršího modulárního rozšíření (extension) MySQL někdy v budoucích verzích PHP.
V neposlední řadě můžete také využít čístě objektového přístupu k databází přes PDO vrstvu, která se za vás postará o většinu úskalí a hrozeb pro vaší webovou aplikaci (například před útoky přes SQL injections a pod). Ale volitelné použití těchto dalších přístupů již nechám zcela na vašem samostudiu a houževnatosti:-).
3. FOpen
Otevře soubor nebo URL na zadané adrese.
Syntaktický zápis funkce:
int fopen (string filename, string mode [, int use_include_path])
Volby pro parametr string
mode:
r
- pouze pro čtení; ukazatel na začátek souborur+
- pro čtení a zápis; ukazatel na začátek souboruw
- pouze pro zápis; ukazatel na začátek souboru a zkrátí soubor na nulovou délku; pokud soubor neexistuje, pokusí se ho vytvořitw+
- pro čtení a zápis; ukazatel na začátek souboru a zkrátí soubor na nulovou délku; neexistující soubor se pokusí vytvořita
- pouze pro zápis; ukazatel na konec souboru; neexistující soubor se pokusí vytvořita+
- pro čtení a zápis; nastaví ukazatel na konec souboru; pokud soubor neexistuje, pokusí se ho vytvořit
4. File_Exists
Zjistí zda soubor existuje a vrátí true
při úspěchu a false
při neúspěchu.
Syntaktický zápis funkce:
bool file_exists (string filename)
5. FGets
Přečte řádek ze souboru.
Syntaktický zápis funkce:
string fgets (int fp, [int length])
Popis chování a parametrů:
- Vratí řetězec o délce maximálně
length
(uvedeno v byte) přečtený ze souboru. - Parametr
fp
je ukazatel na otevřený soubor pomocí funkcefopen()
nebofsockopen()
- Funkce vrací
false
, pokud již není co číst.
6. FClose
Zavře otevřený soubor pomocí funkce fopen
.
Syntaktický zápis funkce:
int fclose (int fp)
Popis chování a parametrů:
- Parametr
fp
je ukazatel na otevřený soubor pomocí funkcefopen()
nebofsockopen()
. - Funkce vrací
true
při úspěchu afalse
při neúspěchu.
$soubor = "c:\temp\pokus.txt"; // jmeno otviraneho souboru
$fp = false; // predpokladam neuspech (soubor neexistuje)
if (File_Exists($soubor)) { // existuje soubor
$fp = FOpen($soubor, "r"); // otevreni souboru pro cteni
}
if (!$fp) {
echo 'Soubor se nepovedlo najít/otevřít'; // nepodarilo se otevreni
}
$vysledek = FGetS($fp,50); // precteni 50ti znaku ze souboru
FClose($fp); // zavreni souboru
echo $vysledek; // vypis vysledku
7. FPuts nebo FWrite
Zapíše zvolený textový řetězec do vybraného souboru.
Syntaktický zápis funkce:
int fputs (int fp, string str [, int length])
int fwrite (int fp, string str [, int length])
Popis chování a parametrů:
- Parametr
fp
je ukazatel na otevřený soubor pomocí funkcefopen()
nebofsockopen()
. - Parametr
str
je zapisovaný řetezec. - Nepovinný parametr
length
udává kolik bitů se má zapsat z řetezcestr
. - Funkce vrací počet zapsaných bitů nebo
false
při neúspěchu. - Počet bitů vždy nemusí znamenat počet zapsaných znaků! Kódovací sady jako UTF-8 a vyžši kódují speciální znaky nejméně dvěma bity!
8. Další souborové funkce
Seznam dalších funkcí, které se vám mohou hodit při práci se soubory. Jejich podrobné specifikace snadno najdete v PHP manuálu nebo pokud máte v prohlížeči zaplý javascript a jste online, tak přímo kliknutím na název funkce!
int filesize (string filename)
- vrátí velikost souboru v bytechstring fread (int fp, int length)
- binárně bezpečné čtení ze souboruint fseek (int fp, int offset [, int whence])
- posune ukazatel pro čtení/zápis v souboruint rewind (int fp)
- posune ukazatel pro čtení/zápis na začátek souborustring fgetc (int fp)
- přečte jeden znak ze souboruint feof (int fp)
- vracítrue
pokud jsme na konci souboru, jinak vracítrue
string fgetss (int fp, int length [, string allowable_tags])
- přečte řádek ze souboru a odstraní HTML značky
9. Ukázky práce se soubory
Pro jednoduchost skriptů nejsou prováděny žádné ošetření chyb.
Příklad 9.1:
Přečtení této stránky bez HTML značek.
<?php
$fp = fopen("03_PHP_-_Soubory_a_MySQL.html", "r");
while (!feof($fp)) {
$data = fgetss($fp, 1024); // cteme zaznamy ze souboru po 1024 bytech
// a funkce fgetss nam zarovne odstrani vsecny HTML tagy
echo $data; // vypisujem zaznamy
}
fclose($fp); // zavreme za sebou otevreny soubor
?>
Příklad 9.2:
Jednoduché počítadlo přístupů na stránku.
<?php
function pocitej () {
$fp = fopen("pocitadlo.txt", "r+"); // otevreme soubor
$pocet = fgets($fp,6) + 1; // precteme hodnotu a zvetsime o 1
rewind($fp); // presuneme ukazatel na zacatek
fputs($fp, $pocet); // vlozime novou hodnotu
fclose($fp); // zavreme soubor
echo "<h1>Počet přístupů: ".$pocet."</h1>"; // vypíšeme hodnotu
}
pocitej();
?>
10. MySQL - připojení
Nejlepší bude ukázat příklad celého připojení k databázi a pak si rozebereme zajímavé příkazy a jejich funkčnost.
Příklad 10.1:
Kompletní připojení k datábázi, s ošetřením chyba nastavením znakové sady (kódování) češtiny. Předpokládáme, že data v mysql databázi
máme v kódování UTF-8 a náš web používá ISO-8859-2 (tedy latin2).
<?php
/*
* Nejprve nastavime nejake promenne - v projektu je urcite umistete do samostatneho souboru,
* ktery posleze zavolate pomoci require!
*/
$PHP_mysql_server = 'localhost'; // adresa MySQL serveru [server[:port]]
$PHP_mysql_login = 'root'; // login k MySQL serveru
$PHP_mysql_pass = 'heslo'; // heslo k MySQL serveru
$PHP_mysql_db = 'projekt'; // nazev databaze v MySQL
$PHP_mysql_charset = 'latin2'; // znakova sada webu projektu
/*
* Nyni se pustime do samotneho pripojovani k mysql databazi
*/
$mc = mysql_connect($PHP_mysql_server, $PHP_mysql_login, $PHP_mysql_pass);
if ($mc) // pripojeni k DB ok
{
$md = mysql_select_db($PHP_mysql_db); // zvolime nasi databazi z $PHP_mysql_db
if ($md) // zvoleni DB ok
{
$mq = mysql_query("SET CHARACTER SET $PHP_mysql_charset"); // znakova sada pro vystup na web
if (mysql_errno() != 0)
{ // chyba zvoleni znakove sady
echo 'Chyba pri nastveni znakove sady: '.mysql_error();
exit; //die(); halt(); - ukonceni vykonavani skriptu
} // END OF: chyba zvoleni znakove sady
} // END OF: if ($md) // zvoleni DB ok
else
{ // nepovedlo se zvoli DB
echo 'Chyba zvoleni db: '.mysql_error();
exit; //die(); halt(); - ukonceni vykonavani skriptu
} // END OF: nepovedlo se zvoli DB
} // END OF: if ($mc) // pripojeni k DB ok
else
{ // pripojeni k MySQL sedveru se nepovedlo
echo 'Chyba pripojeni k MySQL: '.mysql_error();
exit; //die(); halt(); - ukonceni vykonavani skriptu
} // END OF: pripojeni k MySQL serveru se nepovedlo
?>
Seznam použitých funkcí a jejich popis:
mysql_connect()
- Funkce co se stará o samotné připojení k databázi, jako návratovou hodnotu máfalse
při neúspěchu, jinak vrací referenci na připojenou sessionu. Seznam parametrů je celkem jasný z příkladu, jen zmíním, že pokud vám MySQL server, ke kterému se připojujete, běží na nestandartním TCP portu (sandartní je 3306), tak port změníte například na port 4321 v uvedeném příkladu 10.1 takto:$PHP_mysql_server = 'localhost:4321'
.mysql_select_db()
- Funkce nastaví databázi se kterou chceme na MySQL serveru pracovat pomocí jednoho stringového parametru a vrátítrue
při úspěchu afalse
při neúspěchu. Jedná se v podstatě o obdobu vámi dobře známého SQL příkazuUSE jmeno_nasi_databaze
.mysql_query()
- Tato funkce se stará vykonání libovolného SQL dotazu () a vracífalse
při neúspěchu atrue
při úspěchu (u příkazůINSERT, UPDATE, DELETE, DROP
apod.) nebo odkaz zdroj výsledků volaného příkazu (např. uSELECT, SHOW, DESCRIBE
a pod).mysql_errno()
- Funkce vrací číslo chybové hlášky po vykonání dotazu funkcimysql_query()
a vrací0
pokud žádná chyba nenastala.mysql_error()
- Funkce vrací text chybové hlášky po vykonání dotazu funkcimysql_query()
a vrací prázdný řetězec pokud žádná chyba nenastala.mysql_close()
- Funkce uzavře sessionu aktuálního sezeni do MySQL databáze a vrátítrue
při úspěchu afalse
při neúspěchu.
11. MySQL - operace nad databází
Napřed si ukážeme strukturu tabulky nad kterou budeme dělat naše ukázky a poté se ukážeme některé základní operace nad touto tabulkou z PHP.
Příklad 11.1:
V datábázi projekt
, ke které se připojujeme z PHP v příkladu 10.1 založíme tabulku oddeleni
, která bude obsahovat název odděleni (nazev
) a jeho evidenční číslo (id
).
-- Tabulka oddeleni
-- ----------------
-- +-------+-------------+------+-----+---------+----------------+
-- | Field | Type | Null | Key | Default | Extra |
-- +-------+-------------+------+-----+---------+----------------+
-- | id | int(11) | NO | PRI | NULL | auto_increment |
-- | nazev | varchar(60) | YES | | NULL | |
-- +-------+-------------+------+-----+---------+----------------+
CREATE TABLE oddeleni (
id INT(11) AUTO_INCREMENT, -- cislo hlidano automatickym pocitadlem
nazev VARCHAR(60), -- nazev oddeleni
PRIMARY KEY (id)
)
ENGINE=innoDB; -- transakcni engine
Příklad 11.2: - INSERT
Vložíme nové oddělení s názvem "Ekonomické"
<?php
$msq = mysql_query("INSERT INTO oddeleni(nazev) VALUES('Ekonomické')"); // vkladani noveho oddeleni
if (mysql_errno() == 0) {
echo 'Nové oddělení se povedlo vložit a bylo mu přiřazeno čislo: '.mysql_insert_id();
} // END OF: if (mysql_errno() == 0) {
else { // nejaka chyba
echo 'Během vkládání nového záznamu nastala chyba: '.mysql_error();
} // END OF: else { // nejaka chyba
?>
Seznam nových použitých funkcí a jejich popis:
mysql_insert_id()
- Funkce vrátí ID generované na případnémAUTO_INCREMENT
atributu tabulky po příkazuINSERT
.- Všiměte si, že u SQL dotazu ve funkci
mysql_query()
není na konci středník! Středník nejen, že není potřeba, ale dokonce se doporučuje ho nevkládat (z bezpečnostních důvodů při zákazu zřetezení SQL dotazu v query a pod.)
Příklad 11.3: - UPDATE
Aktualizuj naposledy vložený záznam na "Ekonomicke" (funkce mysql_insert_id()
registruje jen INSERT
vložené v rámci
aktuálně připojené sessionu, jakmile je zavolan mysql_close()
nebo již skript doběhl do konce, tak hodnotu ID posledního záznamu nezískáte!
<?php
$msq = mysql_query("UPDATE oddeleni SET nazev = 'Ekonomicke' WHERE ID = '".mysql_insert_id();."'");
if (mysql_errno() != 0) {
echo 'Při aktualizaci záznamu nastala chyba: '.mysql_error();
} // END OF: if (mysql_errno() != 0) {
else { // zaznam uspesne smazan
echo 'Záznam úspěšně aktualizován!';
} // END OF: else { // zaznam uspesne smazan
?>
Příklad 11.4: - DELETE
Smažeme oddělení s hodnotou id
2.
<?php
$msq = mysql_query("DELETE FROM oddeleni WHERE id = '2'");
if (mysql_errno() != 0) {
echo 'Při mazání záznamu nastala chyba: '.mysql_error();
} // END OF: if (mysql_errno() != 0) {
else { // zaznam uspesne smazan
if (mysql_affected_rows() != 0)
echo 'Záznam se povedlo úspěšně smazat!';
else
echo 'Záznam neexistuje!';
} // END OF: else { // zaznam uspesne smazan
?>
Seznam nových použitých funkcí a jejich popis:
mysql_affected_rows()
- Funkce vrátí počet ovlivněných záznamů po použití dotazůUPDATE, DELETE
apod.- Všiměte si, že dvojka v klauzuli
WHERE
je v apostrofech i když je to číslo. Z důvodu předcházení útokům typu SQL injections, všechny hodnoty a proměnné vždy uzavírejte do apostrofů nebo uvozovek!
Příklad 11.5: - SELECT
Vypíšeme všechna oddělení do tabulky se sloupci "Č." jako číslo oddělení a "Název oddělení".
<?php
$msq = mysql_query("SELECT * FROM oddeleni");
if (mysql_errno() != 0) {
echo 'Při pokusu od načtení dat došlo k chybě: '.mysql_error();
} // END OF: if (mysql_errno() != 0) {
else { // zaznam uspesne smazan
if (mysql_num_rows($msq) != 0) { // vypisem tabulku
echo '<table><tr><th>Č.</th><th>Název oddělení</th></tr>';
while ($rec = mysql_fetch_assoc($msq)){ // prochazej vsechny zaznam tabulky
echo "<tr><td>{$rec['id']}</td><td>{$rec['nazev']}</td></tr>\n"; // vypisuj radky tabulky
} // END OF: while ($rec = mysql_fetch_assoc($msq)){ // prochazej vsechny zaznam tabulky
echo '</table>';
} // END OF: (mysql_num_rows($msq) != 0) { // vypisem tabulku
else
echo 'V tabulce oddeleni neexistuje neexistuje žádny záznam!';
} // END OF: else { // zaznam uspesne smazan
?>
Seznam nových použitých a dalších doporučených funkcí a jejich popis:
mysql_num_rows()
- Funkce vrátí počet zaznamu které obsahujeSELECT
v předané referenci z query (v našem případě je reference uložena v proměnné$msq
).mysql_fetch_assoc()
- Funkce vrátí asociativní pole všech atributů vrácenýchSELECT
em v předané referenci z query (v našem případě je reference uložena v proměnné$msq
).mysql_fetch_row()
- To samé jeko funkcemysql_fetch_assoc()
jen vrací očíslované pole od nuly místo asociativního.mysql_fetch_array()
- Funkce je kombinací funkcimysql_fetch_assoc()
amysql_fetch_row()
. Varací jak asociativní pole atributů, tak očíslované atributy od 0.mysql_real_escape_string()
- Funkce se stará o bezpečné ošetření proměnných před vložením do SQL query (například zřetězením). Tuto funkci musíte použít na ošetření všech proměnných předaných z formůlářů abyste předěšly případným útokům ze strany návštěvníků vašeho webu/aplikace. Funkce bere v potaz bepečnostní politiku a nastavení MySQL serveru, takže ji nemůžete použít dřív, než jste připojeni k databází přikazemmysql_connect()
.mysql_escape_string()
- Funkce je horší offline verzí funkcemysql_real_escape_string()
, ale je od verze PHP 5.4 DEPRICATED, takže ji nepoužívejte, neb bude v dalších verzích PHP odstraněna.
12. Úkol
- Vložte na svou úvodní stránku rozpracovaného projektu počitadlo.
- Pozor souboru s hodnotou počítadla např. "
pocitadlo.txt
" musíte nastavit atributy pro zápis. - Soubor s počítadlem musí mít příponu .php NE .html!
13. Zdroje a citace
- ACHOUR, Mehdi, Friedhelm BETZ, Antony DOVGAL, Nuno LOPES, Hannes MAGNUSSON, Georg RICHTER, Damien SEGUY a Jakub VRÁNA. PHP: PHP Manual. [online]. [cit. 2012-08-21]. Dostupné z: www.php.net/manual/
- SQL injection: Wikipedia, the free encyclopedia. In: [online]. [cit. 2012-08-23]. Dostupné z: http://en.wikipedia.org/wiki/SQL_injection
- VRÁNA, Jakub. Kniha 1001 tipů a triků pro PHP [online]. 1. vyd. 2010 [cit. 2012-08-21]. Dostupné z: http://php.vrana.cz/kniha-1001-tipu-a-triku-pro-php.php
- Poznámky neznámého učitele ze SPŠ Zlín :-)