Recursively loop through a PHP array to manipulate data - php

I'm trying to loop through a PHP array but I only ever get back my original data. I think it has something to do with when I break the loop
$newData = $this->seperateKeyValuePairs($data);
private function seperateKeyValuePairs($array)
{
foreach($array as $key => $item)
{
if( is_array($item) ) $this->seperateKeyValuePairs($item);
if( is_string($key) && $this->stringStartsWith($key, 'is_') ) {
$item = $this->makeBoolean($item);
}
}
return $array;
}

I think the problem is on this line:
$item = $this->makeBoolean($item);
You change the value of item. Item is not a pointer to the value in the array, but a copy of it, so the value in the array remains unchanged. What you want to do instead is this:
$array[$key] = $this->makeBoolean($item);
In the same spirit, you have to change
if( is_array($item) ) $this->seperateKeyValuePairs($item);
to
if( is_array($item) ) $array[$key] = $this->seperateKeyValuePairs($item);

Related

How to get PHP value from input using Tagify

I have a problem with submitting a PHP form using jQuery Tagify.
If I add 2 tags like John and Thomas, then I'm getting $_POST['tag'] as:
'[{"value":"John"}, {"value":"Thomas"}]'
How I can change my $_POST['tag'] to get this POST as: John,Thomas?
var_dump(implode(', ', array_column(json_decode($_POST['tag']), 'value')));
First you decode the JSON coming in $_POST['tag'] into an array/object structure. array_column gives you the flat array with the values. Then you join it separated by commas (implode).
Yes, the square brackets is in the way. In fact, tagify-js outputs an array of json objects. So json_decode function doesn't work either. It is necessary to prepare the output.
Here is the function I implemented to save the input value. It converts them to an array of values.
function br_bookmarks_tagify_json_to_array( $value ) {
// Because the $value is an array of json objects
// we need this helper function.
// First check if is not empty
if( empty( $value ) ) {
return $output = array();
} else {
// Remove squarebrackets
$value = str_replace( array('[',']') , '' , $value );
// Fix escaped double quotes
$value = str_replace( '\"', "\"" , $value );
// Create an array of json objects
$value = explode(',', $value);
// Let's transform into an array of inputed values
// Create an array
$value_array = array();
// Check if is array and not empty
if ( is_array($value) && 0 !== count($value) ) {
foreach ($value as $value_inner) {
$value_array[] = json_decode( $value_inner );
}
// Convert object to array
// Note: function (array) not working.
// This is the trick: create a json of the values
// and then transform back to an array
$value_array = json_decode(json_encode($value_array), true);
// Create an array only with the values of the child array
$output = array();
foreach($value_array as $value_array_inner) {
foreach ($value_array_inner as $key=>$val) {
$output[] = $val;
}
}
}
return $output;
}
}
Usage:
br_bookmarks_tagify_json_to_array( $_POST['tag'] );
Hope it helps others.

Removing array key from multidimensional Arrays php

I have this array
$cart= Array(
[0] => Array([id] => 15[price] => 400)
[1] => Array([id] => 12[price] => 400)
)
What i need is to remove array key based on some value, like this
$value = 15;
Value is 15 is just example i need to check array and remove if that value exist in ID?
array_filter is great for removing things you don't want from arrays.
$cart = array_filter($cart, function($x) { return $x['id'] != 15; });
If you want to use a variable to determine which id to remove rather than including it in the array_filter callback, you can use your variable in the function like this:
$value = 15;
$cart = array_filter($cart, function($x) use ($value) { return $x['id'] != $value; });
There are a lot of weird array functions in PHP, but many of these requests are solved with very simple foreach loops...
$value = 15;
foreach ($cart as $i => $v) {
if ($v['id'] == $value) {
unset($cart[$i]);
}
}
If $value is not in the array at all, nothing will happen. If $value is in the array, the entire index will be deleted (unset).
you can use:
foreach($array as $key => $item) {
if ($item['id'] === $value) {
unset($array[$key]);
}
}

PHP in_array not working with current array structure

I am using a custom method to return a query as an array.
This is being used to check if a discount code posted is in the DB.
The array ends up as example:
Array
(
[0] => stdClass Object
(
[code] => SS2015
)
[1] => stdClass Object
(
[code] => SS2016
)
)
So when I am trying to do:
if ( ! in_array($discount_code, $valid_codes)) {
}
Its not working. Is there a way I can still use the function for query to array I am using and check if its in the array?
No issues, I can make a plain array of the codes but just wanted to keep things consistent.
Read about json_encode (serialize data to json) and json_decode (return associative array from serialized json, if secondary param is true). Also array_column gets values by field name. so we have array of values in 1 dimensional array, then let's check with in_array.
function isInCodes($code, $codes) {
$codes = json_encode($codes); // serialize array of objects to json
$codes = json_decode($codes, true); // unserialize json to associative array
$codes = array_column($codes, 'code'); // build 1 dimensional array of code fields
return in_array($code, $codes); // check if exists
}
if(!isInCodes($discount_code, $valid_codes)) {
// do something
}
Use array_filter() to identify the objects having property code equal with $discount_code:
$in_array = array_filter(
$valid_codes,
function ($item) use ($discount_code) {
return $item->code == $discount_code;
}
);
if (! count($in_array)) {
// $discount_code is not in $valid_codes
}
If you need to do the same check many times, in different files, you can convert the above code snippet to a function:
function code_in_array($code, array $array)
{
return count(
array_filter(
$array,
function ($item) use ($code) {
return $item->code == $code;
}
)
) != 0;
}
if (! code_in_array($discount_code, $valid_codes)) {
// ...
}
try this
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
then
echo in_array_r("SS2015", $array) ? 'found' : 'not found';
why not solve it as a school task - fast and easy:
for($i = 0; $i < count($valid_codes); $i++) if ($valid_codes[$]->code == $discount_code) break;
if ( ! ($i < count($valid_codes))) { // not in array
}

unset extract variables in php from within class method

<?php
namespace foo;
class bar{
public static function runner( $data )
{
extract ($data);
foreach( $elements as $element )
{
$varsToWipe = array_keys($element);
extract( $element );
/*
bunch of code using the variables extracted from $element, eg if( isset($runnerSpeed) )
*/
//now i want to be able to unset all the elements set from the extract within the foreach loop
foreach( $varsToWipe as $var )
{
//but what goes here in the unset function?
\unset( );
}
}
}
}
How can I unset the variables extracted from within the foreach loop in the runner method?
The contents of $data can vary and the vars need to be unset so as not used again on the next loop iteration. I know i can ref the array itself but would be quicker to write if this could work...
Thanks,
John
A simpler foreach example:
$array = range(0,6);
$i = 0;
foreach( $array as $a )
{
echo $i.' ';
if( $i == 0 )
{
$egg = true;
}
++$i;
if( isset($egg) )
{
echo 'eggs ';
}
}
will print
0 eggs 1 eggs 2 eggs 3 eggs 4 eggs 5 eggs 6 eggs
You could then add a removal of $egg from the globals as this is where is sits:
$array = range(0,6);
$i = 0;
foreach( $array as $a )
{
echo $i.' ';
if( $i == 0 )
{
$egg = true;
}
else
{
unset( $GLOBALS['egg'] );
}
++$i;
if( isset($egg) )
{
echo 'eggs ';
}
}
Now it would print:
0 eggs 1 2 3 4 5 6
But what do you unset when you are within a class method, where is the variable actually stored?
Don't use the extract() function in the first place and simply iterate over the given array.
<?php
class Foo {
public function runner($data) {
foreach ($data as $delta => $element) {
if ($element === "something") {
// do something
}
}
}
}
Of course you could unset something inside the array now, but why would you want to? I can't see a reason why because the array isn't passed by reference and isn't used after the loop so it will go out of scope and is simply collected by the garbage collector.
In case of nested arrays:
foreach ($data as $delta => $element) {
if (is_array($element)) {
foreach ($element as $deltaInner => $elementInner) {
// ...
Pretty late now but for reference.
You can unset() them directly with:
unset($$var);
What extract does is equivalent to:
foreach($arr as $key => $value) {
$$key = $value;
}
So to unset you do:
foreach(array_keys($arr) as $key) {
unset($$key);
}
But like mentioned, you don't need to unset() them as they are deleted when the function completes as they will become out of scope.
Also, extract() is totally fine as it (most likely) does not copy the data values, it just creates new symbols for each array key. PHP internally will only copy the values if you actually modify it ie. copy-on-write with reference counting.
You can off course test this using memory_get_usage() before and after you do extract() on a large array.

Assign value to double array

I have an issue assigning values to an array of arrays to add duplicates into the same values. Code is as following:
if( isset($rowsarray) && 0 < count($rowsarray) ) {
foreach ( $rowsarray as $rowt ) {
if( $version == $rowt[0] ) {
$rowt[1] += $success;
$rowt[2] += $failure;
$noDuplicate = false;
break;
}
}
}
if( true == $noDuplicate) {
$rowsarray[] = array($version, $success, $failure);
}
So if it's the first occurence of a version I just add it, otherwise I just increas the success and failure rate in the array. I have tried foreach ( $rowsarray as $key => $rowt ) without success as the "internal" array doesnt seem to be affected here. I am total new to php so I guess it's a rather simple solution but for now it takes only the first version access and all the other is inreased inside the loop but not outside it.
You're trying to modify a temporary array created by foreach(), which means $rowt is trashed/replaced on every iteration. You can work around it with a reference or a modified foreach:
foreach ( $rowsarray as &$rowt ) {
^----
$rowt[1] += $success;
or, less troublesome:
foreach($rowsarray as $key => $rowt) {
$rowsarray[$key][1] += $success;
You can simplify this check with:
if( isset($rowsarray) && 0 < count($rowsarray) ) {
with
if( ! empty( $rowsarray ) ){
And then,
foreach ( $rowsarray as $key => $rowt ) {
if( $version == $rowt[0] ) {
$rowsarray[$key][1] += $success;
$rowsarray[$key][2] += $failure;

Categories