Fórum Root.cz
Hlavní témata => Server => Téma založeno: aigor.net 28. 03. 2018, 15:18:15
-
Už druhý den stojím nad naprosto hloupým problémem, nedaří se mi odchytnout ošetřit chybu při spojení na DB přes mysqli v PHP7 (na Debianu)
V hlavním programu mám nastaven vlastní error_handler i exception_handler. Při každé chybě, nebo neošetřené výjimce zapíše záznam do logu a přeruší program. Potud je vše OK.
V následujícím fragmentu třídy se snažím potlačit chybu při chybě spojení a vyhodit vlastní - k tomu nikdy nedojde, protože se vyvolá E_WARNING už na prvním řádku.
if (!@$this->sqli->real_connect($server, $uzivatel, $heslo, $databaze))
{
//trigger_error('Selhalo připojení k SQL serveru, chyba '.$this->sqli->connect_errno.': '.$this->sqli->connect_error, E_USER_ERROR);
die('Connect Error ('.mysqli_connect_errno().') '.mysqli_connect_error());
}
Nedaří se to ošetřit ani přes výjimky. Přepnu mysqli na vyvolávání výjimek a spojím se v bloku try-catch. Sice se vyhodí mysqli_sql_exception, ale zachytím ji až v hlavním programu a ne v tomto bloku.
mysqli_report(MYSQLI_REPORT_STRICT);
try
{
@$this->sqli->real_connect($server, $uzivatel, $heslo, $databaze);
}
catch (mysqli_sql_exception $e)
{
echo 'Zachyceno OK';
die('hello');
}
Fakt už nevidím, kde dělám chybu :-(
-
1. používat @ k potlačení chyb je prasárna
2. jak se připojit k DB napoví dokumentace http://php.net/manual/en/function.mysqli-connect.php
3. nastavení chyb přes funkci mysqli_report funguje až na vykonávané dotazy, nikoliv na samotné připojení k DB
4. doporučuju se podívat na http://php.net/manual/en/book.pdo.php (http://php.net/manual/en/book.pdo.php), přes které se s DB pracuje mnohem lépe :-)
-
ad 1) souhlas, nicméně to nevysvětluje proč to nefunguje. Ten operátor jsem přidával kvůli testování a nechal ho záměrně do dotazu, abych se nedozdvěděl "dej tam zavináč"
ad 2) mysqli-connect mi nedovolí nastavení connection-timeout
ad 3) omyl, kdyby sis přečetl můj příspěvek celý, píšu že místo chyb vyhodí výjimku i při spojování
ad 4) PDO je sice fajn, ale viz bod 2
-
ad 2) mysqli-connect mi nedovolí nastavení connection-timeout
ad 4) PDO je sice fajn, ale viz bod 2
PDO s timeoutem 20 sekund:
$dsn = "mysql:host=$host;dbname=$dbname";
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_TIMEOUT => 20,
);
$dbh = new PDO($dsn, $username, $password, $options);
Kdyby to náhodou nefungovalo, zavolej předtím tohle:
ini_set('connect_timeout', 20);
ini_set('mysql.connect_timeout', 20);
ini_set('default_socket_timeout', 20);
Něco z toho se chytí.
-
ad 1) souhlas, nicméně to nevysvětluje proč to nefunguje. Ten operátor jsem přidával kvůli testování a nechal ho záměrně do dotazu, abych se nedozdvěděl "dej tam zavináč"
ad 2) mysqli-connect mi nedovolí nastavení connection-timeout
ad 3) omyl, kdyby sis přečetl můj příspěvek celý, píšu že místo chyb vyhodí výjimku i při spojování
ad 4) PDO je sice fajn, ale viz bod 2
Ono by to chtělo trochu prozradit implementaci toho, co je v $this->sqli.
Ještě můžeš zkusit následující:
set_error_handler(function ($errno, $errstr) {
throw new RuntimeException($errstr);
});
$this->sqli->real_connect($server, $uzivatel, $heslo, $databaze);
restore_error_handler();
Čímž tím vyvolaný warning převedeš na RuntimeException, kterou už můžeš standardně odchytit v catch.
Nastavení timeoutu pro PDO funguje tak jak popisuje Kit.
-
PDO s timeoutem 20 sekund:
Díky, tohle jsem v dokumentaci předtím neobjevil. Vidím, že s PDO jsem zaspal dobu, jdu to napravovat...
Nicméně chyba objevená - samozřejmě mezi židlí a klávesnicí. Uvedený kód je z konstruktoru pomocé třídy - a samozřejmě ve vlastním namespace.
Proto výjimku nešlo odchytit jako 'catch (exception $e)', ale jako 'catch (\exception $e)' :o
naprostá hloupost na kterou koukám celej den >:(