PHP a odchytávání chyb u mysqli

PHP a odchytávání chyb u mysqli
« kdy: 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.
Kód: [Vybrat]
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.
Kód: [Vybrat]
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 :-(
PMD85 -> Didaktik Gama -> PC XT -> ... x86/x51/ARM
Basic -> Turbo Pascal -> C++ -> Turbo ASM -> C# -> PHP -> Bash :-)


php

Re:PHP a odchytávání chyb u mysqli
« Odpověď #1 kdy: 28. 03. 2018, 16:08:17 »
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, přes které se s DB pracuje mnohem lépe :-)

Re:PHP a odchytávání chyb u mysqli
« Odpověď #2 kdy: 28. 03. 2018, 17:57:09 »
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
PMD85 -> Didaktik Gama -> PC XT -> ... x86/x51/ARM
Basic -> Turbo Pascal -> C++ -> Turbo ASM -> C# -> PHP -> Bash :-)

Kit

Re:PHP a odchytávání chyb u mysqli
« Odpověď #3 kdy: 28. 03. 2018, 19:00:16 »
ad 2) mysqli-connect mi nedovolí nastavení connection-timeout
ad 4) PDO je sice fajn, ale viz bod 2

PDO s timeoutem 20 sekund:
Kód: [Vybrat]
$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:
Kód: [Vybrat]
ini_set('connect_timeout', 20);
ini_set('mysql.connect_timeout', 20);
ini_set('default_socket_timeout', 20);
Něco z toho se chytí.

php

Re:PHP a odchytávání chyb u mysqli
« Odpověď #4 kdy: 28. 03. 2018, 19:59:14 »
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í:
Kód: [Vybrat]
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.


Re:PHP a odchytávání chyb u mysqli
« Odpověď #5 kdy: 29. 03. 2018, 11:38:46 »
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  >:(
PMD85 -> Didaktik Gama -> PC XT -> ... x86/x51/ARM
Basic -> Turbo Pascal -> C++ -> Turbo ASM -> C# -> PHP -> Bash :-)