Search code examples
phpparameterstypingclass-constants

PHP: Class constants in type declarations of input paramaters


For a custom logger I want to force the caller to pass a valid class constant defined in Psr\Log\LogLevel.

This class is defined like:

namespace Psr\Log;
/**
 * Describes log levels.
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT     = 'alert';
    const CRITICAL  = 'critical';
    const ERROR     = 'error';
    const WARNING   = 'warning';
    const NOTICE    = 'notice';
    const INFO      = 'info';
    const DEBUG     = 'debug';
}

The loggers' function (wrong) looks like:

public static function log($log, LogLevel $logLevel = null): void {
   // .....
}

This does not work because LogLevel::DEBUG for instance is a string and not an instance of the class. Is there any way to enforce a class constant in a PHP type declaration? Because if I define string then you can pass any string obviously, but I just want to allow the declared constants.


Solution

  • PHP doesn't have constant restrictions, only types.

    But you can do a workaround like this:

    class LogLevel
    {
        protected string $logName;
    
        private function __construct(string $logName)
        {
            $this->logName = $logName;
        }
        public function getName(): string
        {
            return $this->logName;
        }
    
        public static function emergency(): self
        {
            return new self('emergency');
        }
    
        public static function alert(): self
        {
            return new self('alert');
        }
    
        public static function critical(): self
        {
            return new self('critical');
        }
        // create the other constants here
    }
    

    Now your static funcion works

    public static function log($log, LogLevel $logLevel = null): void {
       // .....
    }
    

    $logLevel will receive LogLevel::emergency(), LogLevel::critical(), etc. and you can get the level name just calling $logLevel->getName()