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;