0

I'm reading the php enum documents and from what I understand, this new feature in its most basic form is for us to set constants to be used in classes for type checking.

Is there any way to work with classes? Example:

enum ClassEnum {
   case \App\Model\Test;
   case \App\Model\AnotherTest;
}
4
  • If you tell us why you want to do this we should be able to show you an actual solution that doesn't involve enums. Commented Feb 28, 2022 at 21:00
  • I have a method where the parameter can be one of three options, so instead of using ClassName|ClassName|ClassName, I want, if possible, to use enum. This is a Laravel project and I found a package that performs the same or similar action, but I want to know if it would be possible to do it with enum. Commented Feb 28, 2022 at 21:17
  • In that case you should likely not be using a class name for a type hint, but an interface. That way your code doesn't need to care about particular concrete implementations of a class, but rather the methods available to interact with it. This also avoids the whole "God Class" problem of trying to make everything an extension of a single approved/accepted "base" class. Commented Feb 28, 2022 at 21:22
  • In my case, the parameter will receive models from a package, so I think it's not possible to use interfaces. Is it okay to leave the parameter without type checking? Commented Feb 28, 2022 at 21:50

1 Answer 1

1

No, you can't use Enums like that. But there are a couple alternatives.

First and foremost would be to use an interface, which sets the contract for what methods an implementation must expose, and what methods other code can expect to use to interact with it.

interface FooInterface {
    public function doThing();
}

class Foo implements FooInterface {
    public function doThing() {
        printf("%s: thing!\n", __CLASS__);
    }
}

class Bar implements FooInterface {
    public function doThing() {
        printf("%s: thing!\n", __CLASS__);
    }
}

class InterfaceTest {
    public function __construct(FooInterface $obj) {
        $obj->doThing();
    }
}

$t1 = new InterfaceTest(new Foo());
$t2 = new InterfaceTest(new Bar());

In the rare case that you want to use multiple, non-extending types you can also use Composite Types which were introduced in PHP 8:

class CompositeTest {
    public function __construct(Foo|Bar $obj) {
        $obj->doThing();
    }
}

$c1 = new CompositeTest(new Foo());
$c2 = new CompositeTest(new Bar());

Both of the above snippets will output:

Foo: thing!
Bar: thing!

But I far and away recommend using Interfaces as it makes your code more flexible and easier to write and maintain.

Sign up to request clarification or add additional context in comments.

2 Comments

Now it became clearer. But as I said, the classes I want to check are models of a package. In this case, would it be possible to "link" the interface with the class without changing the original file?
You could write a wrapper class that implements an interface, eg: class FooWrapper implements FooInterface { private $i; public function __construct(Foo $f) { $this->i = $f; } ... } but before that take a spin through the source of this other library, if it was decently written it probably has something you can hint on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.