php remove object from array of objects - php

I'm trying to remove an object from an array of objects by its' index. Here's what I've got so far, but i'm stumped.
$index = 2;
$objectarray = array(
0=>array('label'=>'foo', 'value'=>'n23'),
1=>array('label'=>'bar', 'value'=>'2n13'),
2=>array('label'=>'foobar', 'value'=>'n2314'),
3=>array('label'=>'barfoo', 'value'=>'03n23')
);
//I've tried the following but it removes the entire array.
foreach ($objectarray as $key => $object) {
if ($key == $index) {
array_splice($object, $key, 1);
//unset($object[$key]); also removes entire array.
}
}
Any help would be appreciated.
Updated Solution
array_splice($objectarray, $index, 1); //array_splice accepts 3 parameters
//(array, start, length) removes the given array and then normalizes the index
//OR
unset($objectarray[$index]); //removes the array at given index
$reindex = array_values($objectarray); //normalize index
$objectarray = $reindex; //update variable

array_splice($objectarray, $index, 1);
//array_splice accepts 3 parameters (array, start, length) and removes the given
//array and then normalizes the index
//OR
unset($objectarray[$index]); //removes the array at given index
$reindex = array_values($objectarray); //normalize index
$objectarray = $reindex; //update variable

You have to use the function unset on your array.
So its like that:
<?php
$index = 2;
$objectarray = array(
0 => array('label' => 'foo', 'value' => 'n23'),
1 => array('label' => 'bar', 'value' => '2n13'),
2 => array('label' => 'foobar', 'value' => 'n2314'),
3 => array('label' => 'barfoo', 'value' => '03n23')
);
var_dump($objectarray);
foreach ($objectarray as $key => $object) {
if ($key == $index) {
unset($objectarray[$index]);
}
}
var_dump($objectarray);
?>
Remember, your array will have odd indexes after that and you must (if you want) reindex it.
$foo2 = array_values($objectarray);

in that case you won't need that foreach just unset directly
unset($objectarray[$index]);

Related

Passing an array copy to a function expecting a reference

I have a loop of the following kind:
foreach ($values as $key => $value) {
$attrs = array('NAME' => $key);
myproc ($attrs);
......
}
Where in myproc the first parameter is defined by reference:
function myproc (& attrs) { .... }
myproc adds the passed value to some structure.
The trouble with this is that at loop end, all the arrays added to the generated structure contains the same value, the last value extracted from the loop.
I tried also something like this :
foreach ($values as $key => $value) {
$attrs = array('NAME' => $key);
$copy = $attrs;
myproc ($copy);
......
}
but the result is the same. I'not allowed to modify the procedure. Any suggestions?
Based on the comment below your question, it seems that the problem is that you are passing a reference and this reference gets updated in the loop, leading to updates in the object you are generating in your function.
To avoid this, you need to unset the variable after the function call so that the link between the value in your object and the referenced variable is broken:
foreach ($values as $key => $value) {
$attrs = array('NAME' => $key);
myproc ($attrs);
// unset the variable so that newer values of it will have no effect
// on the object generated in `myproc`
unset($attrs);
......
}
Also see the manual.
<?php
foreach(['red','pink','green'] as $colour) {
$attrs = ['colour' => $colour];
if(colourToAction($attrs)) {
$results[] = $attrs;
}
}
var_export($results);
function colourToAction(&$attrs) {
$actions = ['red'=>'stop','amber'=>'wait', 'green' => 'go'];
if(isset($attrs['colour']) && isset($actions[$attrs['colour']])){
$attrs['action'] = $actions[$attrs['colour']];
return true;
}
}
Output:
array (
0 =>
array (
'colour' => 'red',
'action' => 'stop',
),
1 =>
array (
'colour' => 'green',
'action' => 'go',
),
)

Loop over one array as if it was a multidimensional array

I have an array like:
$array = array(
'name' => 'Humphrey',
'email' => 'humphrey#wilkins.com
);
This is retrieved through a function that gets from the database. If there is more than one result retrieved, it looks like:
$array = array(
[0] => array(
'name' => 'Humphrey1',
'email' => 'humphrey1#wilkins.com'
),
[1] => array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
)
);
If the second is returned, I can do a simple foreach($array as $key => $person), but if there is only one result returned (the first example), I can't run a foreach on this as I need to access like: $person['name'] within the foreach loop.
Is there any way to make the one result believe its a multidimensional array?
Try this :
if(!is_array($array[0])) {
$new_array[] = $array;
$array = $new_array;
}
I would highly recommended making your data's structure the same regardless of how many elements are returned. It will help log terms and this will have to be done anywhere that function is called which seems like a waste.
You can check if a key exists and do some logic based on that condition.
if(array_key_exists("name", $array){
//There is one result
$array['name']; //...
} else {
//More then one
foreach($array as $k => $v){
//Do logic
}
}
You will have the keys in the first instance in the second yours keys would be the index.
Based on this, try:
function isAssoc(array $arr)
{
if (array() === $arr) return false;
return array_keys($arr) !== range(0, count($arr) - 1);
}
if(isAssoc($array)){
$array[] = $array;
}
First check if the array key 'name' exists in the given array.
If it does, then it isn't a multi-dimensional array.
Here's how you can make it multi-dimensional:
if(array_key_exists("name",$array))
{
$array = array($array);
}
Now you can loop through the array assuming it's a multidimensional array.
foreach($array as $key => $person)
{
$name = $person['name'];
echo $name;
}
The reason of this is probably because you use either fetch() or fetchAll() on your db. Anyway there are solutions that uses some tricks like:
$arr = !is_array($arr[0]) ? $arr : $arr[0];
or
is_array($arr[0]) && ($arr = $arr[0]);
but there is other option with array_walk_recursive()
$array = array(
array(
'name' => 'Humphrey1',
'email' => 'humphrey1#wilkins.com'
),
array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
)
);
$array2 = array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
);
$print = function ($item, $key) {
echo $key . $item .'<br>';
};
array_walk_recursive($array, $print);
array_walk_recursive($array2, $print);

Search PHP array of arrays using an array value and then update other array values in the matching array

I have a string stored in WordPress MySQL database Meta field as serialized string of array of arrays like this:
a:4:{i:0;a:8:{s:19:"ab-variation-letter";s:1:"B";s:18:"ab-variation-title";s:6:"bbbbbb";s:28:"ab-variation-wysiwyg-editor-";s:12:"bbbbbbbbbbbb";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:1;a:8:{s:19:"ab-variation-letter";s:1:"C";s:18:"ab-variation-title";s:5:"ccccc";s:28:"ab-variation-wysiwyg-editor-";s:17:"ccccccccccccccccc";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:2;a:8:{s:19:"ab-variation-letter";s:1:"D";s:18:"ab-variation-title";s:8:"dddddddd";s:28:"ab-variation-wysiwyg-editor-";s:1:"d";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:3;a:8:{s:19:"ab-variation-letter";s:1:"E";s:18:"ab-variation-title";s:8:"eeeeeeee";s:28:"ab-variation-wysiwyg-editor-";s:30:"eeeeeee eeeeeeeeeeeee eeeeeeee";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}}
When I unserialize that string above it looks like this below...
array (
0 =>
array (
'ab-variation-letter' => 'B',
'ab-variation-title' => 'bbbbbb',
'ab-variation-wysiwyg-editor-' => 'bbbbbbbbbbbb',
'ab-variation-conversion-count' => '',
'ab-variation-views' => '',
'ab-variation-start-date' => '',
'ab-variation-end-date' => '',
'ab-variation-winner' => '',
),
1 =>
array (
'ab-variation-letter' => 'C',
'ab-variation-title' => 'ccccc',
'ab-variation-wysiwyg-editor-' => 'ccccccccccccccccc',
'ab-variation-conversion-count' => '',
'ab-variation-views' => '',
'ab-variation-start-date' => '',
'ab-variation-end-date' => '',
'ab-variation-winner' => '',
),
2 =>
array (
'ab-variation-letter' => 'D',
'ab-variation-title' => 'dddddddd',
'ab-variation-wysiwyg-editor-' => 'd',
'ab-variation-conversion-count' => '',
'ab-variation-views' => '',
'ab-variation-start-date' => '',
'ab-variation-end-date' => '',
'ab-variation-winner' => '',
),
3 =>
array (
'ab-variation-letter' => 'E',
'ab-variation-title' => 'eeeeeeee',
'ab-variation-wysiwyg-editor-' => 'eeeeeee eeeeeeeeeeeee eeeeeeee',
'ab-variation-conversion-count' => '',
'ab-variation-views' => '',
'ab-variation-start-date' => '',
'ab-variation-end-date' => '',
'ab-variation-winner' => '',
),
)
based on this array of arrays above. I want to be able to search for the array that has ab-variation-letter' => 'C' and then be able to update any of the other array key values on that matching array. When done I will need to re-serialize back into a string so I can save it back to the Database table again.
I want to build this PHP function below to be able to take my serialized string of array of arrays and search those arrays for an array that has a key/value matching the passed in $array_key string and then update another keyvalue in that same array and then reserialize the whole thing again.
function updateAbTestMetaData($post_id, $meta_key, $meta_value, $array_key, $new_value){
//get serialized meta from DB
$serialized_meta_data_string = 'a:4:{i:0;a:8:{s:19:"ab-variation-letter";s:1:"B";s:18:"ab-variation-title";s:6:"bbbbbb";s:28:"ab-variation-wysiwyg-editor-";s:12:"bbbbbbbbbbbb";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:1;a:8:{s:19:"ab-variation-letter";s:1:"C";s:18:"ab-variation-title";s:5:"ccccc";s:28:"ab-variation-wysiwyg-editor-";s:17:"ccccccccccccccccc";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:2;a:8:{s:19:"ab-variation-letter";s:1:"D";s:18:"ab-variation-title";s:8:"dddddddd";s:28:"ab-variation-wysiwyg-editor-";s:1:"d";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:3;a:8:{s:19:"ab-variation-letter";s:1:"E";s:18:"ab-variation-title";s:8:"eeeeeeee";s:28:"ab-variation-wysiwyg-editor-";s:30:"eeeeeee eeeeeeeeeeeee eeeeeeee";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}}';
//un-serialize meta data string
$meta_data_arrays = unserialize($serialized_meta_data_string);
// search array of arrays $meta_data_arrays for array that has a key == $array_key // 'ab-variation-letter' === 'D'
// update the value of any other key on that matching array
// re-serialize all the data with the updated data
}
The end result should allow me to find the array with key 'ab-variation-letter' === 'C' and update the key/value in that matching array with key 'ab-variation-title' and update its current value from 'ccccc' to 'new value' and then re-serialize the whole entire array of arrays back into the original string with only the updated array data updated/
Perhaps throwing together a recursive function that can make use of calling itself could come in handy:
function replaceArrayKeyValue(array &$arr, $whereKey, $whereValue, $replacement) {
$matched = false;
$keys = array_keys($arr);
for ($i = 0; $i < count($keys); $i++)
{
$key = $keys[$i];
if (is_string($arr[$key])) {
if ($key === $whereKey && $arr[$key] === $whereValue) {
if (is_array($replacement)) {
$arr = array_replace_recursive($arr, $replacement);
} else {
$arr[$key] = $replacement;
}
$matched = $key;
break;
}
} else if (is_array($arr[$key])) {
$m = replaceArrayKeyValue($arr[$key], $whereKey, $whereValue, $replacement);
if ($m !== false) {
$matched = $key.'.'.$m;
break;
}
}
unset($key);
}
unset($keys);
return $matched;
}
With the above function, you pass through the source array ($arr), the key you're looking for ($whereKey), the value that it should match ($whereValue) and the replacement value ($replacement).
If $replacement is an array, I've got a array_replace_recursive in place to perform a recursive replacement, allowing you to pass in the changes you'd like to make to the array. For example, in your case:
$data = unserialize(...);
$matchedKey = replaceArrayKeyValue($data, 'ab-variation-letter', 'C', [
'ab-variation-title' => 'My New Title'
]);
$serialized = serialize($data);
You could replace this with array_recursive if you're not wanting the changes to occur further down any nested child arrays.
When using this function, the $data array is modified directly. The result of the function is a joint string of the key path to that value, in this case:
echo $matchedKey; // Result: 1.ab-variation-letter
If you echo print_r($data, true), you get the intended result:
Array (
[0] => Array( ... )
[1] => Array
(
[ab-variation-letter] => C
[ab-variation-title] => My New Title
[ab-variation-wysiwyg-editor-] => ccccccccccccccccc
[ab-variation-conversion-count] =>
[ab-variation-views] =>
[ab-variation-start-date] =>
[ab-variation-end-date] =>
[ab-variation-winner] =>
)
[2] => Array( ... )
[3] => Array( ... )
)
I got it working after some playing around with this code below. Open to other versions as well thanks
$serialized_meta_data_string = 'a:4:{i:0;a:8:{s:19:"ab-variation-letter";s:1:"B";s:18:"ab-variation-title";s:6:"bbbbbb";s:28:"ab-variation-wysiwyg-editor-";s:12:"bbbbbbbbbbbb";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:1;a:8:{s:19:"ab-variation-letter";s:1:"C";s:18:"ab-variation-title";s:5:"ccccc";s:28:"ab-variation-wysiwyg-editor-";s:17:"ccccccccccccccccc";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:2;a:8:{s:19:"ab-variation-letter";s:1:"D";s:18:"ab-variation-title";s:8:"dddddddd";s:28:"ab-variation-wysiwyg-editor-";s:1:"d";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:3;a:8:{s:19:"ab-variation-letter";s:1:"E";s:18:"ab-variation-title";s:8:"eeeeeeee";s:28:"ab-variation-wysiwyg-editor-";s:30:"eeeeeee eeeeeeeeeeeee eeeeeeee";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}}';
$update_on_key = 'ab-variation-title';
$ab_version = 'C';
$new_value = 'new variation title on variation C';
$new_data = updateMetaArrayData($serialized_meta_data_string, $update_on_key, $ab_version, $new_value);
echo '<pre>';
echo $new_data;
function updateMetaArrayData($serialized_meta_data_string, $update_on_key, $ab_version, $new_value){
$new_meta_data_arrays = array();
//un-serialize meta data string
$meta_data_arrays = unserialize($serialized_meta_data_string);
foreach($meta_data_arrays as $key => $value){
$new_meta_data_arrays[$key] = $value;
if(isset($value['ab-variation-letter']) && $value['ab-variation-letter'] == $ab_version){
$new_meta_data_arrays[$key][$update_on_key] = $new_value;
}
}
echo '<pre>';
print_r($new_meta_data_arrays);
$new_serialized_meta = serialize($new_meta_data_arrays);
return $new_serialized_meta;
}

PHP - array key within array value

I have a PHP array like this:
$arr = array(
'id' => 'app.settings.value.id',
'title' => 'app.settings.value.title',
'user' => 'app.settings.value.user'
);
I want to remove '.id', '.title' and '.user' in the array values. I want to insert the key of this array at the end of the value. I know, that I can get an array key by passing an array and a value to 'array_search', but I want the key within this one array definition - at the end of it's value. Is this possible?
I don't like this, but I guess it's simple and works:
$arr = array(
'id' => 'app.settings.value',
'title' => 'app.settings.value',
'user' => 'app.settings.value'
);
$result = array();
foreach ($arr AS $key => $value) {
$result[$key] = $value . '.' . $key;
}
You're storing app.settings.value which is the same for all array items, so personally I'd prefer:
$arr = array(
'id',
'title',
'user'
);
function prepend_key($key)
{
return 'app.settings.value.' . $key;
}
$result = array_map('prepend_key', $arr);
With $result containing:
array(
'app.settings.value.id',
'app.settings.value.title',
'app.settings.value.user'
);
At the end of the day, either works :)

adding element to array

I have an array that looks like this:
array
0 =>
array
'title' => string 'Ireland - Wikipedia, the free encyclopedia'
'url' => string 'http://en.wikipedia.org/wiki/Ireland'
1 =>
array
'title' => string 'Ireland's home for accommodation, activities.'
'url' => string 'http://www.ireland.com/'
that I want to add a score of 0 to each element. I thought this simple foreach loop would do the trick but...well....it doesn't :/
public function setScore($result)
{
foreach($result as $key)
{
$key = array('title', 'url', 'score' => 0);
}
return $result;
}
Can someone help me out?
Thanks
foreach works on a copy of the array. You can modify $key all you want, it's not going to reflect on the original array.
You can use $key by reference though, then it'll work as expected:
foreach ($result as &$value) {
$value['score'] = 0;
}
Manual entry: http://php.net/manual/en/control-structures.foreach.php
You create a new array here and do nothing with it:
foreach($result as $key){
$key = array('title', 'url', 'score' => 0);
}
What you want to do is to modify a reference to existing one:
foreach($result as &$key){ # Note the '&' here
$key['score'] = 0;
}
Although deceze is right, you can also do this using array_walk(), like this:
array_walk( $result, function( &$el) { $el['score'] = 0; });
Here's an example of how to accomplish this.
$array = array( array( 'title' => "Ireland - Wikipedia, the free encyclopedia", 'url' => "http://en.wikipedia.org/wiki/Ireland"), array( 'title' => "Ireland's home for accommodation, activities.", 'url' => "http://www.ireland.com/" ) );
function setScore( $result )
{
foreach( $result as &$element )
{
$element['score'] = 0;
}
return $result;
}
$array = setScore( $array );
print_r( $array );
You could also do:
function setScore( &$result )
{...}
and then just:
setScore( $array );

Categories