Fatal error: Declaration of Exceptions::getMessage() must be compatible with Throwable::getMessage(): string in /var/www/html/php-books/php-and-mysql-web-development/chapter07/user-defined-exceptions-pag-202/exception-class.php on line 21

https://www.php.net/manual/en/language.exceptions.extending.php

<?php

class Exceptions implements Throwable
{
    protected $message = 'Unknown exception';   // exception message
    private $string;                          // __toString cache
    protected $code = 0;                        // user defined exception code
    protected $file;                            // source filename of exception
    protected $line;                            // source line of exception
    private $trace;                           // backtrace
    private $previous;                        // previous exception if nested exception

    public function __construct($message = '', $code = 0, Throwable $previous = null){

    }

    final private function __clone(){

    }           // Inhibits cloning of exceptions.

    final public function getMessage(){

    }     // message of exception

    final public function getCode(){

    }           // code of exception

    final public function getFile(){

    }          // source filename

    final public function getLine(){

    }          // source line

    final public function getTrace(){

    }          // an array of the backtrace()

    final public function getPrevious(){

    }       // previous exception

    final public function getTraceAsString(){
    } // formatted string of trace

    // Overrideable
    public function __toString() {
    } // formatted string for display
}

?>

phpstorm with php 8.2 returns these errors
Private methods cannot be final as they are never overridden by other classes:17
Return type declaration must be compatible with Throwable->getMessage() : string:21
Return type declaration must be compatible with Throwable->getFile() : string:29
Return type declaration must be compatible with Throwable->getLine() : int:33
Return type declaration must be compatible with Throwable->getTrace() : array:37
Return type declaration must be compatible with Throwable->getPrevious() : null|\Throwable:41
Return type declaration must be compatible with Throwable->getTraceAsString() : string:45
'__toString' method must return a string:49

    Well, the error is that it wants you to specify what the method will return so that it matches the return type specified for the Throwable interface (The : string or whatever type is specified before the opening "{"). But why you are even trying this is a mystery to me. See the note on that linked page:

    Note:
    PHP classes cannot implement the Throwable interface directly, and must instead extend Exception.

      Fatal error: A function with return type must return a value in /var/www/html/php-books/php-and-mysql-web-development/chapter07/user-defined-exceptions-pag-202/exception-class.php on line 22

      class Exceptions implements Throwable
      {
          protected $message = 'Unknown exception';   // exception message
          private $string;                          // __toString cache
          protected $code = 0;                        // user defined exception code
          protected $file;                            // source filename of exception
          protected $line;                            // source line of exception
          private $trace;                           // backtrace
          private $previous;                        // previous exception if nested exception
      
          public function __construct($message = '', $code = 0, Throwable $previous = null){
      
          }
      
        private function __clone(){
      
          }           // Inhibits cloning of exceptions.
      
          final public function getMessage():string{
           return;
          }     // message of exception
      
          final public function getCode():int{
      return;
          }           // code of exception
      
          final public function getFile():string{
              return;
          }          // source filename
      
          final public function getLine():int{
              return;
          }          // source line
      
          final public function getTrace():array{
              return;
          }          // an array of the backtrace()
      
          final public function getPrevious():null{
              return;
          }       // previous exception
      
          final public function getTraceAsString():string{
              return;
          } // formatted string of trace
      
          // Overrideable
          public function __toString():string {
              return;
          } // formatted string for display
      }

      Return value is expected to be 'int', 'void' returned:26
      Return value is expected to be 'int', 'void' returned:34
      Return value is expected to be 'array', 'void' returned:38

        The error message says it all. You have added the "promise" to return a string, but you instead return null ( by just saying return; without actually having it return anything). For now, pending making the functions actually do something useful, you could just change it to return "";

          Fatal error: Class Exceptions cannot implement interface Throwable, extend Exception or Error instead in /var/www/html/php-books/php-and-mysql-web-development/chapter07/user-defined-exceptions-pag-202/exception-class.php on line 3

          class Exceptions implements Throwable
          {
              protected $message = 'Unknown exception';   // exception message
              private $string;                          // __toString cache
              protected $code = 0;                        // user defined exception code
              protected $file;                            // source filename of exception
              protected $line;                            // source line of exception
              private $trace;                           // backtrace
              private $previous;                        // previous exception if nested exception
          
              public function __construct($message = '', $code = 0, Throwable $previous = null){
          
              }
          
            private function __clone(){
          
              }           // Inhibits cloning of exceptions.
          
              final public function getMessage():string{
               return "";
              }     // message of exception
          
              final public function getCode():int{
                  return "";
              }           // code of exception
          
              final public function getFile():string{
                  return "";
              }          // source filename
          
              final public function getLine():int{
                  return "";
              }          // source line
          
              final public function getTrace():array{
                  return "";
              }          // an array of the backtrace()
          
              final public function getPrevious():null{
                  return null;
              }       // previous exception
          
              final public function getTraceAsString():string{
                  return "";
              } // formatted string of trace
          
              // Overrideable
              public function __toString():string {
                  return "";
              } // formatted string for display
          }

          I suppose I should change class Exceptions implements Throwable for class Exceptions extends Exception or Error

          but after I have these errors

          Fatal error: Type of Exceptions::$file must be string (as in class Exception) in /var/www/html/php-books/php-and-mysql-web-development/chapter07/user-defined-exceptions-pag-202/exception-class.php on line 3
          Type must be 'string' (as in base class '\Exception'):8
          Type must be 'int' (as in base class '\Exception'):9
          Cannot override final method Exception->getMessage():21
          Cannot override final method Exception->getCode():25
          Cannot override final method Exception->getFile():29
          Cannot override final method Exception->getLine():33
          Cannot override final method Exception->getTrace():37
          Cannot override final method Exception->getPrevious():41
          Cannot override final method Exception->getTraceAsString():45

          bertrc I suppose I should change class Exceptions implements Throwable for class Exceptions extends Exception or Error

          Yes, as @NogDog already said.

          The other error messages also say what is wrong. For some of them you haven't declared the type (and why bother declaring them at all if you're inheriting them anyway?). The error message tells you what types they're supposed to have; others (declared final) you can't override at all as they're built in to the PHP runtime and you shouldn't even be trying to override them.

            Type must be 'string' (as in base class '\Exception'):8
            Type must be 'int' (as in base class '\Exception'):9

            protected string $file; // source filename of exception
            protected int $line; // source line of exception

            I don't know how to fix the problem

            Cannot override final method Exception->getMessage():21
            Cannot override final method Exception->getCode():25
            Cannot override final method Exception->getFile():29
            Cannot override final method Exception->getLine():33
            Cannot override final method Exception->getTrace():37
            Cannot override final method Exception->getPrevious():41
            Cannot override final method Exception->getTraceAsString():45

            bertrc Cannot override final method Exception

            You cannot redefine those "final" methods from the parent class, so do not even include them in your new child class.

            bertrc
            Type must be 'string' (as in base class '\Exception'):8
            Type must be 'int' (as in base class '\Exception'):9

            What are lines 8 and 9? And why do you need to re-declare them here if they are inherited from the parent class? (I.e.: if you are not going to change them, then there is no need to include them in the new, child class -- they will be inherited from the parent class.) In other words, you may only need as little as this:

            class MyException extends Exception {
                // all done
            }
            

            See Example #2 at https://www.php.net/manual/en/language.exceptions.extending.php for how you might extend Exception, only adding/changing things that you specifically want/need (and are allowed) to change.

            NogDog

            NogDog In other words, you may only need as little as this:

            class MyException extends Exception {
                // all done
            }

            90% of the time when I'm extending an Exception it looks just like that.

            class ParseException extends DomainException {}

            Later, I can distinguish ParseException from other DomainExceptions by giving it its own catch block.

            I have only this class

            class Exceptions extends Exception
            {
                protected $message = 'Unknown exception';   // exception message
                private $string;                          // __toString cache
                protected $code = 0;                        // user defined exception code
                protected string $file;                            // source filename of exception
                protected int $line;                            // source line of exception
                private $trace;                           // backtrace
                private $previous;                        // previous exception if nested exception
            
                public function __construct($message = '', $code = 0, Throwable $previous = null){
            
                }
            
                private function __clone(){
            
                }           // Inhibits cloning of exceptions.
            
                final public function getMessage():string{
             return "";
                }     // message of exception
            
                final public function getCode():int{
                    return "";
                }           // code of exception
            
                final public function getFile():string{
            return "";
                }          // source filename
            
                final public function getLine():int {
                    return "";
                }          // source line
            
                final public function getTrace():array{
                    return "";
                }          // an array of the backtrace()
            
                final public function getPrevious():null{
                    return "";
                }       // previous exception
            
                final public function getTraceAsString():string{
                    return "";
                } // formatted string of trace
            
                // Overrideable
                public function __toString():string {
                    return "";
                } // formatted string for display
            }

            I should create a new class I have only this file exception-class.php

            Weedpacket recommend this class

            class MyException extends Exception {
            // all done
            }
            90% of the time when I'm extending an Exception it looks just like that.

            class ParseException extends DomainException {}

            these errors
            Cannot override final method Exception->getMessage():21
            Cannot override final method Exception->getCode():25
            Cannot override final method Exception->getFile():29
            Cannot override final method Exception->getLine():33
            Cannot override final method Exception->getTrace():37
            Cannot override final method Exception->getPrevious():41
            Cannot override final method Exception->getTraceAsString():45

            bertrc Cannot override final method Exception->getMessage():21
            Cannot override final method Exception->getCode():25
            Cannot override final method Exception->getFile():29
            Cannot override final method Exception->getLine():33
            Cannot override final method Exception->getTrace():37
            Cannot override final method Exception->getPrevious():41
            Cannot override final method Exception->getTraceAsString():45

            Again: any method defined as final in the parent class cannot be redefined in a child class, so do not even include it in your child class. Only include methods and/or properties that you need to be different from the parent class's definitions -- with the caveat that if they are "final", you cannot redefine them at all. Therefore, based on https://www.php.net/manual/en/language.exceptions.extending.php, the only methods you might include in your child class are __construct() and __toString() (and odds are low you'll ever need to modify either of them, I suspect).

              PS: In case it's not clear to you, the child class has access to all the methods defined in the parent class if not overridden by the child class, so you do not lose any functionality by not defining them in your child class.

                PPS: Part of your confusion may be that you started out trying to implement an interface. In that case, the interface is a sort of promise that your class will provide those methods. But now you are extending the Exception class, which already implements that interface, so you do not have to worry about its methods being defined. You only need to worry about which (non-final) methods of Exception you need to modify in your new child class, which may (and likely in this case, will) be none of them.

                  Write a Reply...