PHP Exception::getCode() contradicts Throwable interface that it implements

浪子不回头ぞ 提交于 2021-02-11 15:37:29

问题


I've found a contradiction I could not understand.

Exception::getCode()

has this definition:

final public Exception::getCode ( void ) : mixed

with description:

Returns the exception code as integer in Exception but possibly as other type in Exception descendants (for example as string in PDOException)

but the Exception class implements Throwable interface that defines:

abstract public getCode ( void ) : int

So how for an example PDOException as a descendant of Exception could return string type with getCode() without violating the Throwable interface that defines return type as int?

Putting aside PDOException I don't think it would be possible even for the Exeption class to work with the getCode() : mixed

See proof:

<?php

interface Bar {
    public function getCode() : int;
}

class Foo implements Bar
{
    public function getCode()
    {
        return 'test';
    }
}

$bar = new Foo;
echo $bar->getCode();

runnig the script above gives an error:

PHP Fatal error: Declaration of Foo::getCode() must be compatible with Bar::getCode()

as expected.

Does anyone know why this is possible that Exception class implements Throwable interface but has a different implementation of getCode() and everything "works"?

Maybe it does not have a different implementation but if so then PDOException could not return any other type than int - proof:

<?php

interface Bar {
    public function getCode() : int;
}

class Foo implements Bar
{
    public function getCode() : int
    {
        return 'test';
    }
}

$bar = new Foo;
echo $bar->getCode();

gives an error:

PHP Fatal error: Uncaught TypeError: Return value of Foo::getCode() must be of the type int, string returned

that contradicts with the statement PDOException may return string as return of getCode()

Assuming PDOException::getCode() may return a string instead of int and PDOException extending RuntimeException that defines:

public Exception::__construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]]

then how to throw your own CustomException that extends from PDOException in case of getting string as error code from PDOException::getCode()?

example code that fails (for the example it always sets error code as string):

class CustomException extends \PDOException
{
    public function __construct($msg = '', $code = 0, $previous = null)
    {
        $code = 'CustomException error code as string: "$code"';
        parent::__construct($msg, $code, $previous);
    }
}

try {

    try {
        $dsn = 'mysql:dbname=not_existing_database;host=127.0.0.1';
        $user = 'dbuser';
        $password = 'dbpass';

        $pdo = new \PDO($dsn, $user, $password, [\PDO::ERRMODE_EXCEPTION => true]);

    } catch (\PDOException $e){
        throw new CustomException($e->getMessage(), $e->getCode());
    }

} catch (\Exception $e){
    echo 'Code: ' . $e->getCode() . PHP_EOL;
    echo 'Message: ' . $e->getMessage() . PHP_EOL;
}

gives:

PHP Fatal error: Uncaught Error: Wrong parameters for CustomException([string $message [, long $code [, Throwable $previous = NULL]]])

Example code tested with PHP 7.3.18 CLI.

来源:https://stackoverflow.com/questions/62234089/php-exceptiongetcode-contradicts-throwable-interface-that-it-implements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!