TalkPHP

TalkPHP (http://www.talkphp.com/forums.php)
-   Advanced PHP Programming (http://www.talkphp.com/advanced-php-programming/)
-   -   Exceptions and suppressing mysqli errors (http://www.talkphp.com/advanced-php-programming/2768-exceptions-suppressing-mysqli-errors.html)

delayedinsanity 05-07-2008 06:04 AM

Exceptions and suppressing mysqli errors
 
I'm just learning about exceptions and the Exception class, so I decided to give this a go;

PHP Code:

// in my construct

try {
    
$this->connectDB();
} catch (
Exception $e) {
    
$e->getMessage();
    die;
}

// the method

private function connectDB () {
    
$this->mysqli = @new mysqli(DB_SERVERDB_USERDB_PASSDB_NAME);
    if (!
is_object($this->mysqli)) {
        throw new 
Exception ("I'm sorry Dave, I'm afraid I can't do that.");
    }


The problem is the @ doesn't seem to be suppressing the error from calling a new mysqli object...

xenon 05-07-2008 09:59 AM

Don't use error suppression (@). It only slows your script. Instead, use error_reporting to show or hide the errors (error_reporting(0) in a live environment, error_reporting(E_ALL) when testing).

mysqli::__construct([...]) returns false if a connection couldn't be established, so there's no need for error suppression there (it doesn't generate a notice/error/warning). Instead, try:

PHP Code:

$this->mysqli = new mysqli(...);
if(
$this->mysqli == false)
{
    echo 
mysqli_connect_error();



sketchMedia 05-07-2008 10:37 AM

Testing it just now, contrary to the manual the __construct method doesn't seem to return false on connect failure; it instead returns an object of type mysqli along with the warning
Code:

Warning:  mysqli::mysqli() [function.mysqli-mysqli]: (28000/1045): Access denied for user 'user'@'localhost' (using password: YES)
therefore use mysqli_connect_errno()

PHP Code:


$mysqli 
= new mysqli('localhost''user''password''db');

if (
mysqli_connect_errno()) { die('Connect failed: ' mysqli_connect_error()); } 

and xenon is correct error suppression can have a speed impact on your script, so use error_reporting(0); to hide all warnings/errors/notices etc etc and use your own error handling stuff (for example exceptions)

delayedinsanity 05-07-2008 02:06 PM

Okay, you both seemed to miss the question, but thank you for trying. :)

I'm not worried about the speed impact of using @, because I'm learning about using the Exception class, and in particular the try {} catch {} and throw expressions. I'm also aware of mysqli_connect_error(), errno(), and die() the problem is I don't want to use those just yet. I want the throw new exception to handle the error, without turning off all error reporting on my test server.

@ isn't working anyways, it's not suppressing the error. Neither is error_reporting(0), it's still pumping out Connect failed: Unknown MySQL server host 'DB_SERVE' (11004). The mispelled CONST is on purpose, I'm trying to cause the error in this case.

Salathe 05-07-2008 02:48 PM

Quote:

Originally Posted by delayedinsanity (Post 14382)
The problem is the @ doesn't seem to be suppressing the error from calling a new mysqli object...

If the code is precisely as you posted, the @ should suppress any error. If you're still getting the error message then show us a full copy/paste script which doesn't work for you so that we can try it.

The following file outputs (for me) the expected output (error successfully suppressed):
Doh MySQLi Exception: Access denied for user 'root'@'localhost' (using password: YES)
PHP Code:

<?php header('Content-Type: text/plain;charset=utf-8'); error_reporting(E_ALL E_STRICT);

class 
DI_Test {

    const 
SERVER 'localhost',
          
USER   'root',
          
PASS   'invalid',
          
DB     'talkphp_test';
    private 
$mysqli;

    public function 
__construct()
    {
        try {
            
$this->connectDB();
        } catch (
Exception $e) {
            die(
$e->getMessage());
        }
    }
    
    private function 
connectDB ()
    {
        
$this->mysqli = @new mysqli(self::SERVERself::USERself::PASSself::DB);
        if (
mysqli_connect_errno())
            throw new 
Exception ('Doh MySQLi Exception: '.mysqli_connect_error());
    }
}

$test = new DI_Test;
var_dump($test);


sketchMedia 05-07-2008 02:54 PM

I believe that message is what the mysqli object is printing from its internal error reporting system so therefore it wont get caught by error_reporting(0) or the @ operator.

i think
PHP Code:

mysqli_report(MYSQLI_REPORT_OFF); 

should shut it up

delayedinsanity 05-07-2008 03:15 PM

Salathe: The code is exactly as posted, minus all the other methods and properties in the class, it would look pretty much the same as yours (with the exception being that my constants are defined outside of the class in a seperate config file, thus the lack of self::)

sketch: I'll try that when I get home, that sounds like it could/should help. The wierd thing I'm curious about is this snippet from the manual on mysqli_report;

PHP Code:

mysqli_report(MYSQLI_REPORT_ALL);

$mysqli = new mysqli("localhost""my_user""my_password""world");

/* check connection */
if (mysqli_connect_errno()) {
    
printf("Connect failed: %s\n"mysqli_connect_error());
    exit();


...seems to imply that even with error reporting on, the error shouldn't pop up unless you explicitly check mysql_connect_errno(), but that's definitely not the case.

I'll update you all when I get home. Thanks again,
-m

sketchMedia 05-07-2008 04:14 PM

I think the manual is a little lacking in areas, it even says that the constructor for mysqli returns FALSE on connect fail, but a constructor can't return values.

taken from "http://uk.php.net/manual/en/mysqli.connect.php"
Quote:

Returns a object which represents the connection to a MySQL Server or FALSE if the connection failed.

delayedinsanity 05-07-2008 04:37 PM

Hahah, as usual the mistake is a silly one.

No exception was being thrown because I was checking if $this->mysqli was an object, which it was, error or not. Using mysqli_connect_error() (or as Salathe did, mysqli_connect_errno()) got it to work.

As a sidenote, mysqli_report() doesn't suppress the PHP notice itself, it just means mysqli_connect_error() doesn't get any information to return to you. So I either have to use @ or error_reporting(0) to test my exception.

Oh and apparently the code wasn't *exactly* as posted, but I won't go into further detail now that it's fixed. Lets just chock it up to early morning coding should not happen in my house. Thank you for your time, I'm here all week.
-m

Salathe 05-07-2008 04:43 PM

Good to see you're happy delayedinsanity :-)

sketchMedia, the manual isn't very clear I must admit! However, it is simply not possible to assign a value of FALSE to a variable when using $var = new Something which is why an empty object is returned on error and you have to check connect_errno/error to see if something went all wonky.

sketchMedia 05-07-2008 07:11 PM

Yep seems the person who wrote that document either misunderstands how the new keyword works or its been copied from the procedural version (which im supposing must have been written first) and they havent changed that, very confusing for beginners and advanced users alike, i think most of the PHP documentation needs an overhaul anyway.

sketchMedia 05-07-2008 07:15 PM

Quote:

As a sidenote, mysqli_report() doesn't suppress the PHP notice itself, it just means mysqli_connect_error() doesn't get any information to return to you.
actually when that is active, errors that the object encounters get passed through an exception called 'mysqli_sql_exception' therefore doesnt go through the normal PHP error reporting; resulting in both '@' and 'error_reporting(0)' failing.

Glad your all sorted though.

sketchMedia 05-07-2008 07:27 PM

Quote:

As a sidenote, mysqli_report() doesn't suppress the PHP notice itself, it just means mysqli_connect_error() doesn't get any information to return to you.
actually when that is active, errors that the object encounters get passed through an exception called 'mysqli_sql_exception' therefore doesnt go through the normal PHP error reporting; resulting in both '@' and 'error_reporting(0)' failing to catch its messages.

Also as an example, the code snippet posted by salathe, when run with mysqli_report(MYSQLI_REPORT_OFF) set, the message generated is:

Code:

Doh MySQLi Exception: Access denied for user 'root'@'localhost' (using password: YES)
which is the exception message set in the catch statement however if its set to on (MYSQLI_REPORT_ALL):

Code:

Access denied for user 'root'@'localhost' (using password: YES)
so you see, with it ON the 'mysqli_sql_exception' overrides the exception being thrown in the class because it is raised inside the mysqli object itself.

Glad your all sorted though.


All times are GMT. The time now is 12:25 PM.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0