1

DISCLAIMER: So, this is a probably duplicate but I've spent the better part of an hour trying to figure this out, and I'm frustrated with how this shouldn't be so difficult. This SO (PHP manipulating multidimensional array values) looks like it's similar to what I'm trying to do,but it's not quite clear what the resolution was.

I have a multidimenionsal array of values retrieved via an SQL query. I iterate over the main array to access the subarrays, which I then iterate over each subarray to access the key pair values. When a certain key in a subarray is encountered, I perform a bitwise operation on that value, and assign a value to a variable for later use. My issue lies in getting these new values assigned back to the key of the present subarray. Here's my code:

public function getPublicList()
{
    $this->sql = "SELECT id, name, difficulty, conditions, details FROM {$this->table} WHERE enabled='y'";
    $this->execSql("Get Legs List", SELECT_MULTI);

    $conditions = '';
    $val = '';

    // break down this data's array into pieces
    foreach($this->data as $key => $value)
    {
        // iterate through the subarrays and find conditions
        foreach($value as $key => $val)
        {
            // var_dump($key . " => " . print_r($val, true));
            if($key === 'conditions')
            {
                // run bitwise operations to determine what conditions are set
                if($val & 1)
                    $conditions .= "no-shade,";
                if($val & 2)
                    $conditions .= "quiet,";
                if($val & 4)
                    $conditions .= "elevation,";
                if($val & 8)
                    $conditions .= "gravel";

                $val = rtrim($conditions, ",");
                $conditions = '';
            }
            $value['conditions'] = $val;
        }
    }
}

In my various attempts, I have managed to get the values back into various parts of the subarrays, but not where I need them. I need $conditions to be assigned to $value['conditions'] for each array in $this->data. $value['conditions'] = $val; is my latest attempt at achieving what I need, but other values of the subarray wind up being assigned $val as well.

I'm pretty stumped with this one, and I think that's contributing to my lack of finding an answer in searches. If you can point me towards an answer, or towards docs that will explain how to achieve this, I will greatly appreciate it. TIA!

UPDATE:

Here's the result of var_dump(print_r($value));:

Array ( 
[id] => 4 
[name] => Leg 1 
[difficulty] => vh 
[conditions] => 4 
[details] => And you're off! Exchange 1 is where you begin the relay, starting at Timberline Lodge on Mt. Hood, and proceeding for 5.44 miles down some steep, windy terrain. Make sure you to have your required safety gear, and be mindful of other runners. This leg will test what you're made of! 
) 
bool(true) 
Array ( 
[id] => 4 
[name] => Leg 1 
[difficulty] => vh 
[conditions] => Leg 1 
[details] => And you're off! Exchange 1 is where you begin the relay, starting at Timberline Lodge on Mt. Hood, and proceeding for 5.44 miles down some steep, windy terrain. Make sure you to have your required safety gear, and be mindful of other runners. This leg will test what you're made of! 
) 
bool(true) 
Array ( 
[id] => 4 
[name] => Leg 1 
[difficulty] => vh 
[conditions] => vh 
[details] => And you're off! Exchange 1 is where you begin the relay, starting at Timberline Lodge on Mt. Hood, and proceeding for 5.44 miles down some steep, windy terrain. Make sure you to have your required safety gear, and be mindful of other runners. This leg will test what you're made of! 
) 
bool(true) 
Array ( 
[id] => 4 
[name] => Leg 1 
[difficulty] => vh 
[conditions] => no-shade,quiet,elevation,gravel 
[details] => And you're off! Exchange 1 is where you begin the relay, starting at Timberline Lodge on Mt. Hood, and proceeding for 5.44 miles down some steep, windy terrain. Make sure you to have your required safety gear, and be mindful of other runners. This leg will test what you're made of! 
) bool(true) 
Array ( 
[id] => 4 
[name] => Leg 1 
[difficulty] => vh 
[conditions] => And you're off! Exchange 1 is where you begin the relay, starting at Timberline Lodge on Mt. Hood, and proceeding for 5.44 miles down some steep, windy terrain. Make sure you to have your required safety gear, and be mindful of other runners. This leg will test what you're made of! 
[details] => And you're off! Exchange 1 is where you begin the relay, starting at Timberline Lodge on Mt. Hood, and proceeding for 5.44 miles down some steep, windy terrain. Make sure you to have your required safety gear, and be mindful of other runners. This leg will test what you're made of! ) bool(true) 
Array ( 
[id] => 5 
[name] => Leg 2 
[difficulty] => h 
[conditions] => 5 [details] =>
Placeholder Content
).... for thirty something more "legs"
2
  • 2
    What are the values for $val during various iterations? would it be better to run the bitwise comparison on $val instead of $value? Commented Jan 11, 2017 at 0:43
  • You are correct, I copied code over from a pastebin I had to share in IRC that had been modified accordingly yet. Updated the question with a partial dump of the values so you can see what exactly is occurring on each iteration. Commented Jan 11, 2017 at 0:58

2 Answers 2

1

Your looping looks a little more complicated than it needs to be. I thin kthis should work

public function getPublicList($data)
{
    $this->sql = "SELECT id, name, difficulty, conditions, details FROM {$this->table} WHERE enabled='y'";
    $this->execSql("Get Legs List", SELECT_MULTI);

    // just loop through the data, if it has a "conditions" key, adjust it
    foreach($this->data as $key => $value)
    {
        if (array_key_exists("conditions", $value) {
            $this->data[$key]["conditions"] = $this->do_condition_adjustment($value);
        }
    }

}    

// separate function to apply the flags to a single conditions value
private function do_condition_adjustment($value) {
    $conds = array();
    if ($value & 1) {
    $conds[] = "no-shade";
    }
    if ($value & 2) {
    $conds[] = "quiet";
    }
    if ($value & 4) {
    $conds[] = "elevation";
    }
    if ($value & 8) {
    $conds[] = "gravel";
    }

    return implode(",", $conds);
}

EDIT: removed unused vars, fixed incorrectly typed key

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

1 Comment

This got me closer, and I think on the right path. The values are being assigned appropriately now, but still no go for the multiple conditions. I can work with this though, so I'm accepting this as the answer! Thank you!
1

From the PHP documentation on foreach:

In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.1

So precede the values in the iterators with an ampersand:

foreach($this->data as $dataKey => &$value)    {
    // iterate through the subarrays and find conditions
    foreach($value as $key => &$val) {
        //update $val accordingly
        //e.g. $val .= 'quiet';

Otherwise, you will need to update referencing the array directly (i.e. $this->data):

foreach($this->data as $dataKey => $value)    {
    // iterate through the subarrays and find conditions
    foreach($value as $key => $val) {
        //update $val accordingly
        //e.g. $this->data[$dataKey][$key] .= 'quiet';

2 Comments

This provides the same results that my initial attempts did, unfortunately. It seems during each iteration, the conditions value get rewritten with each key's value. It's good to know that one can access the values by reference though! Always learning something new, so thank you!
Perhaps an issue may be that there is this line $value['conditions'] = $val; which is executed inside the double foreach blocks outside the block containing the bitwise comparisons _even if $key === 'conditions evaluations to false.... I made this playground example to illustrate my example but see various types of values in the conditions indexes - e.g. 'vh', 5, 'Leg 1'...should those values just be integers?

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.