0

I have a mysqli call ($result = $this->mysqli->query($query)) in which $query is an insert statement that generates the error: "Duplicate entry 'dt' for key 'username_UNIQUE'";. I have set the mysqli reporting mode with

\mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

The callstack at this point is about 8 methods deep, and there are several try-catch blocks along the way.

Finally there is a try-catch block in index.php, the outermost block of code. The exception seems to be ignoring all the deeper try-catch blocks, but is caught in the outermost one. Not sure if it matters, but all code blocks are in class methods except for the code in index.php.

To demonstrate this problem, I'll show you index.php and the first method called from index.php.

<?php
    define('DS',DIRECTORY_SEPARATOR);
    define('APP_START',microtime(true));
    define('ROOT_DIR',dirname(__FILE__).DS);
    define('FW_DIR',sprintf("%svendor%sfw%s",ROOT_DIR,DS,DS));
    define('APP_DIR',sprintf( '%sapp%s',ROOT_DIR,DS));
    try {
        // set up the autoloader
        require sprintf('%sbootstrap%sbootstrap.php',FW_DIR,DS);
        // next, set up the factory for all future class instantiation
        $factory = new fw\factory\ClassFactory();
        // create the app
        $app = $factory->getClass('app\app');
        // process the request
        $ob = "";
        $result = $app->go();
        // return anything in the output buffer then the application output
        echo $ob.$result;
    } catch (Exception $e) {
        die("Caught Exception in index.php: ".$e->getMessage());
    }

I have determined that the above code executes into $app->go(), but does not reach the line echo $ob.$result;.

Now here's the $app class:

<?php
namespace app;
class App extends \fw\app\App
{
    protected $trace = false;
    public function __construct(protected \fw\exception\ErrorHandler $errorhandler,
                                protected \fw\session\WebSession $session,
                                protected \app\http\RequestHandler $requesthandler,
                                protected \database\MySqlDB $db
                                ) {
        parent::__construct();
    }
    public function go(){
        try {
            $this->requesthandler->init($this->errorhandler,$this->session,$this->db);
            $result = $this->requesthandler->processrequest(false);
        } catch (Exception $e) {
            die(__METHOD__." : ".$e->__toString());
        }
        return $result;
    }
}

I have determined that the code enters $this->requesthandler->processrequest(false);. Many method calls deeper it reaches the insert statement that triggers the exception.

The output from the above is "Caught Exception in index.php: Duplicate entry 'dt' for key 'username_UNIQUE'" which clearly comes from the catch in index.php. My question is, why does the code not die in the catch block in the $app class (or any of the other try-catches deeper in the stack).

5
  • 2
    At least App class catches \app\Exception exceptions, and not \Exception. See the difference? Commented Nov 13, 2024 at 14:09
  • @u_mulder, no I don't understand what you are saying. My understanding is that the catch in $app should trap any exception trickling up from inside processrequest(false); Commented Nov 13, 2024 at 14:11
  • 1
    Time to read about php namespaces. Commented Nov 13, 2024 at 14:15
  • Are you saying that exceptions are qualified by the namespace in which they are generated, and that I should include namespaces in my type hints in the catch block ? I wrapped the $this->mysqli->query($query) in a try-catch block and it didn't trap the exception either. Commented Nov 13, 2024 at 14:18
  • 1
    OK a quick read and I discovered the \Exception vs Exception. And for this I thank you. I put the backslash into the $app->go() catch block and it was caught there. Off to do more reading. Thanks again @u_mulder Commented Nov 13, 2024 at 14:26

1 Answer 1

-1

Your App class is specified to be using

namespace app;

which means that the classes referenced will be looked for inside this namespace. Therefore, your

try {
    //some code
} catch (Exception $e) {
    //some code
}

will catch any Exception object inside the app namespace, that is, any \app\Exception that might be thrown. The actual exception that is thrown is an instance of \Exception and hence it will not be caught with the catch that you have. You could have

} catch (\Exception $e) {

for example and that's the full namespace name of the Exception class whose instances you intended to catch.

Look into aliasing and importing as well as namespaces for more information.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.