Home > Software engineering >  Instantiate Class from method return and pass data to constructor PHP
Instantiate Class from method return and pass data to constructor PHP

Time:12-04

I have notification classes called ProductNotification, OrderNotification, etc, these have a mail method which returns another class which holds further data for the sending of emails:

class ProductNotification {
    public function mail()
    {
        return ProductMail::class;
    }
}
class OrderNotification {
    public function mail()
    {
        return OrderMail::class;
    }
}

Is there a way to instantiate the ProductMail class from the method, the following doesn't work and I'm not sure how to pass through another variable $data to the constructo.?

class BaseNotification {
    public function toMail()
    {
        return (new $this->mail())->to($email)->send();
    {
}

I know that if mail() was a property on the class instead, that this would be possible and I can pass through $data to the constructor as the following works, but is this possible from a method?

class ProductNotification {
    public $mail = ProductMail::class;
}
class BaseNotification {
    public function toMail()
    {
        return (new $this->mail($data))->to($email)->send();
    {
}

CodePudding user response:

You can store the class as a local variable in the toMail method and then instantiate it.

class BaseNotification {
    public function toMail($data)
    {
        $mail_class = $this->mail();

        return new $mail_class($data);
    }
}

CodePudding user response:

You can't instantiate an object from a method call, but you can do so from a variable. So just assign the method's return call to a variable:

class ProductNotification extends BaseNotification {
    public function mail() {
        return ProductMail::class;
    }
}

class OrderNotification extends BaseNotification {
    public function mail() {
        return OrderMail::class;
    }
}

class BaseNotification {
    public function toMail()
    {
        $data = [];
        $class = $this->mail();
        return (new $class($data))->to($email)->send();
    {
}

Though it might be cleaner to just use the mail() method to build the mail:

class ProductNotification extends BaseNotification {
    public function mail($data) {
        return new ProductMail($data);
    }
}

class OrderNotification extends BaseNotification {
    public function mail($data) {
        return new OrderMail($data);
    }
}

class BaseNotification {
    public function mail() {
        throw new \Exception("not implemented");
    }

    public function toMail()
    {
        $data = [];
        return $this->mail($data)->to($email)->send();
    {
}
  • Related