0

I've written a PHP class in my project's framework that contains a constructor, and for the purposes of this class it contains a single argument called name.

My class is loaded dynamically as part of the feature I'm building and I need to load a value into my argument from an array, but when I do this it just comes through as Array even when I use array_values, e.g, here's my class:

<?php

class GreetingJob
{

    /**
     * The name
     */
    public $name;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * Write data to a file
     */
    public function writeToFile($data = '')
    {
        $file = fopen('000.txt', 'w');
        fwrite($file, $data);
        fclose($file);
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        try {
            $this->writeToFile('Hello ' . $this->name);
        } catch (Exception $e) {
            // do something
        }
    }
}

And where it's loaded:

/**
* Get the job
*/
public function getJob($job = '') {
    return APP . "modules/QueueManagerModule/Jobs/$job.php";
}

/**
* Check that the job exists
*/
public function jobExists($job = '') {
    if (!file_exists($this->getJob($job))) {
        return false;
    }

    return true;
}

/**
* Execute the loaded job
*/
public function executeJob($class, $rawJob = [], $args = []) {
    require_once $this->getJob($class);

    $waitTimeStart = strtotime($rawJob['QueueManagerJob']['available_at']) / 1000;
    $runtimeStart = microtime(true);

    // initiate the job class and invoke the handle
    // method which runs the job
    $job = new $class(array_values(unserialize($args)));
    $job->handle();
}

$args would look like this:

[
  'name' => 'john'
]

How can I dynamically pass args through to my class in the order that they appear and use the values from each.

5
  • 1
    if args was like you said in the end, you could get the value you are looking for doing: $args['name'] and pass it to the class constructor when instantiating it. But that's pretty easy to guess so there's probably something I'm missing Commented Apr 6, 2022 at 8:14
  • It's not surprising that array_values returns an array. What else did you expect? Also, what do you mean by "it just comes through as Array"? Commented Apr 6, 2022 at 8:16
  • The output into my file is: Hello Array @NicoHaase Commented Apr 6, 2022 at 8:19
  • @DiegoDeVita, thanks for your reply, yeah, I can't hardcode $args['name'], as the data supplied to my dynamic class in $args may not always be name, and the class isn't always the same class, some will have more args some won't have any at all. Commented Apr 6, 2022 at 8:20
  • You need to have some set structure. Of both the data you get and the class can differ, then how would you ever know what to extract from the data, how to extract it and then how to pass it in to the constructor? Commented Apr 6, 2022 at 8:42

2 Answers 2

1

array_values() still returns an array. All it does it resetting keys to be consecutive zero-based integers.

I think you want to use the splat operator:

$job = new $class(...array_values(unserialize($args)));

Full runnable example:

<?php

class GreetingJob
{
    public function __construct($name)
    {
        var_dump($name);
    }
}

$class = 'GreetingJob';
$args = serialize(
    [
        'name' => 'Jimmy',
    ]
);
$job = new $class(...array_values(unserialize($args)));

Beware that the overall design can be confusing. Accepting arguments in an associative array suggests names matter and position doesn't, but it's the other way round.

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

Comments

0

this is the way to instantiate a class dynamically using Reflection in php:

$className = 'GreetingJob';
$args = [];
$ref = new \ReflectionClass($className);
$obj = $ref->newInstanceArgs($args);

https://www.php.net/manual/en/reflectionclass.newinstanceargs.php

Comments

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.