Home > Software design >  get name of extended class in abstract base class
get name of extended class in abstract base class

Time:09-14

I have an abstract base class implements the laravel queueable trait:

abstract class BaseJob {
   use Queueable;
}

Queueable defines $queue:

trait Queueable
{
    public $queue;
}

In the actual job it is now possible to defined the classname as the queue name:

class SpecificJob extends BaseJob {
   public $queue = self::class;

    public function __construct($someParameter) {
        // they all have custom constructors so they would overwrite the BaseJob constructor and I would also like to avoid calling parent::__construct;
    }
}

Is there some way to do this in the baseclass so it is not required to do it in every class that extends from it?

I thought of something like this:

abstract class BaseJob {
   use Queueable;
   public $queue = static::class;
}

However this is not possible: 'static::' is not allowed in compile-time constants

CodePudding user response:

You can use the constructor to assign the computed value to $queue


class Base {
   public $queue = '';
   public function __construct() {
       $this->queue = static::class;
   }
}
class Derived extends Base {
}

$d = new Derived;
var_dump($d->queue);

Output:

string(7) "Derived"

CodePudding user response:

You can use late static bindings in the Queueable trait to get the implementing class name if you use a getter rather than a public property.

trait Queueable
{
    public function getQueue()
    {
        return static::class;
    }
}

abstract class BaseJob {
    use Queueable;
}

class SpecificJob extends BaseJob {
    
    public function __construct($someParameter) {
        // they all have custom constructors so they would overwrite the BaseJob constructor and I would also like to avoid calling parent::__construct;
    }
}

$mySpecificJob = new SpecificJob('wombats');

assert($mySpecificJob->getQueue() == 'SpecificJob', 'We expect the trait to return the class name of the SpecificJob instance');

echo $mySpecificJob->getQueue().PHP_EOL;

The convention of relying on the implementing class name for the queue name give me hives, personally, I would want to be explicit when naming the queues. From your example, I don't see a reason to use a trait, you can do everything you need to do in the base class if you require sub classes to implement a method that returns the queue name. You could even use the class name by returning the value of static::class if you want.

abstract class BaseJob
{
    public abstract function getQueue(): string;
}

class SpecificJob extends BaseJob
{
    public function __construct($someParameter)
    {
        // they all have custom constructors so they would overwrite the BaseJob constructor and I would also like to avoid calling parent::__construct;
    }
    
    public function getQueue(): string
    {
        return self::class;
    }
}

class CustomNameJob extends BaseJob
{
    private const _queueName = 'custom_queue';
    
    public function __construct($someParameter)
    {
        // they all have custom constructors so they would overwrite the BaseJob constructor and I would also like to avoid calling parent::__construct;
    }
    
    public function getQueue(): string
    {
        return self::_queueName;
    }
}

$mySpecificJob = new SpecificJob('wombats');

assert($mySpecificJob->getQueue() == 'SpecificJob', 'We expect the the class name of the SpecificJob instance');

echo $mySpecificJob->getQueue().PHP_EOL;

$myCustomNameJob = new CustomNameJob('wombats');

assert($myCustomNameJob->getQueue() == 'custom_queue', 'We expect the  queue name specified in the CustomNameJob class');

echo $myCustomNameJob->getQueue().PHP_EOL;
  • Related