Luke James Emery
Luke James Emery

Reputation: 469

Searching in multidimensional php objects

    public function filter($index, $value) {
        if($this->tasks) {
            foreach ($this->tasks as $id => $t) {
                if($t->$index != $value) {
                    unset($this->tasks[$id]);
                }
            }
        } else {
            echo "Tasks are empty";
        }
    }

So I am having a problem with the function above searching multidimensional objects. What I mean by that is like these:

$task->form->id
$task->form->type
$task->author->id
$task->fields->[FIELDNAME]->value
$task->form->template->id
$task->id

etc. These are the kinds of fields that need to be accessed. I thought that I could just, in $index, put "form->id" but that didn't work. For my application, I literally can spell it out. I just don't want to have to write a function for each to the last, because some of them (as you can see) only need to be on the first level and some need to be all the way down four objects.

Just tell me what more data you need and I will give it. I know every keystroke intimately so it sometimes means I forget to share something.

If you help, thank you so much.

WHAT I DID


Okay so I got it to work but I did something different.

Within the Form class

public function search($value, $type = NULL) {
    if(is_object($this->fields)) {
        foreach($this->fields as $page) {
            foreach($page as $name=>$field) {
                if($name != "pdata") {
                    if ($type != NULL && $field->type == $type && $field->value == $value || $type == NULL && isset($field->value) && $field->value == $value) {
                        return true;
                    }
                } 
            }
            return false;
        }
    } else {
        //Probably corrupted
        return false;
    }
    return false;
}

Outside of it I can just call this function and delete or add based on whether it returns true or false.

Upvotes: 0

Views: 1398

Answers (2)

Jiri Kriz
Jiri Kriz

Reputation: 9292

You can use get_object_vars() to process all public variables of an object and proceed recursively to reach all variables named id. Here is a simple template:

class Task {
    public $author, $form, $id;
}
class Author {
    public $id;
}
class Form {
    public $id, $type, $template;
}
class Template {
    public $id;
}

$tasks = Array();

$task = new Task();
$tasks[] = $task;
$task->id = "id1";
$task->author = new Author();
$task->author->id = "id1";
$task->form = new Form();
$task->form->template = new Template();
$task->form->template->id = "id1";

function filter($parent, $object, $id_value) {
    $vars = get_object_vars($object);
    foreach ($vars as $var => $value) {
        if ($var == "id") {
            if ($value == $id_value) {
                echo "$parent -> $var == $value <br />";
            }
        }
        else if (is_object($value) && isset($value)) {
            filter("$parent -> $var", $value, $id_value);
        }
    }
}

foreach ($tasks as $index => $task) {
    filter("Task[$index]", $task, "id1");
}

The output is:

Task[0] -> author -> id == id1 
Task[0] -> form -> template -> id == id1 
Task[0] -> id == id1 

Upvotes: 1

Shattuck
Shattuck

Reputation: 2780

function array_searchRecursive( $needle, $haystack, $strict=false, $path=array() )
{
    if( !is_array($haystack) ) {
        return false;
    }

    foreach( $haystack as $key => $val ) {
        if( is_array($val) && $subPath = array_searchRecursive($needle, $val, $strict, $path) ) {
            $path = array_merge($path, array($key), $subPath);
            return $path;
        } elseif( (!$strict && $val == $needle) || ($strict && $val === $needle) ) {
            $path[] = $key;
            return $path;
        }
    }
    return false;
}

OR

I know you don't want to write it all out, but I have to say I love the way this is done in the Symfony framework. In symfony you have an Entity class that defines functions to retrieve each piece of information (variable) from a given object.

One way you could mimic this is to create a base class for tasks that has functions to retrieve each variable you need...such as getTaskId.

Then you could extend this base class with the one you are working with now. This would give you access to the functions you created to parse your object. Retrieving $task->form->template->id could be as simple as calling the getTemplateId function.

I know this would probably take longer than what you were looking for, but I hope it helps.

Upvotes: 2

Related Questions