56

It is possible to replace block of if( .. instanceof ...), elseif(... instanceof ...), ... with switch?

For example:

<?php
$class = ..... //some class

if($class instanceof SomeClass) {
    //do something
} elseif($class instanceof SomeAnotherClass) {
    //do something else
}
leninzprahy
  • 4,583
  • 3
  • 17
  • 13

3 Answers3

96

For a polymorphic switch with instanceof which considers inheritance:

switch(true) {  
    case $objectToTest instanceof TreeRequest:
        echo "tree request";
        break;
    case $objectToTest instanceof GroundRequest:
        echo "ground request";
        break;
}

For a switch where the class name should match exactly:

$class = get_class($objectToTest);

switch($class) {  
    case 'TreeRequest':
        echo "tree request";
        break;
    case 'GroundRequest':
        echo "ground request";
        break;
}
Blackbam
  • 17,496
  • 26
  • 97
  • 150
Ivan
  • 2,463
  • 1
  • 20
  • 28
  • 9
    that switch(true), :+1: – koponk Dec 06 '16 at 01:58
  • 25
    A warning to anyone looking at using the first example: it's not the same as `instanceof` as it ignores class inheritance and implementations. – SEoF Dec 29 '16 at 12:52
  • 6
    Sure, it's possible. But **why oh why** would you want to do that in the first place? There's nothing wrong with `if( .. instanceof ...), elseif(... instanceof ...)`. Not only the first example is incorrect, but the second one takes also much more space, degrades readability and efficiency (as it prevents compiling the "cases" statements as they are dynamic. Don't do such thing. – Patrick Allaert Dec 05 '17 at 11:47
  • Beware, the danger of using `get_class($object)` is that some frameworks (like Symfony) return the **Proxy** classname (like when lazy loading,...), so not the real classnames you want to compare with! – Julesezaar Jul 02 '23 at 11:36
46

The following is more correct:

$class = get_class($objectToTest);

switch($class) {  
    case TreeRequest::class:
        echo "tree request";
        break;
    case GroundRequest::class:
        echo "ground request";
        break;
}

This way namespaces are properly compared (you don't have to type them out) and if anything changes such as the namespace or class name you'll get a decent IDE error informing you that your code is broken.

whitebrow
  • 2,015
  • 21
  • 24
8

And using the match expression this would look like this:

return match(get_class($object)) {  
   TreeRequest::class => "tree request",
   GroundRequest::class => "ground request",
   default => "default request"
}

Remember it misses inheritance and takes only the current class. Match expression considering inheritance:

return match(true) {  
   $object instanceof TreeRequest=> "tree request",
   $object instanceof GroundRequest => "ground request",
   default => "default request"
}
Jsowa
  • 9,104
  • 5
  • 56
  • 60