PHP - How to append array with some conditions - php

$list = array(
[0]=> array(
[name]=>'James'
[group]=>''
)
[1]=> array(
[name]=>'Bobby'
[group]=>''
)
)
I am looking to update the item 'group' where the name is 'Bobby'. I am looking for a solution with the two following formats. Thank you in advance for your replies. Cheers. Marc.
array_push($list, ???)
and
$list[] ??? = someting

As far as I know, there's no way updating your array with one of the given syntax.
The only similar thing I can come on is looping over the array using array_walk ... http://www.php.net/manual/en/function.array-walk.php
Example:
array_walk($list, function($val, $key) use(&$list){
if ($val['name'] == 'Bobby') {
// If you'd use $val['group'] here you'd just editing a copy :)
$list[$key]['group'] = "someting";
}
});
EDIT: Example is using anonymous functions which is only possible since PHP 5.3. Documentation offers also ways working with older PHP-versions.

This code may help you:
$listSize = count($list);
for( $i = 0; $i < $listSize; ++$i ) {
if( $list[$i]['name'] == 'Bobby' ) {
$list[$i]['group'] = 'Hai';
}
}
array_push() doesn't really relate to updating a value, it only adds another value to an array.

You cannot have a solution that will fit both formats. The implicit array push $var[] is a syntactic construct, and you cannot invent new ones - certainly not in PHP, and not most (all?) other languages either.
Aside from that, what you are doing is not pushing an item on to the array. For one thing, pushing items implies an indexed array (yours is associative), and for another pushing implies adding a key to the array (the key you want to update already exists).
You can write a function to do it, something like this:
function array_update(&$array, $newData, $where = array(), $strict = FALSE) {
// Check input vars are arrays
if (!is_array($array) || !is_array($newData) || !is_array($where)) return FALSE;
$updated = 0;
foreach ($array as &$item) { // Loop main array
foreach ($where as $key => $val) { // Loop condition array and compare with current item
if (!isset($item[$key]) || (!$strict && $item[$key] != $val) || ($strict && $item[$key] !== $val)) {
continue 2; // if item is not a match, skip to the next one
}
}
// If we get this far, item should be updated
$item = array_merge($item, $newData);
$updated++;
}
return $updated;
}
// Usage
$newData = array(
'group' => '???'
);
$where = array(
'name' => 'Bobby'
);
array_update($list, $newData, $where);
// Input $array and $newData array are required, $where array can be omitted to
// update all items in $array. Supply TRUE to the forth argument to force strict
// typed comparisons when looking for item(s) to update. Multiple keys can be
// supplied in $where to match more than one condition.
// Returns the number of items in the input array that were modified, or FALSE on error.

Related

link a value from an array to another in PHP

I'm trying two combine two arrays based on the values names.
Here what I'm trying to do :
$array1 = ("fifa21","pes21","halflife2","carma2");
$array2 = ("fifa21_cover","pes21_cover","halflife2_cover");
I want to loop through both arrays and if value from array1 match value from array 2 it will list both values like this :
fifa21 - fifa21_cover
pes21 - pes21_cover
halflife2 - halflife2_cover
carma2 - default_cover
if not find anything in the array2, a default cover will be used.
Note: the arrays will be filled dynamically based in a scanDir (two different folders search) and the arrays can be sorted differently than shown in the example above.
This code will loop through array1 and check to see if the item cover exists in array2, if it does then it will echo out in the format you wanted.
$array1 = array("fifa21","pes21","halflife2","carma2");
$array2 = array("fifa21_cover","pes21_cover","halflife2_cover");
foreach ($array1 as $item) {
if (in_array($item."_cover", $array2)) {
echo "<p>".$item." - ".$item."_cover</p>\n";
} else {
// use default cover...
}
}
(because it is lunch time and I need to write some code)
Given two arrays:
$array1 = ["fifa21", "pes21", "halflife2", "carma2"];
$array2 = ["fifa21_cover", "pes21_cover", "halflife2_cover"];
A function such as this can walk through and look for items that start with those values:
function merge_arrays(array $array1, array $array2): array
{
$output = [];
array_walk(
$array1,
static function ($key) use ($array2, &$output) {
$items = array_filter($array2, static fn($f) => 0 === mb_strpos($f, $key));
if (count($items) === 1) {
$output[$key] = reset($items);
return;
}
if (count($items) === 0) {
$output[$key] = 'default_cover';
return;
}
throw new RuntimeException('More than one item found starting with key ' . $key);
}
);
return $output;
}
When called as:
print_r(merge_arrays($array1, $array2));
It will output:
(
[fifa21] => fifa21_cover
[pes21] => pes21_cover
[halflife2] => halflife2_cover
[carma2] => default_cover
)
For your use-case, it might be overly complicated when compared to a for loop, but it does the job.
Another version that more-blindly assumes only a one-to-one match could use the ?? operator for a null check, although I wouldn't recommend this. The more terse and compact that code looks, the more I find that it is usually very hard to reason about, especially in the future:
function merge_arrays(array $array1, array $array2): array
{
$output = [];
array_walk(
$array1,
static function ($key) use ($array2, &$output) {
$output[$key] = array_filter($array2, static fn($f) => 0 === mb_strpos($f, $key))[0] ?? 'default_cover';
}
);
return $output;
}
All code snipping provided works, however if the array values have extension it always assumes the default cover. I can figure it how using my code by removing the extension for compare purpose, and then I add it back.
Inside my loop I use this :
$keyvaluetemp = substr($keyvalue, 0, strrpos($keyvalue, "."));
the above it inside my first ForEach (where I check the first array), and then in the covers array I remove the "_cover" by nothing :
$keyvalue2temp = (str_replace("_cover", "",$keyvalue2));
then I use the following code inside the second ForEach to add the data to a DB:
// if fantart match the game file name so we associate it to the game and save to the DB
if ( stripos ( $keyvalue2temp , $keyvaluetemp ) !== FALSE )
{
$sql = "UPDATE listgames SET FanArt='$keyvalue2' WHERE Name='$keyvalue'";
$con->exec($sql);
}
// if fanart is empty we add a default picture
$checkifempty = "SELECT `FanArt` FROM `listgames` WHERE `Name` = '$keyvalue'";
$runsql = $con->query($checkifempty);
$row = $runsql->fetch(PDO::FETCH_ASSOC);
$fanartkey = $row['FanArt'];
if($fanartkey == '')
{
$sql = "UPDATE listgames SET FanArt='nopic.JPG' WHERE Name='$keyvalue'";
$con->exec($sql);
}
Later in my code I print the results from the DB. I don't know if this is the best approach, however it does exactly what I want :)

PHP check if array contains any key other than some whitelisted

I would like to check all keys of a global GET array and do something, if it contains keys, other than some whitelisted ones from an array.
Let's say the current url is:
.../index.php?randomekey1=valueX&randomkey2=valueY&acceptedkey1=valueZ&randomkey3=valueA&acceptedkey2=valueB
Just for better visualization:
These GET parameters are all available in the global GET variable which looks something like this:
$GET = array(
"randomekey1" => "valueX",
"randomkey2" => "valueY",
"acceptedkey1" => "valueZ",
"randomkey3" => "valueA",
"acceptedkey2" => "valueB"
);
The keys I accept and want to let pass, I put into an array too:
$whitelist = array(
"acceptedkey1",
"acceptedkey2",
"acceptedkey3",
);
Now I want to check whether $GET contains any key other than the whitelisted. So in the URL example from above it should return "true", because there are keys in the $GET array which aren't in the whitelist.
Not only the existence of such an unknown (none whitelisted) key should trigger a true, but please also its emptyness!
Another example would be the following url:
.../index.php?acceptedkey1=valueZ&acceptedkey3=valueB
This should return false, because no other key other than the ones in the whitelist were found.
Unfortunately I was not able to find any modification of the in_array function or array_search which would fit these requirements, because as far as I know these functions are only looking for something specific, whereas in my requirements I am also looking for something specific (the whitelist keys), but at the same tme I have to check if some unknown keys exist.
Thank you.
It seems you want to determine whether an array contains keys that don't exist in a whitelist.
One way to find the difference between arrays is to use array_diff():
array_diff ( array $array1 , array $array2 [, array $... ] ) : array
Returns an array containing all the entries from array1 that are not present in any of the other arrays.
So, it can be used to return all keys from the URL that are not present in the whitelist:
$extrasExist = !empty( array_diff( array_keys($GET), $whitelist ) );
var_dump($extrasExist);
Here's a demonstration:
$get1 = array(
"randomekey1" => "valueX",
"randomkey2" => "valueY",
"acceptedkey1" => "valueZ",
"randomkey3" => "valueA",
"acceptedkey2" => "valueB"
);
$get2 = array(
"acceptedkey1" => "valueZ",
"acceptedkey2" => "valueB"
);
$whitelist = array(
"acceptedkey1",
"acceptedkey2",
"acceptedkey3"
);
$extrasExist = !empty(array_diff(array_keys($get1),$whitelist));
var_dump($extrasExist);
$extrasExist = !empty(array_diff(array_keys($get2),$whitelist));
var_dump($extrasExist);
bool(true)
bool(false)
Everything in PHP doesn't have to be all "lets find function that does exactly what I'm looking for". Just do a simple foreach loop, which can accomplish what you're looking for:
function clear_filter() {
$whitelist = array( "project", "table_name", "filterDates", );
foreach ($_GET as $gkey => $gval) {
if (!in_array($gkey, $whitelist)) {
return false;
}
}
return true;
}
You can also write it more simply, with one foreach loop like below:
function isValid() {
// Copy the array
$temp = $_GET;
// Loop through the array, and remove any whitelisted elements
foreach ($whitelist as $wkey) {
unset($temp[$wkey]);
}
// If count($temp) > 0, there are non whitelisted entries in the array.
return count($temp) === 0;
}
You can use the following function.
$check = checkWhitliest( $_GET, $whitelist ) );
var_dump ($check );
You can call the above function as
function checkWhitliest( $array, $whitelist ) {
$allKeys = array_keys ( $array); //Get all Keys from the array.
$diff = array_diff( $allKeys, $whitelist); //Get the values which are not in whitelist.
if( count ( $diff ) > 0 ) { //If the count is greater than 0, then there are certain extra kesy in $_GET
return true;
}
return false;
}
There are only two techniques that I would recommend for this task and both make key comparisons for performance reasons. Using array_diff() or in_array() will always be slower than array_diff_key() and isset(), respectively, because of how PHP treats arrays as hash maps.
If you don't mind iterating the entire $GET array (because its data is relatively small), then you can concisely flip the whitelist array and check for any key differences.
var_export(
(bool)array_diff_key($GET, array_flip($whitelist))
);
If performance is more important than code brevity, then you should craft a technique that uses a conditional break or return as soon as a non-whitelisted key is encountered -- this avoids doing pointless iterations after the outcome is decided.
$hasNotWhitelisted = false;
$lookup = array_flip($whitelist);
foreach ($GET as $key => $value) {
if (isset($lookup[$key])) {
$hasNotWhitelisted = true;
break;
}
}
var_export($hasNotWhitelisted);
Or
function hasNotWhitelisted($array, $whitelist): bool {
$lookup = array_flip($whitelist);
foreach ($array as $key => $value) {
if (isset($lookup[$key])) {
return true;
}
}
return false;
}
var_export(hasNotWhitelisted($GET, $whitelist));
All of the above techniques deliver a true result for the sample data. Demo of all three snippets.

PHP: Check for existing array inside of array of objects

Have a problem with checking array inside of large array of objects. For example I have
$arr1 = array("a"=>12,"b"=5,"c"=>16);
and I need to check if this array exists inside array like this:
$arr2 = array( array( "a"=>12,"b"=5,"c"=>16),
array("d"=>1,"g"=5,"c"=>16),
array("a"=>12,"c"=5,"e"=>3) );
I have tried in_array(), and it works, but takes a lot of time if I have large $arr2.
Thank you in advance.
P.S. works with PHP 5.6
Instead of your current $arr structure, you'd better have an associative array, where the keys uniquely identify the value.
If you need to search that array several times, you might still save time if you would spend some time to create such associative array from your existing array:
$arr2 = array(
array( "a"=>12,"b"=>5,"c"=>16),
array("d"=>1,"g"=>5,"c"=>16),
array("a"=>12,"c"=>5,"e"=>3)
);
// use key/value pairs, with as key the JSON-encoding of the value
// Note: this will take some time for very large arrays:
foreach ($arr2 as $sub) {
ksort($sub); // need to sort the keys to make sure we can find a match when needed
$hash[json_encode($sub)] = $sub;
}
// function to see whether the value is in the array: this will be fast!
function inHash($hash, $sub) {
ksort($sub);
return isset($hash[json_encode($sub)]);
}
// test
if (inHash($hash, array("d"=>1,"g"=>5,"c"=>16))) {
echo "found";
} else {
echo "not found";
}
Of course, if you could create the original immediately with such keys, then you don't have the overhead of creating it afterwards.
#D.Kurapin simply try with == or === operator(according to you) with foreach() like below:
<?php
$arr1 = array("a"=>12,"b"=>5,"c"=>16);
$arr2 = array( array( "a"=>12,"b"=>5,"c"=>16),
array("d"=>1,"g"=>5,"c"=>16),
array("a"=>12,"c"=>5,"e"=>3) );
$isExist = false;
foreach ($arr2 as $key => $value) {
if($value === $arr1){
$isExist = true;
break;
}
}
if($isExist){
echo "yes found in the array";
}
else{
echo "sorry did not find in the array";
}

php - Find array for which a key have a given value

I have an array of dictionnaries like:
$arr = array(
array(
'id' => '1',
'name' => 'machin',
),
array(
'id' => '2',
'name' => 'chouette',
),
);
How can I find the name of the array containing the id 2 (chouette) ?
Am I forced to reindex the array ?
Thank you all, aparently I'm forced to loop through the array (what I wanted to avoid), I thought that it were some lookup fonctions like Python. So I think I'll reindex with id.
Just find the index of array that contains the id you want to find.
SO has enough questions and answers on this topic available.
Assuming you have a big array with lots of data in your real application, it might be too slow (for your taste). In this case, you indeed need to modify the structure of your arrays, so you can look it up faster, e.g. by using the id as an index for the name (if you are only interested in the name).
As a for loop would be the best way to do this, I would suggest changing you array so that the id is the arrays index. For example:
$arr = array(
1 => 'machin',
2 => 'chouette',
);
This way you could just get the name for calling $arr[2]. No looping and keeping your program running in linear time.
$name;
foreach ($arr as $value){
if ( $value['id'] == 2 ){
$name = $value['name'];
break;
}
}
I would say that it might be very helpful to reindex the information. If the ID is unique try something like this:
$newarr = array();
for($i = 0;$i < count($arr);$i++){ $newarr[$arr[$i]['id']] = $arr[$i]['name']; }
The result would be:
$newarr = array('1'=>'machin','2'=>'chouette');
Then you can go trough the array with "foreach" like this:
foreach($newarr as $key => $value){
if($value == "machin"){
return $key;
}
}
But of course the same would work with your old array:
foreach($arr as $item){
if($item['name'] == "machin"){
return $item['id'];
}
}
It depends on what you are planning to do with the array ;-)
array_key_exist() is the function to check for keys. foreach will help you get down in the multidimensional array. This function will help you get the name element of an array and let you specify a different id value.
function findKey($bigArray, $idxVal) {
foreach($bigArray as $array) {
if(array_key_exists('id', $array) && $array['id'] == $idxVal) {
return $array['name'];
}
}
return false;
}
//Supply your array for $arr
print(findKey($arr, '2')); //"chouette"
It's a bit crude, but this would get you the name...
$name = false;
foreach($arr as $v) {
if($v['id'] == '2') {
$name = $v['name'];
break;
}
}
echo $name;
So no, you are not forced to reindex the array, but it would make things easier.

Checking if all the array items are empty PHP

I'm adding an array of items from a form and if all of them are empty, I want to perform some validation and add to an error string. So I have:
$array = array(
'RequestID' => $_POST["RequestID"],
'ClientName' => $_POST["ClientName"],
'Username' => $_POST["Username"],
'RequestAssignee' => $_POST["RequestAssignee"],
'Status' => $_POST["Status"],
'Priority' => $_POST["Priority"]
);
And then if all of the array elements are empty perform:
$error_str .= '<li>Please enter a value into at least one of the fields regarding the request you are searching for.</li>';
You can just use the built in array_filter
If no callback is supplied, all entries of input equal to FALSE (see converting to boolean) will be removed.
So can do this in one simple line.
if(!array_filter($array)) {
echo '<li>Please enter a value into at least one of the fields regarding the request you are searching for.</li>';
}
Implode the array with an empty glue and check the size of the resulting string:
<?php if (strlen(implode($array)) == 0) echo 'all values of $array are empty'; ?>
Please note this is a safe way to consider values like 0 or "0" as not empty. The accepted answer using an empty array_filter callback will consider such values empty, as it uses the empty() function. Many form usages would have to consider 0 as valid answers so be careful when choosing which method works best for you.
An older question but thought I'd pop in my solution as it hasn't been listed above.
function isArrayEmpty(array $array): bool {
foreach($array as $key => $val) {
if ($val !== '' || $val !== null) // remove null check if you only want to check for empty strings
return false;
}
return true;
}
you don't really need it.
You're going to validate these fields separately and by finishing this process you can tell if array was empty (or contains invalid values, which is the same)
simplify use this way:
$array = []; //target array
$is_empty = true; //flag
foreach ($array as $key => $value) {
if ($value != '')
$is_empty = false;
}
if ($is_empty)
echo 'array is empty!';
else
echo 'array is not empty!';
I had the same question but wanted to check each element in the array separately to see which one was empty. This was harder than expected as you need to create the key values and the actual values in separate arrays to check and respond to the empty array element.
print_r($requestDecoded);
$arrayValues = array_values($requestDecoded); //Create array of values
$arrayKeys = array_keys($requestDecoded); //Create array of keys to count
$count = count($arrayKeys);
for($i = 0; $i < $count; $i++){
if ( empty ($arrayValues[$i] ) ) { //Check which value is empty
echo $arrayKeys[$i]. " can't be empty.\r\n";
}
}
Result:
Array
(
[PONumber] => F12345
[CompanyName] => Test
[CompanyNum] => 222222
[ProductName] => Test
[Quantity] =>
[Manufacturer] => Test
)
Quantity can't be empty.
this is pretty simple:
foreach($array as $k => $v)
{
if(empty($v))
{
unset($array[$k]);
}
}
$show_error = count($array) == 0;
you would also have to change your encapsulation for your array values to double quotes.

Categories