40

In the following example, if the class does not exist, I want to catch the error and create a Null class instead.

But in spite of my try/catch statements, PHP simply tells me Class 'SmartFormasdfasdf' not found.

How can I get PHP to catch the 'class not found' error?

<?php
class SmartFormLogin extends SmartForm {
    public function render() {
        echo '<p>this is the login form</p>';
    }
}

class SmartFormCodeWrapper extends SmartForm {
    public function render() {
        echo '<p>this is the code wrapper form</p>';
    }
}

class SmartFormNull extends SmartForm {
    public function render() {
        echo '<p>the form "' . htmlentities($this->idCode) . '" does not exist</p>';
    }
}

class SmartForm {

    protected $idCode;

    public function __construct($idCode) {
        $this->idCode = $idCode;
    }

    public static function create($smartFormIdCode) {
        $className = 'SmartForm' . $smartFormIdCode;
        try {
            return new $className($smartFormIdCode);
        } catch (Exception $ex) {
            return new SmartFormNull($smartformIdCode);
        }
    }
}

$formLogin = SmartForm::create('Login');
$formLogin->render();
$formLogin = SmartForm::create('CodeWrapper');
$formLogin->render();
$formLogin = SmartForm::create('asdfasdf');
$formLogin->render();
?>

Solution:

Thanks @Mchl, this is how I solved it then:

public static function create($smartFormIdCode) {
  $className = 'SmartForm' . $smartFormIdCode;
  if(class_exists($className)) {
    return new $className($smartFormIdCode);
  } else {
    return new SmartFormNull($smartFormIdCode);
  }
} 
Edward Tanguay
  • 189,012
  • 314
  • 712
  • 1,047

5 Answers5

50

Because it's a fatal error. Use class_exists() function to check if class exist.

Also: PHP is not Java - unless you redefined default error handler, it will raise errors and not throw exceptions.

Mchl
  • 61,444
  • 9
  • 118
  • 120
  • 3
    I forgot, PHP try/get feature merely helps you build your own exception handling by enabling you to throw your own errors, but doesn't consequently catch errors itself as in C#/Java. – Edward Tanguay Dec 12 '10 at 11:12
  • 1
    See http://www.php.net/manual/en/class.errorexception.php for example on how to 'rewrite' all (except fatal) errors to exceptions. Also, as other suggested, since 5.3 you might want to use autoloader to throw an exception when a file containing given class is not found. – Mchl Dec 12 '10 at 11:15
  • 2
    @Edward - it certainly lets you catch *exceptions*, but almost everything native to PHP doesn't throw Exceptions, just errors. You can work around this easily by defining your own *error_handler* and having that throw Exceptions using ErrorException (see http://au.php.net/errorexception and the example there). This easily switches PHP's native error system to a useful Exception based system that works quite nicely with throw/try/catch etc. – El Yobo Dec 12 '10 at 11:16
33

Old question, but in PHP7 this is a catchable exception. Though I still think the class_exists($class) is a more explicit way to do it. However, you could do a try/catch block using the new \Throwable exception type:

$className = 'SmartForm' . $smartFormIdCode;
try {
    return new $className($smartFormIdCode);
} catch (\Throwable $ex) {
    return new SmartFormNull($smartformIdCode);
}
ChadSikorra
  • 2,829
  • 2
  • 21
  • 27
  • 1
    Alternatively, if you want to get more specific with what you are catching, you can catch the \Error type instead (tested to work in PHP 7.1). This would make your code more brittle to changes how the PHP language evolves, but also less likely to catch something you did not intend it to catch. If you have good automated tests, you should be able to get away with the more specific version because your tests would fail if PHP suddenly started throwing a different type for this. – still_dreaming_1 Aug 17 '17 at 02:45
  • Thanks. Perfect answer. – Hasnat Babur Jul 01 '20 at 19:39
8

php >= 7.0

php can catch 'class not found' as Throwable

try {
        return new $className($smartFormIdCode);
} catch (\Throwable $ex) {
        return new SmartFormNull($smartformIdCode);
}
Horace
  • 141
  • 1
  • 3
5

You need to use class_exists to see if the class exists before you try and instantiate it.

Incidentally, if you're using a class autoloader, be sure to set the second arg to true.

John Parker
  • 54,048
  • 11
  • 129
  • 129
0

Because php emits fatal error when you ty to create new object of non existing class. To make it work you will need php >= 5.3 and autoload function, where you should try to look for file with class definition or throw your custom exception.

dev-null-dweller
  • 29,274
  • 3
  • 65
  • 85
  • a) autoload is the wrong way to do it - see http://au.php.net/manual/en/function.spl-autoload-register.php and b) it doesn't require PHP 5.3 – El Yobo Dec 12 '10 at 11:17
  • 1
    Throwing exceptions in autoloader does indeed require 5.3. ANd there's nothing 'wrong' about it as long as you know what you're doing (i.e. it's a bit silly to throw an exception when there are more autoloaders in autoload queue). – Mchl Dec 12 '10 at 11:24
  • @El Yobo - can you elaborate what is wrong with autoload? spl function does the same, only difference is that it allows you to provide more functions to run in search for correct file. Ans as for b), as Mchl said, you will still need php 5.3 to make it throw an exception. – dev-null-dweller Dec 12 '10 at 13:07