in_array not finding the value which is present? - php

Here is the code to check if the contact_id is present in the pool of particular user's pool
function checkid()
{
$conn = connectPDO();
$query = "SELECT contact_id FROM contacts WHERE contact_by = :cby";
$st = $conn->prepare( $query );
$st->bindValue( ':cby', $this->contact_by, PDO::PARAM_INT );
$st->execute();
$row = $st->fetchALL();
$conn = null;
print_r($this->contact_id); //1
print_r($row); //Array ( [0] => Array ( [contact_id] => 1 [0] => 1 ) [1] => Array ( [contact_id] => 3 [0] => 3 ) )
if( !in_array( $this->contact_id, $row ))
{
echo 'You are not authorised to update the details of this contact';
}
}
Here is the url:
http://localhost/contmanager/home.php?action=update&contactid=1
One thing i noticed is that, when i use fetch instead of fetchall, it works fine for contact_id '1' but fails when using fetchALL.

in_array not works for multidimentional array's, A workaroud will be:
foreach( $row as $each ){ #collect all the ids in an array
$temp[] = $each['contact_id'];
}
Then check for in_array:
if( !in_array( $this->contact_id, $temp )){
//your code here
}

use this function for multidimentional array's :
function in_multiarray($elem, $array)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem)
return true;
else
if(is_array($array[$bottom]))
if(in_multiarray($elem, ($array[$bottom])))
return true;
$bottom++;
}
return false;
}
example :
$array = array( array( 'contact_id' => '1' , 1 ) , array( 'contact_id' => '3' , 3 ) );
var_dump( in_multiarray( 1 , $array ) );

Related

Building a string Concat array with the same ID inside a query loop

i have a query inside a for loop that getting the product name of every array element. Now in every element of my array, i have an ID, where i want to concat all product names with the-same shipping_id.
Here i have my array with values like these:
Array name:id with values of:
Array
(
[0] => Array
(
[product_id] => 1
[shipping_id] => 1
)
[1] => Array
(
[product_id] => 2
[shipping_id] => 1
)
[2] => Array
(
[product_id] => 1
[shipping_id] => 2
)
)
now i made this code with these:
$first = true;
$temp_ship_id = "";
$product_list = "";
foreach ($ids as $product) {
$productname = $this->getproductname($product[0][product_id]);
// if($first) {
// $temp_ship_id = $product[0][shipping_id];
// $first = false;
// }
// if($product[0][shipping_id] == $temp_ship_id) {
// $product_list .= $productname.";
// } else {
// $product_list .= $productname.";
// //$product_list = "";
// $temp_ship_id = $product[0]->shipping_id;
// }
}
public function getproductname($product_id) {
$product = DB::table('products')->select('product_name')
->where(['products.product_id'=>$product_id])
->first();
return $product->product_name;
}
what am i doing is, i am getting the first shipping id and store it and i made a condition if they are thesame then i go concat the productname but, i see my logic is bad.
Please help me in other way. Something like This line of code to begin with:
foreach ($ids as $product) {
$productname = $this->getproductname($product[0][product_id]);
//code for concat goes here
}
public function getproductname($product_id) {
$product = DB::table('products')->select('product_name')
->where(['products.product_id'=>$product_id])
->first();
return $product->product_name;
}
Adjust below to your actual data, let me know if you have questions.
<?php
$concat = array();
$array = array( array( 'product_id'=>1, 'shipping_id'=>1, 'product_name' => 'a' ), array( 'product_id'=>2, 'shipping_id'=>1, 'product_name' => 'b' ), array( 'product_id'=>3, 'shipping_id'=>2, 'product_name' => 'c' ), array( 'product_id'=>4, 'shipping_id'=>1, 'product_name' => 'd' ) );
foreach( $array as $row ) {
if( isset( $concat[ $row['shipping_id'] ] ) ) {
$concat[ $row['shipping_id'] ] .= ',' . $row['product_name'];
} else {
$concat[ $row['shipping_id'] ] .= $row['product_name'];
}
}
var_dump( $concat );
?>

Splitting a Associative Array Based off if Condition of Value

I'm combining an array based off a MySQL Query:
$newskus = array();
$newqtys = array();
$sql1 = $db->query("//QUERY//");
while($row = $sql1->fetch_assoc()) {
$newskus[] = $row['SKU'];
$newqtys[] = $row['Quantity'];
}
$newskusandqtys = array_combine($newskus, $newqtys);
This gives me an associative array like so:
Array
(
[Product 1] => -1
[Product 2] => 0
[Product 3] => 3
)
I'm looking to split this array based off the condition of the integer value.
That is, if the value is above 0, it'll put the contents into a variable $newqtysabovezero
Ending with an expected output of
Array
(
[Product 3] => 3
)
And the other way around, if the value is greater than or equal to 0, put this into an array variable $newqtysbelowzero with an expected output of
Array
(
[Product 1] => -1
[Product 2] => 0
)
I'm able to do this with a numerical array, but it of course is not passing the key:
foreach( $newqtys as $item ) {
if ( $item > '0' ) {
$newqtysabovezero[] = $item;
} elseif ( $item <= '0') {
$newqtysbelowzero[] = $item;
}
}
How would I modify this to get my expected output?
Here is one way:
foreach( $newqtys as $key => $item ) {
if ( $item > '0' ) {
$newqtysabovezero[$key] = $item;
} elseif ( $item <= '0') {
$newqtysbelowzero[$key] = $item;
}
}
And here is a method using array_filter():
$in = array(
'Product 1' => -1,
'Product 2' => 0,
'Product 3' => 3
);
function at_and_below($v) {
return $v <= 0;
}
function above($v) {
return $v > 0;
}
$newqtysabovezero = array_filter($in, 'above');
$newqtysbelowzero = array_filter($in, 'at_and_below');
At first, to get all values from the 'Quantity' field as integers you should cast them to integer type:
...
while($row = $sql1->fetch_assoc()) {
$newskus[] = $row['SKU'];
$newqtys[] = (int) $row['Quantity'];
}
$newskusandqtys = array_combine($newskus, $newqtys);
Then, you can easily separate values which are greater than OR equal/less than 0:
foreach (newskusandqtys as $k => $item) {
if ($item > 0) {
$newqtysabovezero[$k] = $item;
} else {
$newqtysbelowzero[$k] = $item;
}
}
You can skip the array_combine part, and just read the values into the final arrays as you fetch them.
while($row = $sql1->fetch_assoc()) {
if ($row['Quantity'] > 0) {
$newqtysabovezero[$row['SKU']] = $row['Quantity'];
} else {
$newqtysbelowzero[$row['SKU']] = $row['Quantity'];
}
}

How to navigate through an array of unordered keys

Hello i want to pagination an array with for loop but the problem is my array keys is not like(1,2,3,4,5 ... etc) ,,
for ($x=0; $x<$members_per_page; $x++) {
$position = (int) ($currentPage-1) * $members_per_page + $x;
$member = get_userdata($members[$position]);
blackfyre_clan_members_links($member,$post_meta_arr, $post_id, $isleader);
if ( $position >= $last_key ) break;
}
and my array content is :
Array
(
[4] => Array
(
[boid] => 4
[cr_nickname] =>
)
[564] => Array
(
[boid] => 564
[cr_nickname] =>
)
) .... ETC
You could force your array to have sequential keys by using array_values like below:
for ($x=0; $x<$members_per_page; $x++) {
$position = (int) ($currentPage-1) * $members_per_page + $x;
$member = get_userdata(array_values($members)[$position]);
blackfyre_clan_members_links($member,$post_meta_arr, $post_id, $isleader);
if ( $position >= $last_key ) break;
}
However a (possibly) better way to paginate would be :
$offset = (int) ($currentPage-1) * $members_per_page;
$slice = array_slice ($members, $offset, $members_per_page,true);
array_walk($slice, function ($member) use ($post_meta, $post_id, $isleader) {
blackfyre_clan_members_links($member,$post_meta_arr, $post_id, $isleader);
});
Just use foreach ($members as $member){} instead of for

Search a multidimensional array for duplicates and return duplicate values and array key

I have the following multidimensional array:
$ancestors = array(
[1] =>array("Andrew","Adele"),
[2] =>array("Bertha","Bill","Billy","Blake"),
[3] =>array("Cathy","Case","Cory","Creek","Andrew","Ceaser","Cece","Childer"));
I am trying to search the rows and return duplicate values along with the array key of the lowest number the duplicate appears and return values to an associative array:
$common = array("Andrew"=>"1");
// merge all array in one
$new = array();
foreach($ancestors as $i)
$new = array_merge($new, $i);
// make array value => count and sort in in descendant order
$ar = array_count_values($new);
arsort($ar);
// save result array while count > 1
$result = array();
foreach($ar as $k => $v) {
if ($v < 2) break;
$result[$k] = array_search($k, $new) + 1;
}
print_r($result);
We have to compare each row with following rows, so row 1 with 2 and 3, row 2 with 3, row 3 with nothing (it is already compared).
To do this, we use a base-1 for to loop through all $ancestors elements except last, then we compare each name with greater ancestors:
$result = array();
/* Loop count($ancestors) -1: */
for( $i = 1; $i<count( $ancestors ); $i++ )
{
/* Loop for each name: */
foreach( current( $ancestors ) as $val )
{
/* If name is already in result, skip: */
if( isset( $result[$val] ) ) continue;
/* Loop for each following ancestors: */
foreach( array_slice( $ancestors, $i, Null, True ) as $key => $row )
{
if( in_array( $val, $row ) ) $result[ $val ] = key( $ancestors );
}
}
next( $ancestors );
}
For this $ancestors:
$ancestors = array(
1 =>array( "Andrew","Adele" ),
2 =>array( "Bertha","Bill","Billy","Blake","Adele" ),
3 =>array( "Cathy","Case","Cory","Creek","Andrew","Ceaser","Bill","Cece","Childer" ),
4 =>array( "Cathy" )
);
the result is:
Array
(
[Andrew] => 1
[Adele] => 1
[Bill] => 2
[Cathy] => 3
)
First combine all the names into one array, with names as keys and arrays of generation indexes as values:
foreach ($ancestors as $generation_key => $generation) {
foreach ($generation as $name) {
$combined[$name][] = $generation_key;
}
}
Then limit the combined results to values having more than one instance of the name:
$duplicates = array_filter($combined, function($x) { return count($x) > 1; });
Then convert the arrays to single values using min:
foreach ($duplicates as &$value) {
$value = min($value);
}
unset($value);

php array_multisort() by 2 field

I use array_multisort() function to sort an array by a field value. what I need is to sort it by 2 field values, by date and by time.
here is the structure of the array:
Array
(
[0] => Array
(
[id_art] => 5292
[free_art] => 0
[apero_art] => 0
[name_cat] => Teatro
[date_dat] => 2010-11-24
[date2_dat] => 0000-00-00
[name_spa] => Cinema Teatro
[title_int] => Il piacere dell'onestÃ
[id_cat] => 2
[time_tim] => 20:30:00
[intro_int] => Una produzione Teatro Eliseo di Roma - ChiassoCultura
[image_art] => noimage.png
)
[1] => Array
(
[id_art] => 4983
[free_art] => 0
[apero_art] => 0
[name_cat] => Cinema
[date_dat] => 2011-04-20
[date2_dat] => 2011-04-20
[name_spa] => Cinema Morettina
[title_int] => Inland Empire
[id_cat] => 1
[time_tim] => 20:30:00
[intro_int] => Rassegna dedicata a David Lynch
[image_art] => noimage.png
)
[2] => Array
(
[id_art] => 4983
[free_art] => 0
[apero_art] => 0
[name_cat] => Cinema
[date_dat] => 2011-04-22
[date2_dat] => 2011-04-22
[name_spa] => Cinema Iride
[title_int] => Inland Empire
[id_cat] => 1
[time_tim] => 17:00:00
[intro_int] => Rassegna dedicata a David Lynch
[image_art] => noimage.png
)....
What I do now is:
function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
$sort_col = array();
foreach ($arr as $key=> $row) {
$sort_col[$key] = $row[$col];
}
array_multisort($sort_col, $dir, $arr);
}
How can I easily make in one time the double sort?
Thanks.
If I understand what you need to do, you can use usort:
usort($array, function($a, $b) {
if ($a['date_cat'] > $b['date_cat']) return 1;
if ($a['date_cat'] < $b['date_cat']) return -1;
if ($a['time_tim'] > $b['time_tim']) return 1;
if ($a['time_tim'] < $b['time_tim']) return -1;
return 0;
});
The way your function works it a bit twisty, to me.
You extract a column of your array to create an array to sort linked to the original array. It took several readings and a php manual check to understand your code (too bad), you should have (to me) detach the creation of the index array into another function prior than calling the sort.
If you need to have dynamic colums selection maybe you can leverage on closures (PHP 5.3+ ?):
function your_sort($orderby, $array) {
return usort($array, function ($a, $b) use ($orderby) {
foreach($orderby as $field) {
if ($a[$field] > $b[$field]) return 1;
if ($a[$field] < $b[$field]) return -1;
}
return 0;
});
}
And then you can call the function like this:
your_sort(array('date_cat','time_tim'), $array);
Usign some code from php.net comment and other adjustment, I wrote a function that accept these argument:
$a = array
$orderby = an order string written in sql language
$children_key = name of the eventual column where eventual children node are saved
Here the function:
function array_multiorderby( $data, $orderby, $children_key=false )
{
// parsing orderby
$args = array();
$x = explode( ' ', str_replace( ',', ' ', $orderby ) );
foreach( $x as $item )
{
$item = trim( $item );
if( $item=='' ) continue;
if( strtolower($item)=='asc' ) $item = SORT_ASC;
else if( strtolower($item)=='desc' ) $item = SORT_DESC;
$args[] = $item;
}
// order
foreach ($args as $n => $field)
{
if (is_string($field))
{
$tmp = array();
foreach ($data as $key => $row)
$tmp[$key] = $row[$field];
$args[$n] = $tmp;
}
}
$args[] = &$data;
call_user_func_array('array_multisort', $args);
$data = array_pop($args);
// order children
if( $children_key )
{
foreach( $data as $k=>$v ) if( is_array($v[$children_key]) ) $data[$k][$children_key] = array_multiorderby( $v[$children_key], $children_key, $orderby );
}
// return
return $data;
}
Application to your specific case:
$array = array_multiorderby( $array, "date_dat DESC, time_tim DESC" );

Categories