| Autor | Zpráva | ||
|---|---|---|---|
| llook Profil |
Časté potížeNa určité věci narazí dřív nebo později skoro každý, proto se některá témata opakují. Nejčastější potíže s PHP jsem se pokusil vypsat zde, třeba to někomu pomůže.Původní obsah přesnut níže – nejčastější problémy v začátcích [#2]. Zde se budu snažit shromažďovat odkazy na další online materiály o PHP a částečně i MySQL od začátků až po současný vývoj. # Kde hledat víc informací• Především PHP manuál (php.net), anglicky. Reference jazyka, reference funkcí. Nevíte, jak funguje nějaká funkce? Určitě ji vyhledejte v manuálu, např. explode().• Pokročilejší články a moderní trendy ve vývoji aplikací v PHP lze najít na Zdrojáku s nálepkou PHP (databáze). • Kdysi dobrý, ale dnes zastaralý PHP tutoriál (linuxsoft.cz). Je psán pro PHP 4, v současnosti nebudou jeho scripty s defaultním nastavením fungovat. Inspirujte se, ale neberte vše doslova. • Mírně pokročilejší témata: PHP triky, La Trine >> PHP, phpFashion. • Anglicky psané net.tutsplus.com/category/tutorials/php a phpmaster.com/category/php-tutorials • MySQL: MySQL Documentation (anglicky), MySQL >= 4.1 a čeština • SQLite: SQLite.org • Slepice nebo vejce? Podobně věčná je i otázka jestli používat framework, než založite vlastní téma, přečtěte si Framework: Ano, či ne?. # Výkonnost aplikace• Disproving the Single Quotes Performance MythRozcestník na další témata [#3] |
||
|
Časová prodleva: 6 dní
|
|||
| Alphard Profil |
Nejčastější problémy začátečníkůZde najdete netřízené nečastější začátečnické problémy, začínáte-li, nejdříve se podívejte sem.# Chyba „Parse error: syntax error, …“Chyba syntaxe znamená, že máte špatně napsaný skript. Zde dvojnásob platí: Zkuste to řešit samostatně předtím než pošlete dotaz do diskuse. I začátečník by měl znát základní syntaxi jazyka a být schopný si opravit překlep.Jak na tuto chybu? Hláška vypadá nějak takto: Parse error: syntax error, unexpected něco in /cesta/soubor.php on line číslo. Zvýrazněné části jsou název souboru a číslo řádku. Překontrolujte kód na daném řádku daného souboru a také o řádek výše (např. zapomenutý středník na konci předchozího příkazu). Pokud přesto nic neobjevíte, pošlete dotaz do diskuse, přiložte několik řádků kódu kolem problémového místa (nekopírujte celé skripty s desítkami/stovkami řádků kódu!) a označte řádek, kam odkazuje chybová hláška. Tip: Syntaktickým chybám lze předcházet používáním vhodného PHP editoru (respektive IDE), kde se syntaktické chyby zvýrazňují už během psaní. # Warning mysql_fetch_array() (nebo jiná MySQL funkce): supplied argument is not a valid MySQL result resource…případně Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given…Znamená, že nejspíš máte chybu v SQL dotazu, jehož výsledek se snažíte přečíst. Funkce mysql_query může krom výsledku dotazu vrátit i FALSE (Viz manuál) a ve skriptu byste s tím měli počítat. Příklad: $result = mysql_query($sql);
if(!$result){ /* Kód pro zalogování chyby a zobrazení nějaké chybové stránky uživateli. */ }mysql_error()- k problémům projevujícím se výše uvedenou hláškou přikládejte rovnou i výsledek mysql_error()!
Poznámka: Stejně jako u všech ostatních chyb, ani tady není vhodné nechat chybové hlášky vypisovat na ostrém webu přímo do stránky, tedy např.: mysql_query($sql) or die(mysql_error()); je přípustné pro testovací prostředí, ale na ostrém webu by to nemělo být.
$query = 'select * from tabulka where id = 5';
$result = mysql_query($query);
if (!$result) { # zde by šlo doplnit podmínku && DEBUG == true, ale začátečníci to asi řešit nebudou a pak použijí jiný db layer
echo "<br>\n", htmlspecialchars($query, ENT_QUOTES), "<br>\n", mysql_error(), "<br>\n";
}
while ($item = mysql_fetch_assoc($result)) {
// normální zpracování výsledku,
// stále je ale možné, že nebyly nalezeny žádné výsledky, to nekontrolujeme, viz mysql_num_rows()
}# Nefungují proměnné z formuláře nebo z URL (vypnuté register globals)K hodnotě vstupního pole s názvem „nazev“ se dříve přistupovalo přes proměnnou $nazev. Z bezpečnostních důvodů je dnes tato možnost na většině serverů zakázaná.
K hodnotám zaslaným metodou POST lze přistupovat přes $_POST['nazev'], metodou GET přes $_GET['nazev']. K proměnným z cookies přes pole $_COOKIE.
Případně lze využít pole $_REQUEST, ve kterém jsou všechny proměnné zaslané metodou GET, POST i v cookies.
Podobně lze získávat hodnoty serverových proměnných z pole $_SERVER a session z $_SESSION.
Chceme-li uploadovat soubor, pracujeme s $_FILES. Register globals lze zapnout (pokud je to povoleno) vložením následujícího kódu do .htaccess. Tento přístup ale nelze doporučit. PHP ho od verze 5.4 nepodporuje. php_flag register_globals on # Získaní IP adresyIP adresu lze najít v poli $_SERVER, viz register globalsecho 'Vaše IP adresa je: '.$_SERVER['REMOTE_ADDR']; # Divný znak (čtvereček) na začátku includovaného souboru v UTF-8Soubor v kódování UTF-8 a UTF-16 může začínat takzvanou BOM signaturou. V případě UTF-8 je sice zcela zbytečná, přesto ji některé editory vkládají.Řešením je ve svém editoru nastavit, aby BOM nevkládal (v PSPadu Nastavení » Nastavení Programu » Program 2), nebo to nějakým způsobem odmazat. V některých editorech to nelze. A stručný popis UTF-8 Někdy lze BOM poznat dle prázdného místa. # Lomítka ve vstupních hodnotáchPři určitém nastavení PHP se v hodnotách z formulářů samo přidá zpětné lomítko před znaky uvozovek ("), apostrofů (') a zpětných lomítek (\).
Pokud je to tak nastavené, funkce get_magic_quotes_gpc() vrací 1, jinak 0. Zařídit, aby $_GET['promenna'] nebyla takto olomítkována lze takto:
<?php
if (get_magic_quotes_gpc()) {
$_GET['promenna'] = stripslashes($_GET['promenna']);
}
?># headers already sent…Pokud už byl generovaný nějaký výstup, tak už nelze používat funkceheader(), setcookie() ani session_start(). Jejich volání skončí chybou.
Přesvědčete se, že před začátkem <?php ?> není žádný text (ani mezera) a že nebylo nic odesláno třeba funkcemi jako echo nebo print.
Jestliže se ve skriptu volá session_start(), je obvykle rozumné volání dát hned jako první příkaz, případně nejblíže začátku skriptu jak je možné.
Pokud je text v UTF-8, tím výstupem může být i tzv. BOM signatura, vizte výše zmíněný Divný znak (čtvereček). # Jak předat proměnnou vkládanému souboruSouboru vkládaném pomocíinclude/require nelze předat proměnnou tímto způsobem:
<?php include 'soubor.php?e=mc2'; // NELZE !!! ?> <?php $promenna = 'hodnota'; include 'soubor.php'; ?> Předání title z includovaného souboru do indexu # Kam zmizelo odřádkování za „Pokud je hned za ukončením PHP ještě znak „ |
||
|
Časová prodleva: 4 roky
|
|||
| Alphard Profil |
#3 · Zasláno: 26. 9. 2008, 21:05:20 · Upravil/a: Alphard
Rozcestník
V prvním příspěvku můžete nalézt netřízené nejčastější potíže a jejich stručná řešení. V dalších příspěvcích jsou k dispozici hotová řešení dalších častých problémů. Jejich obsah je uveden (a průběžně aktualizován zde): • [#4] Problémy s e-maily • Diakritika v emailech • Odeslání více položek • [#5] Rekurzivní zipování • [#6] Registrace a přihlášení uživatelů • [#7] Výpis výsledků z databáze (nebo z jiného zdroje) do tabulky o více sloupcích • [#8] Odlišení lichých a sudých řádků • [#9] Práce se soubory • Upload a download souborů • Vypsání náhodného obrázku • [#10] Užitečné odkazy • Regulární výrazy • [#11] Hashování • [#12] Zkrácení perexu |
||
|
Časová prodleva: 6 měsíců
|
|||
| Alphard Profil |
#4 · Zasláno: 3. 4. 2009, 22:33:54 · Upravil/a: Alphard
Problémy s e-maily
Jednoduché použití funkce mail() se 3 povinnými parametry často nestačí. # Kódování e-mailu, aneb abychom neposílali otazníky.Text musíme posílat s uvedeným kódováním. Dříve se doporučovalo ISO-889-2, dnes bych neměl strach z UTF-8 a vzhledem k předpokládanému vývoji ho doporučuji.Kódování předmětu (a dalších hlaviček) a zprávy samotné se zadávají samostatně. Předmět zakódovat musíme, zakódováním těla zprávy nic nezkazíme. Hlavičky by mohly vypadat nějak takhle: $head = "MIME-Version: 1.0".PHP_EOL; Zde je zadané kódování zprávy. Když budeme posílat html mail, zde změníme na text/html. $head .= "Content-Type: text/plain; charset=\"utf-8\"".PHP_EOL; Tuto hlavičku uvedeme, pokud kódujeme i tělo zprávy. $head .= "Content-Transfer-Encoding: base64".PHP_EOL; To by ze základních hlaviček mohlo být vše. Teď kódování předmětu: $predmet = "=?utf-8?B?".base64_encode(autoUTF($predmet))."?="; Všimněte si, že pracujeme s utf-8 a používáme funkci autoUTF(), viz následující. Pokud budeme chtít použít jméno, poskládáme hlavičku takto: "From: =?UTF-8?B?".base64_encode(autoUTF("Moje Jméno"))."?=<ja@email.cz>".PHP_EOL;Už zbývá jen zakódování zprávy samotné, opět použijeme base64_encode() $zprava = base64_encode(autoUTF($zprava)); Abychom bez námahy získali text v utf, použijeme k tomu funkci od Davida Grudla. Dokážete-li získat data ve správném kódování (např. máte vše v utf-8), lze tento krok vynechat. To je vše, vypadá to trochu složitě, ale vše můžeme naskládat do vlastní funkce. <?php
/* *************** diskuse.jakpsatweb.cz *** PHP FAQ ********************** */
function autoUTF($s)
{
if (preg_match('#[\x80-\x{1FF}\x{2000}-\x{3FFF}]#u', $s)) // detect UTF-8
{
return $s;
}
elseif (preg_match('#[\x7F-\x9F\xBC]#', $s)) // detect WINDOWS-1250
{
return iconv('WINDOWS-1250', 'UTF-8', $s);
}
else // assume ISO-8859-2
{
return iconv('ISO-8859-2', 'UTF-8', $s);
}
}
function cs_mail($to, $predmet, $zprava, $head = "")
{
$predmet = "=?utf-8?B?".base64_encode(autoUTF($predmet))."?=";
$head .= "MIME-Version: 1.0".PHP_EOL;
$head .= "Content-Type: text/plain; charset=\"utf-8\"".PHP_EOL;
$head .= "Content-Transfer-Encoding: base64".PHP_EOL;
$zprava = wordwrap(base64_encode(autoUTF($zprava)), 78, PHP_EOL, true);
return mail($to, $predmet, $zprava, $head);
}
/* ********************************************************************** ** */Jak to použít? Zkopírujte si do stránky výše uvedený kód a pak stačí tuto funkci zavolat. Ukázka použití: <?php
$mail = 'jmeno@email.cz';
$predmet = 'ěščřžýáíé46';
$zprava = "Test, \r\n ěščřžýáíé123456789";
if (cs_mail($mail, $predmet, $zprava, "From: vas@web.cz".PHP_EOL))
{
echo 'E-mail byl úspěšně odeslán.<br>';
}
else
{
echo 'E-mail se bohužel nepodařilo odeslat.<br>';
}To je vše, už jen vysvětlit. $mail obsahuje e-mailovou adresu příjemce, $predmet předmět e-mailu a $zprava zprávu samotnou. To je asi jasné. 4. parametr obsahuje další hlavičky, oddělené koncem řádku. # Odeslání více položekČasto máme obsáhlejší formulář a potřebujeme z něj odeslat všechny jeho položky, řešení je jednoduché. Stačí všechny proměnné spojit do $zprava.Pokud posíláme mail jako html, je vhodné ošetřit vstupy funkcí htmlspecialchars($s, ENT_QUOTES).
$zprava = "Jméno: {$_POST['jmeno']}".PHP_EOL;
$zprava .= "Příjmení: {$_POST['prijmeni']}".PHP_EOL;
$zprava .= "Telefon: {$_POST['telefon']}".PHP_EOL;
$zprava .= "Ulice: {$_POST['ulice']}".PHP_EOL;
$zprava .= "Žádost: {$_POST['zadost']}".PHP_EOL;
$zprava .= "Poznámka: {$_POST['poznamka']}".PHP_EOL;Teď stačí $zprava vložit jako třetí parametr funkce mail. Pro složitější věci (např. přílohy) doporučuji PHPMailer nebo Nette mail. |
||
| Alphard Profil |
#5 · Zasláno: 3. 4. 2009, 22:35:53 · Upravil/a: Alphard
# Rekurzivní zipování<?php
class Zipuj
{
protected $jmeno_zipu;
protected $root;
protected $zip;
public function __construct($root = ".", $jmeno_zipu = "zip.zip")
{
$this->root = $root;
$this->jmeno_zipu = $jmeno_zipu;
$this->zip = new ZipArchive();
$this->zip->open($this->jmeno_zipu, ZIPARCHIVE::CREATE);
$this->nactiAdr();
$this->uloz();
}
public function nactiAdr($cesta = "")
{
$hn = scandir($this->root.$cesta);
foreach ($hn as $file)
{
if ($file == "." || $file == "..")
{
continue;
}
if (is_dir($this->root.$cesta."/".$file))
{
$this->zip->addEmptyDir($cesta."/".$file);
$this->nactiAdr($cesta."/".$file);
}
else
{
$this->zip->addFile($this->root.$cesta."/".$file, $cesta."/".$file);
}
}
}
public function uloz()
{
$this->zip->close();
}
}
// zazipuje nám vše na cestě zadané v první parametru a výsledný zip pojmenuje dle druhého parametru
$zalohuj = new Zipuj('./test/test2', 'zaloha.zip'); Pozn: Vyžaduje knihovnu zip (nastavuje se v php.ini), není-li k dispozici, lze očekávat chybu Fatal error: Class 'ZipArchive' not found in … |
||
| Alphard Profil |
#6 · Zasláno: 3. 4. 2009, 22:37:37 · Upravil/a: Alphard
# Registrace uživatelůNa začátek uvedu odkazy na několik pokročilejších technik zabezpečení (nebo jeho obejití). Ukradli jsme účet k Facebooku. S Androidem za pět sekund Série článků Nenechte si uhodnout Session ID od Jana Tichého. Jednoduchá kostra přihlašovacího scriptu Základ napsal srigi. Tento script je návodem na jednoduchou realizaci přihlašování uživatelů na webu za pomoci databázové tabulky a sessions. Databázová tabulka Informace o uživatelích budeme uchovávat v databázové tabulce. Vytvoříte ji tak, že spustíte následující sql dotaz. CREATE TABLE users ( id int NOT NULL auto_increment, username varchar(20) NOT NULL, # délka je na vás password char(40) NOT NULL, # další sloupce lze doplnit dle potřeby, tohle je minimum PRIMARY KEY (id) ); Hned můžeme přidat nového uživatele. Heslo z bezpečnostích důvodů zahašujeme. Jméno je admin a heslo secret. INSERT INTO users (id, username, password)
VALUES (
NULL, 'admin', SHA1('secret')
);PHP kód. Je podrobně komentován. V komentářích je mj. popsáno, kam vkládat obsah. <?php
$path = "/"; // máte-li stránky v rootu, nechte bezezměny, pokud je provozujete v nějakém podadresáři, zadejte jeho jméno
// např. stránky mám na moje-domena.cz/adresar/, tak zadám $path = "/adresar/";
// funkce pro ošetření vstupních dat od uživatele
// viz http://cz.php.net/manual/en/info.configuration.php#ini.magic-quotes-gpc
function db_escape($str)
{
return mysql_real_escape_string(@get_magic_quotes_gpc() ? stripslashes($str) : $str);
}
include "pripojeni_db.php"; // soubor pripojeni_db.php zajistí připojení k databázi a výběr databáze, se kterou pracujeme
session_start(); // tohle je nezbytné a je nutné uvést tuto funkci na všech stránkách, kam se přihlášený uživatel dostane
// možnost nastavit automatické spouštění session_start() nechávám stranou
// zjistíme, co chce uživatel dělat
if (isset($_SESSION['username']) && isset($_GET['logout']))
{
// uživatel je přihlášen a chce se odhlásit, takže smažeme údaje o přihlášení
$_SESSION = array();
if (isset($_COOKIE[session_name()]))
{
setcookie(session_name(), '', time()-42000, '/');
}
session_unset();
session_destroy();
// a přesměrujeme na index.php
header("location:http://".$_SERVER['SERVER_NAME'].$path."index.php", TRUE, 303);
exit;
}
elseif (isset($_SESSION['username']))
{
//session_regenerate_id(); // ochrana před session fixation, lze vynechat
// uživatel je přihlášen a nechce se odhlásit, zde zobrazíme obsah pro registrované
// můžeme využit include apod.
// tohle informuje uživatele, že je přihlášen a vypíše odkaz pro odhlášení
// můžeme to ale přemístit do includovaného souboru (kam se nám hodí)
echo "<p>Přihlášen: $_SESSION[username] <a href=\"http://".$_SERVER['SERVER_NAME'].$path."index.php?logout=1\">odhlásit</a></p>\n";
}
else
{
// uzivatel není přihlášen
// pokud odeslal přihlašovací údaje, snaží se přihlásit
if (isset($_POST['username']) && isset($_POST['password']))
{
// ošetříme vstupní údaje od uživatele
// funkce trim() má význam hlavně u hesla, ořeže bílé znaky (např. mezery) na začátku a konci řetězce
$username = db_escape(trim($_POST['username']));
$password = db_escape(trim($_POST['password']));
// zjistíme, jestli je v databázi daný uživatel a jestli se prokazuje platným heslem
// více o ukládání hesel, např. o tzv. solení, najdete na http://php.vrana.cz/ukladani-hesel.php
$result = mysql_query("SELECT COUNT(*) FROM users WHERE username = '$username' AND password = sha1('$password')");
if (mysql_result($result, 0)) // předpokládáme, že dotaz proběhl úspěšně, pokud ne, bude stejně vráceno false
// true (a splnění podmínky) nastane pouze tehdy, když v databázi existuje správná kombinace uživatelského jména a hesla
{
// uložíme potřebné SESSION proměnné
$_SESSION['username'] = $username;
$_SESSION['cas_prihlaseni'] = time(); // čas, kdy se uživatel přihlásil, pozor, nejedná se o čas poslední akce, nevím, jestli ho využijete, může být smazán
// po přihlášení uživatele přesměrujeme na index.php
header ("location:http://".$_SERVER['SERVER_NAME'].$path."index.php", TRUE, 303);
exit; // aby bylo pravidlům učiněno zadost, zde stejně končí podmínka a jiná nemůže být splněna
}
else
{
// uživatel zadal neplatné přihlašovací údaje
// přesměrujeme ho na index.php a zobrazíme chybovou hlášku
header ("location:http://".$_SERVER['SERVER_NAME'].$path."index.php?incorrect_login=1", TRUE, 303);
exit;
}
}
else
{
// uživatel není přihlášen a ani neodeslal přihlašovací formulář, tak mu ho zobrazíme
echo "<div>";
if (isset($_GET['incorrect_login']))
{
echo "<p style=\"color: #F00\">Zadali jste neplatné uživatelské jméno nebo heslo</p>\n";
}
// zobrazíme formulář pro přihlášení
?>
<form action="index.php" method="post">
Jméno: <input name="username" type="text"><br>
Heslo: <input name="password" type="password"><br>
<input name="submit" type="submit" value="Přihlásit">
</form>
</div>
<?php
}
}
?># Solený hashStručné vysvětlení principu soli od JokeraPodrobnější informace o bezpečnosti hesel, nejen solení. Taktéž od Jokera. |
||
|
Časová prodleva: 4 měsíce
|
|||
| Alphard Profil |
#7 · Zasláno: 3. 8. 2009, 12:52:10 · Upravil/a: Alphard
# Výpis výsledků z databáze (nebo z jiného zdroje) do tabulky o více sloupcíchTestovcí tabulka obsahuje 7 dní.CREATE TABLE `dny` (
`den` varchar(10) default NULL
);
INSERT INTO `dny` VALUES ('Pondělí'), ('Úterý'), ('Středa'), ('Čtvrtek'), ('Pátek'), ('Sobota'), ('Neděle');Řazení po řádcích Výsledek vypadá takhle: 1. Pondělí 2. Úterý 3. Středa 4. Čtvrtek 5. Pátek 6. Sobota 7. Neděle Kód, který to zajistí: $result = mysql_query("select den from dny");
define ("COLS", 3); // počet sloupců
echo "<table>\n";
for ($i = 0; $zaznam = mysql_fetch_assoc($result); $i++)
{
if ($i % COLS == 0) echo "<tr>";
echo "<td>".($i+1).". ".$zaznam['den']."</td>";
if ($i % COLS == COLS - 1) echo "</tr>\n";
}
if ($i % COLS != 0)
{
while ($i++ % COLS != 0)
{
echo "<td> </td>";
}
echo "</tr>\n";
}
echo "</table>\n";Řazení po sloupcích Tentokrát to vypadá takhle: 1. Pondělí 4. Čtvrtek 7. Neděle 2. Úterý 5. Pátek 3. Středa 6. Sobota A kód, kterým to vytvoříme: $result = mysql_query("select den from dny");
while ($line = mysql_fetch_assoc ($result))
$zaznamy[] = $line;
define ("COLS", 3);
$pocetRadku = ceil(count ($zaznamy) / COLS);
echo "<table>\n";
for ($i = 0; $i < $pocetRadku; $i++)
{
echo "<tr>";
for ($j = 0; $j < COLS; $j++)
{
echo "<td>";
if (isset($zaznamy[$j*$pocetRadku + $i]))
echo ($j*$pocetRadku + $i + 1).". ".$zaznamy[$j*$pocetRadku + $i]['den'];
else
echo " ";
echo "</td>";
}
echo "</tr>\n";
}
echo "</table>\n"; |
||
|
Časová prodleva: 5 dní
|
|||
| Alphard Profil |
#8 · Zasláno: 8. 8. 2009, 01:10:01 · Upravil/a: Alphard
# Odlišení lichých a sudých řádkůPři výpisu dat (nejen z databáze) často potřebujeme odlišit liché a sudé řádky.Vytvoříme si dvě CSS třídy. .licha {font-weight: bold; color: #00f}
.suda {font-style: italic; color: #063}V praxi bychom asi měnili jen pozadí, ale to nemohu v této diskusi demonstrovat. Teď již zbývá jen vypsat data a odlišit jednotlivé řádky. Využijeme tabulku z předchozího přikladu. $result = mysql_query("select den from dny"); // výběr dat z databáze
echo "<table>";
$m = 0; // pomocná proměnná, můžeme ji zároveň použít pro číslování řádků
while ($line = mysql_fetch_assoc($result)) // data vypisujeme v cyklu
{
echo "<tr class=\"".(++$m % 2 ? "licha" : "suda")."\">"; // tady se za pomoci modula a ternárního operátoru vypíše vhodná třída
echo "<td>$m. {$line['den']}</td>"; // zde je $m využita jako číslo řádku
echo "</tr>\n";
}
echo "</table>";Jak to funguje? Hodnota proměnné $m se při každém průchodu cyklem zvyšuje o 1. Využitím matematické funkce modulo (zbytek po celočíselném dělení) určíme, jestli je daný řádek lichý nebo sudý, a pomocí ternárního operátoru vložíme správnou třídu. Jak to vypadá? Výhodou tohoto řešení je možnost využít $m k číslování řádků. 1. Pondělí 2. Úterý 3. Středa 4. Čtvrtek 5. Pátek 6. Sobota 7. Neděle Další možností (a tentokrát zapsanou přehedněji) je neustálé prohazovaní hodnot true a false v jedné proměnné. echo "<ul>";
$suda = false;
while ($line = mysql_fetch_assoc($result))
{
$trida = $suda ? "suda" : "licha"; // stejné jako minule
$suda = !$suda; // ! neguje současnou hodnotu a negaci ukládá pro příští iteraci
echo "<li class=\"$trida\">{$line['den']}</li>";
}
echo "</ul>";Tentokrát ukázka generuje seznam. • Pondělí • Úterý • Středa • Čtvrtek • Pátek • Sobota • Neděle |
||
| Alphard Profil |
#9 · Zasláno: 8. 8. 2009, 01:38:23 · Upravil/a: Alphard
Práce se soubory# Upload souborůUpload a download souborů na LinuxsoftuPHP triky – Zabezpečený upload souborů PHP triky – Zmenšení obrázků # Překročení pamětiFatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 9216 bytes) in …Nejčastěji se tato chyba vyskytuje při úpravě velkých obrázků. Knihovna GD musí otevřít obrázek, který je mnohem větší než např. *.jpg soubor, a překročí maximální povolenou paměť. Bez změny nastavení hostingu obtížně řešitelný problém, jedna z možností je použít např. ImageMagick. Vysvětelní. # Vypsání náhodného obrázku<?php $obrazky = array( // pole s adresami obrázků "img/9.jpg", "img/21.jpg", "img/e02.jpg", ); shuffle($obrazky); echo "<img src=\"$obrazky[0]\">"; // jeden náhodný echo "<img src=\"$obrazky[1]\">"; // druhý náhodný ?> Jestli chceme vybírat ze všech .jpg souborů v adresáři bez jejich vypisování, stačí předchozí script upravit na: <?php
$path = "img/";
$obrazky = glob("$path*.jpg");
shuffle($obrazky);
echo "<img src=\"$obrazky[0]\">"; // jeden náhodný
echo "<img src=\"$obrazky[1]\">"; // druhý náhodnýPokud jsou obrázky v databázi, lze je jednoduše vybrat dotazem: select obrazek from obrazky order by rand() limit 2 Podstatné je order by rand(), zbytek si upravte dle potřeby. |
||
|
Časová prodleva: 1 rok
|
|||
| Alphard Profil |
#10 · Zasláno: 15. 9. 2010, 11:17:10 · Upravil/a: Alphard
# Užitečné odkazyV tomto příspěvku budou postupně přibývat odkazy na řešení častých nebo zajímavých problémů v PHP.# Nadpis skupiny nejen při výpisu z databázeAanicka andulka B bolek boris Viz Nadpis skupiny. # EscapováníEscapování - definitivní příručka# Uvozovky# Regulární výrazyOnline testování a stručný přehledPodrobné shrnutí syntaxe, návody a hotová řešení Seriál na rootu V PHP používejte funkce z rodiny preg_, skupina ereg_ je deprecated (tj. zavržená, v dalších verzích bude zrušena). Pro testování shody a získání výsledků preg_match() a preg_match_all(). Pro úpravy řetězce preg_replace(). Modifikátory v PHP manuálu. Další odkazy: Regulární výrazy na wikipedii http://phpfashion.com/zradne-regularni-vyrazy-v-php # Návrh aplikaceTriviální způsob includování obsahu stránky spolu s titulkem# Práce s XMLMetody parsování XML# CronÚlohy v PHP na serveru Programujte.com |
||
|
Časová prodleva: 7 dní
|
|||
| Alphard Profil |
#11 · Zasláno: 22. 9. 2010, 15:04:20
# Jak získat zpět text zakódovaný přes MD5 (SHA-1, SHA-256, …)?Nijak, nejde to.V první řadě je nutné si uvědomit, že MD5 (SHA-1, SHA-256, atp.) je otisk, ne zašifrování ani zakódování. Samotný otisk nedává dost informací, aby z něj šlo rekonstruovat vstup, ze kterého byl vytvořen. Logicky když např. MD5 otisk má vždy 32 bajtů a vstup může být téměř libovolně velký, musejí být různé vstupy dávající stejné otisky. Ze samotného otisku pak nelze poznat, který z možných vstupů k němu vedl. # Jak na funkci „zapomenuté heslo“, když mám jen otisk (hash) hesla?(častá otázka po zjištění, že hash nejde „dekódovat“)Toto se obvykle řeší tak, že se uživateli nastaví nové náhodně vygenerované heslo a to se mu pošle. Lepší řešení je poslat uživateli výzvu s odkazem na stránku, kde si může heslo změnit. Zabráníme tak případnému měnění hesel útočníkem (který heslo sice nezíská, ale obtěžuje naše uživatele). Schopnost zaslat uživateli jeho původní heslo lze považovat za příznak vážné bezpečnostní chyby. Znamená to totiž, že vůbec existuje možnost heslo získat. A když to dokáže aplikace, dokáže to i případný útočník, který by se do ní naboural. Viz Poslání zapomenutého hesla. |
||
| Alphard Profil |
#12 · Zasláno: 24. 9. 2010, 09:56:15 · Upravil/a: Alphard
# Zkrácení článku pro výpis perexuČasto je třeba vypsat v seznamu článků jen jejich krátkou ukázku, tzv. perex. Pokud článek neobsahuje html značky, lze použít jednoduchéselect substring_index(`obsah`, ' ', 10) perex from `clanky` Jednoduchou úpravou select concat(substring_index(`obsah`, ' ', 10), '…') perex from `clanky` Pokud zkracujeme na pevnou délku (nehledáme mezery) lze upravit tak, aby se … doplnil jen když se zkracuje: select concat(substr(`obsah`, 1, 200), if(length(`obsah`) > 200, '…', '')) perex from `clanky` Na úrovni PHP lze zkrácení textu dosáhnout funkcí substr(), případně mb_substr(). echo substr("Lorem ipsum dolor sit amet, consectetur adipiscing elit.", 0, 17)."…";Složitější úpravy, např. vyřešení problémů s neuzavřenými html značkami, se obvykle řeší v PHP. Často stačí, když všechny značky odstraníme, tj. použijeme funkci strip_tags(), a následně zkrátíme (druhý script v Zkrácení textu s XHTML značkami). Pokud je nutné značky zachovat, viz Zkrácení textu s XHTML značkami. V obou případech je u delších článků vhodné z databáze vybrat určitý nadlimitní počet znaků, který se v PHP dále zkrátí. Není nutné načítat celé články. Pokud používáte nějaký šablonovací systém, postará se o konečnou fázi sám. Latte filter v Nette: <a href="…">{$linkText|truncate:20}</a>Smarty modifikátor truncate: <h1>{$articleTitle|truncate:30:"…":true}</h1> |
||
|
Časová prodleva: 1 rok
|
|||
| Alphard Profil |
#13 · Zasláno: 23. 2. 2012, 13:49:40 · Upravil/a: Alphard
Komunikace mezi javascriptem a PHP# Jak přenést proměnnou z javascriptu do PHPMám tento kód, ale nefunguje mi dle očekávání:<script>
var i = confirm('blablbla');
</script>
<?php
echo $i;Proč to nemůže fungovat? Protože PHP se nejdříve zpracuje na serveru, teprve výsledná html stránka se odešle klientovi a ten začne vyhodnocovat javascript. V této chvíli sice může vyvolat dialogové okno a zeptat se uživatele na informace, ale již vygenerovanou stránku nelze zpětně upravit. Jak to udělat jinak? Je důležité si uvědomit, že proměnné naplněné v js lze do php odeslat nejdříve při dalším požadavku na server. Pak máme několik možností. • Přesměrování stránky na sebe sama a doplnění informací do url – výhodou je možnost okamžitého překreslení nové stránky již na serveru, nevýhodou je velká prodleva, než se uživateli nová stránka načte a ztráta všechny neuložených věcí (u rozepsaného formuláře). • Odeslání skrytého formuláře na server (např. do iframe), možnost použít kromě dat v url i post data – výhodou je možnost odeslání post dat nebo třeba i upload obrázku na pozadí, přenáší se pouze užitečná data, stránka se znovu nenačítá. Nevýhodou je obtížnější získání odpovědi serveru. • Vyvolat jiný požadavek na server, např. v js vytvořit objekt obrázku. Nevýhodou je, že nezískáme odezvu serveru, data lze tedy přenášet jen jedním směrem. • Vytvořit cookies, která se při dalším požadavku na server odešle automaticky. Tento způsob je také v dané chvíli jednosměrný a je zde riziko, že uživatel stránku opustí a data se na server už nedostanou. Je to ale použitelné např. pro jednoduchou anktetu. • Využít AJAX – hlavní výhodou je, že lehce najdete hotové řešení, i když ne vždy optimální (jednoduchá ukázka, řešení s jQuery – jen na tohle je framework zbytečně velký, ale jestli už ho stejně načítáte, proč ho nepoužít). Tato metoda je univerzální a častou používaná. Počítá se zde s okamžitou odpovědí serveru, která vyvolá předem určenou js funkci (která může reagovat na odpověď např. změnou stránky). Komunikace se serverem je asynchronní, tj. zpracování dalšího javascriptu nečeká na dokončení předchozí požadavku. Tato řešení jsou bohužel závislá na funkčním javascriptu, když základ řešení necháte na html formuláři, bude to fungovat vždy (myslete i na mobilní zařízení). # Jak přenést proměnnou z PHP do javascriptuTento směr je značně jednodušší, protože PHP část se vykonává dříve.var vekUzivatele = <?php echo $vekUzivatele; ?>; // kdyby se předával string, musí se použít uvozovky a správné escapování Pokud přenášíte více hodnot, mohl by se vám hodit JSON. Umí s ním pracovat php i javascript. Práce s cookies# Rozdíl ve viditelnosti cookies při vytvoření javascriptem a PHPData obsažená v cookies se mezi javascriptem a PHP předávají v http hlavičce. V době jejich platnosti jsou ukládána a spravována prohlížečem klienta. Pokud tedy v js vytvoříme cookies, je odezva okamžitá a hned na dalším řádku kódu ji můžeme přečíst. Jakmile ale zapojíme PHP, musíme počítat s čekáním na další požadavek (načtení stránky). Teprve s ním prohlíteč vloží do své žádosti o novou stránku aktuální data z cookies a serverový script je uvidí. V počáteční fázi zpracování stránky jsou z requestu vytvořena superglobální pole, zde $_COOKIES. Toto pole zůstává v průběhu běhu scriptu již statické. Pozor, ani funkce setcookie() toto pole již nezmění, pouze přidá do nové hlavičky odesílané klientovi nová data. Z toho plyne, že PHP cookies uvidí až po znovunačtení stránky. |
||
|
Časová prodleva: 4 měsíce
|
|||
| Alphard Profil |
Konfigurace PHPPHP interpreta nastavujeme především editací souboru php.ini (další možností je např. ini_set()).# Nalezení správného php.ini souboruČastou chybou je editace špatného souboru. Ten správný naleznete ve výpisu phpinfo() pod klíčem Loaded Configuration File .# Zapnutí výpisu všech chyb a varování1) V globálním konfiguračním souboru php.ini nebo od PHP 5.3 v souboru .user.ini display_errors = On error_reporting = E_ALL 2) V souboru .htaccess (pokud PHP běží jako modul mod_php5 v Apache) <IfModule mod_php5.c> php_flag display_errors On php_value error_reporting 30719 </IfModule> 3) Na začátku skriptu (neukáže např. syntaktické chyby, ke kterým dojde před spuštěním skriptu) <?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);Všechny typy chyb jsou popsány v dokumentaci PHP - Predefined Constants. |
||
|
Časová prodleva: 1 rok
|
|||