0

I need to get the value of an array nested in others array from an object. Something like this:

$callback = $this->__get("tasks[$taskIndex]['subtasks'][$key]['callback']");

It don't work, as PHP thinks that the property name includes the square brackets and PHP don't interpret it as an array.

BACKGROUND

It is from the TaskRunner class that I created to help me deal with callbacks.

class TaskRunner(
 #code ..
 public function __get($property) {
   if(isset($this->{$property})) {
     return $this->{$property};
   }
   return null;
 }

 public function runSubtask($taskIndex, $whenToRunSubtask) {
    $subtasks = $this->__get("tasks[$taskIndex]['subtasks']");
    foreach($subtasks as $key => $subtask) {
       if($subtask['when'] === $whenToRunSubtask) {
         $callback = $this->__get("tasks[$taskIndex]['subtasks'][$key]['callback']");
         $args = $this->__get("tasks[$taskIndex]['subtasks'][$key]['args']");
         $this->runCallback($callback, $args);
      }
    }
 }

)

I did my work and searched for this. I found the following similar questions on StackOverflow:

Multidimensional arrays in class with __set and __get

PHP set magic method with array as names

Magic method get and set values dynamically from array

This is just to name a few because I spent over 1 hour searching for a solution. So, please don't mark it as duplicated because the other questions that are similar to mine don't solve my problem.

One solution I found by myself was to use isset

$callback = isset($this->tasks[$taskIndex]['subtasks'][$key]['callback']) ? $this->tasks[$taskIndex]['subtasks'][$key]['callback'] : null;

$args = isset($this->tasks[$taskIndex]['subtasks'][$key]['args']) ? $this->tasks[$taskIndex]['subtasks'][$key]['args'] : null;

Although the code above works, it is pretty ugly! I'm looking for a shorter and cleaner solution. It matters because I'm using the solution above in a lot of places, so my code is difficult to read and to maintain.

I'd like to know if there is a simple, preferably built-in, way to accomplish this.

An important point is that some of the properties I'm trying to access, the args for example, may not exist. If they don't exist, it should return null. For example, if $this->tasks[$taskIndex]['subtasks']['key]['args'] don't exist then the var $args should be null. The same for other variables. I need them to be null and not false because the method runCallback of my taskRunner class checks if the args is null before run the callback; if args is nulll it just run the callback; if not, it runs the callback and pass the args as the argument of the callback.

Note: PHP version is 7.3

  • Had you considered adding a new method with clear arguments to get what you need? In other words why do you _need_ magic for this? – Rarst Jul 25 '19 at 15:40
  • Yes, I can use a new method. Do you have any suggestions to implement the method? If so, feel free to share; I'll be glad to hear from you:) . One point I need to make is that it is possible that the properties I trying to access don't exist. If they don't exist, I should get null from these properties or on the contrary, it will mess other methods of the taskRunner Class. – Student of Science Jul 25 '19 at 15:44

1 Answers1

1

So I feel there are two issues here:

  1. your API is kind of bulky because you are trying to wrangle this into magic
  2. your sanity checks are bulky because your arrays are complex

I would refine both into a dedicated method along these lines, using clear arguments and null coalescing operator for the check:

    public function callback( $index, $key ) {
        return $this->tasks[ $index ]['subtasks'][ $key ]['callback'] ?? null;
    }
Rarst
  • 2,335
  • 16
  • 26