Working with array, compare values and sum them - php

I have cart system which is saved in json array in database. I want to select all orders then all product_id's inside this array and show on page products which has most sells like bestsellers.
So far I'm able to take the array out and it's looks like this
array(2) {
[224]=> array(6) {
// data in which I'm not interested
}
}
array(2) {
[23]=> array(6) {
// data in which I'm not interested
}
}
array(2) {
[1]=> array(6) {
// data in which I'm not interested
}
}
array(2) {
[1231]=> array(6) {
// data in which I'm not interested
}
}
Each array(2) {...} represent one order. I need this [224],[23].. because those are products ID. My question is how to know what property to select in my loop?
If it was like this
array(2) {
["id"]=> string(13) "32"
}
I will make something like $data->id to get 32
This is how I got the array
foreach ($products as $item) {
$data = json_decode($item->details, true);
echo var_dump($data);
}
Any help is appreciated.
Update: with print_r($data); they're looking like this
Array (
[224] => Array (
// data
)
)
Array (
[23] => Array (
// data
)
)
....
To me this is completely different because I don't know the name of column therefore I can't use array_column()

If always the key of $data is product id, then in foreach loop get the key by using php function key().
foreach ($products as $item) {
$data = json_decode($item->details, true);
echo key($data)."</br>";
//OR Create an array to store all the product ids
$product_ids[] = key($data);
}
echo "<pre>";
print_r($product_ids);
// to count each product id
$product_ids_count = array_count_values($product_ids);
//get the most used product id
echo $most_used_product_id = array_search(max($product_ids_count),$product_ids_count);

You can use array_keys which will list all keys in the array.
http://php.net/manual/en/function.array-keys.php
$products = array_keys($array);
And the $products array will hold your values 224, 23 and so on.
https://3v4l.org/PEjfH
With this $products array you can get values from your original array like this:
$array[$product[0]]["cost"]
I just made up the cost but you get the idea.
The above would be the same as $array["224"]["cost"]

Related

How to convert array and sort elements by categories?

Please help.
Can't understand how to sort items by categories in array.
I have plain array with products:
Item 1 (Category C)
Item 2 (Category B)
Item 3 (Category A)
Item 4 (Category C)
Item 5 (Category B)
Item 6 (Category A)
and want to sort list by categories, something like:
Category A
Item 3
Item 6
Category B
Item 2
Item 5
Category C
Item 1
Item 4
Original array something like this:
array(4) {
[0]=>
array(19) {
["product_name"]=> "Samsung GALAXY Note 3"
["categories_id"]=> "3"
["categories_name"]=> "Smartphones"
}
[1]=>
array(19) {
["product_nam"]=> "Samsung GALAXY Note 8"
["categories_id"]=> "2"
["categories_name"]=> "Tablets"
}
[2]=>
array(19) {
["product_nam"]=> "Samsung GALAXY Tab 3"
["categories_id"]=> "3"
["categories_name"]=> "Smartphones"
}
[3]=>
array(19) {
["product_name"]=> "Samsung ATIV Smart PC"
["categories_id"]=> "1"
["categories_name"]=> "Laptops"
}
}
Try:
foreach($array as $value){
$newArray[$value["categories_name"]][] = $value;
}
print_r($newArray);
// First group items by categories
$groupedData = [];
foreach ($originalArray as $item) {
$categoryID = $item['categories_id'];
if (!isset($groupedData[$categoryID])) {
$groupedData[$categoryID] = [
'name' => $item['categories_name'],
'items' => [],
];
}
$groupedData[$categoryID]['items'][] = $item['product_name'];
}
// Next you can sort $groupedData with sorting functions
// Then output data
foreach ($groupedData as $array) {
echo $array['name'] . ':<br />';
foreach ($array['items'] as $item) {
echo $item . '<br />';
}
}
Try this function:
/**
* Creates custom array map from 2-dimensional $arr with predefined structure, changing its keys by value, which is present in second dimension.
*
* #param array $arr 2-dimensional array, which should be mapped, basing on subarray value
* #param string $targetKey Subarray key name. Value, which corresponds to this key, will be set as key in 1st dimension, and this 1st-dimensional key will correspond to subarray
* #param boolean $add If TRUE, every res. arr val represented as indexed list of subarrays. Otherwise every res. arr val contains one sub. arr
* #return array Mapped arr | original arr, if $targetKey wasn't found in any subarray
*/
public static function setKeyFromVal($arr, $targetKey, $add = false)
{
$mappedArr = [];
foreach ($arr as $subArr) {
if (array_key_exists($targetKey, $subArr)) {
if ($add) {
$mappedArr[$subArr[$targetKey]][] = $subArr;
} else {
$mappedArr[$subArr[$targetKey]] = $subArr;
}
unset($mappedArr[$subArr[$targetKey]][$targetKey]);
}
}
return empty($mappedArr) ? $arr : $mappedArr;
}
Call it (with true argument!):
setKeyFromVal($a, 'categories_id', true);
categories_id is a sort key, and you can change it.

Why is it when I take 3 array values it shows error but when I only show 1 value it works?

When I use var_dump($paid) it will show all the values
this is the code. If I use all 3 description, amount, and payment_type it will show an error that the amount is undefined. But if I use only 1 like for example I use only the description and erase the rest the code will work
$paid = array();
foreach ( $user as $u ) :
$paidDetail = \App\PaymentTransaction::where('user_id','=', $u->user_id)->get();
if ($paidDetail->count()) :
$paid[]['description'] = $paidDetail[0]->description;
$paid[]['amount'] = $paidDetail[0]->amount;
$paid[]['payment_type'] = $paidDetail[0]->payment_type;
endif;
endforeach;
return $paid;
this is for the view/blade to show the details in the frontend
{{ $paid['description'] }}
{{ $paid['amount'] }}
{{ $paid['payment_type'] }}
showing each 1 of them works but showing all of them at the same time will show an error saying that the 2nd value is undefined
Below is the var_dump($paid)
array(1) { ["description"]=> string(33) "Plan Subscription Payment for PRO" }
array(1) { ["amount"]=> float(350) }
array(1) { ["payment_type"]=> string(27) "Stripe Payment Subscription" }
array(1) { ["description"]=> string(38) "Test Plan Subscription Payment for PRO" }
array(1) { ["amount"]=> float(351) }
array(1) { ["payment_type"]=> string(27) "Stripe Payment Subscription" }
It's just because,
Your foreach loop overwriting 0 Index Parameters and every time last record stores in Array.
And Executing query in every iteration of foreach loop may reduce your code performance.
You Should use laravel eloquent model and relationship for this issue.
https://laravel.com/docs/5.5/eloquent-relationships
Try this:
$paid = array();
$i=0;
foreach ( $user as $u ) :
$paidDetail = \App\PaymentTransaction::where('user_id','=', $u->user_id)->get();
if ($paidDetail->count()) :
$paid[$i]['description'] = $paidDetail[0]->description;
$paid[$i]['amount'] = $paidDetail[0]->amount;
$paid[$i]['payment_type'] = $paidDetail[0]->payment_type;
$i++;
endif;
endforeach;
return $paid;
The main issue with you code is that you forgot to use a index on you array. Adding $i as an index makes sure that each user payment have his own index.
Note
Lopping thru an collection and doing a SQL QUERY for each user is not wrong but also not a good practice. Try to get both in one SQL Statment.

return passed array keys and values

I am working in WordPress. I am using a plugin to get the admin options. The plugin takes an argument as an ID to get the value from the database like so.
$option = ot_get_option('email_address');
The above line of code would return
myEmail#example.com
I want to write a helper function that would get multiple values at once. Normally, I would get the options like this.
$option_1 = ot_get_option('option1');
$option_2 = ot_get_option('option2');
$option_3 = ot_get_option('option3');
I figured there could be a better way that would look a little nicer. I put together this little function that does work
function ritual_get_options($arg_list = array())
{
$options = array();
foreach( $arg_list as $key => $value){
$options[] = ot_get_option($value, array());
}
return $options;
}
using the function above, I can now pass the id's of the options like so
ritual_get_options('option1','option2','option3');
My issue is that the above will return an array with numeric keys. 0,1,2. Here is the exact array that is getting returned when I do a var_dump on the front end
[0]=>
string(16) "100 Main Street,"
[1]=>
string(18) "Hamilton, Ontario."
[2]=>
string(15) "+1 800 999 9898"
[3]=>
string(19) "mail#yourdomain.com"
I want to return the array keys with the value so that I can easily figure out what value is in what key. Here is the line that I used to get the above array
$options = ritual_get_options(array('number' => 'streetnumber','street' => 'street','phone' => 'phone_number','email' => 'email'));
When I go to use the returned values, I want to be able to use the key so that I could do
echo $options['number'];
instead of doing
echo $options[0];
I have not been able to figure out how to return the keys passed in to the function and preserve them into through the return.
Set the option name as key while building the array:
foreach( $arg_list as $option ){
$options[$option] = ot_get_option( $option );
}
Btw, using extract() on the $options array will allow you to use e.g. $phone_number instead of $options['phone_number']

Array Combine in PHP

I am trying to combine keys and values in arrays. I have an product_id with different price.
Let say
Product id and price
id 101 and price is 100
id 105 and price is 200
id 101 and price is 300
list of product ids in array with $product_ids[] and list of price also $price_amount[]
So I preferred to combine the two arrays using array_combine
I made array_combine($product_ids,$price_amount);
Now it appears look like this way
array(2) { [101]=> float(100) [105]=> float(300) }
Is there is a way to add the key elements to the id as something like
array(2) {
[101] => float(400) (100+300)
[105] => float(300)
}
Here is the idea i tried
$products = array();
$order_totalss = array();
foreach (get_posts('post_type=shop_order&numberposts=-1&post_status=publish') as $order) {
$order = new WC_Order($order->ID);
if (wc_customer_bought_product($order->billing_email, $order->user_id, $product_id)) {
$productcounts[] = $product_id;
$order_totalss[] = $order->get_total();
}
}
$arraymergeme = array_combine($productcounts, $order_totalss);
You will have to do this manually I'm afraid:
$total = array();
foreach ($product_ids as $key => $value) {
// each value of product_ids becomes the key
if (isset($total[$value])) {
// we have seen this key before
$total[$value] += $price_amount[$key];
} else {
// new key
$total[$value] = $price_amount[$key];
}
}
Simple code so you can see what's happening clearly:
$ids = array(101, 105, 101);
$prices = array(100, 200, 300);
$totals = array();
foreach ($ids as $key => $id)
{
// Make sure index is defined
if ( ! isset($totals[$id]))
{
// Make sure we have a value
$totals[$id] = 0;
}
// Assuming index $key matches... add to the total
$totals[$id] += $prices[$key];
}
PHP arrays are associative so you can write something like: price['101'] = 100 thereby using the product id as the array index.
Thinking you are looking for something like this. I haven't done php in awhile, so the syntax may need tweaking, but I think the logic is correct.
$cart = array(
"101" => 100,
"105" => 200,
"101" => 300
);
$product_id_arr = array();
foreach ($cart as $product_id => $price) {
if(array_key_exists($product_id, $product_id_arr)){
$product_id_arr[$product_id] = $product_id_arr[$product_id] + $price;
}else{
$product_id_arr[$product_id] = $price;
}
}
array_combine will not do the trick for you. You will have to iterate through the array and total them as you go. Here's an example:
<?php
$product_ids = array('101', '105', '101');
$price_amount = array(100, 200, 300);
$combined = array();
$productCount = count($product_ids);
for($i = 0; $i < $productCount; $i++) {
// if this product_id is not in the $combined array, add its price
// as associative array ('101'=>100)
// but if it is found in $combined, add to its current price
if (!array_key_exists($product_ids[$i], $combined)) {
$combined[$product_ids[$i]] = $price_amount[$i];
} else {
$combined[$product_ids[$i]] += $price_amount[$i];
}
}
print_r($combined);
?>
Results:
Array
(
[101] => 400
[105] => 200
)
Try this
$final_arr = array();
for($i=0;$i<count($product_ids);$i++) {
if(!isset($final_arr[$product_ids[$i]])) {
$final_arr[$product_ids[$i]] = 0;
}
$final_arr[$product_ids[$i]] += $price_amount[$i];
}
Yes you can add key elements to id, basically an array can be created by using the array() language construct. It takes any number of comma-separated key => value pairs as arguments.
array(
key => value,
key2 => value2,
key3 => value3,
...
)
the one you are looking for is associative array. you can definitely specify the key you want and store the value you want at that key.
here is a link that would be helpful

Understanding CodeIgniter objects and multidimensional arrays

I'm working on a project in CodeIgniter 2 and now I'm stuck on the most basic of concepts.
Model:
Get an object array from my table which contains all rows that match a specific value for a field named foo. There can be one or more rows that match. In this example, two rows.
public function get_sample($foo)
{
$query = $this->db->get_where('sample_db', array('foo' => $foo));
return $query->result();
}
Controller:
Assign the results and make output available to view.
public function view($foo)
{
$data['array'] = $this->sample_model->get_sample($foo);
$this->load->view('view', $data);
}
View:
echo var_dump($array); // for testing
echo $array[1]->text
var_dump() of $array:
array(2) {
[0]=> object(stdClass)#23 (4) {
["id"]=> string(1) "1"
["foo"]=> string(3) "bar"
["number"]=> string(4) "1234"
["text"]=> string(23) "This is content in 1234"
}
[1]=> object(stdClass)#24 (4) {
["id"]=> string(1) "2"
["foo"]=> string(3) "bar"
["number"]=> string(4) "9999"
["text"]=> string(23) "This is content in 9999"
}
}
The rendered ouput of echo $array[1]->text; is: This is content in 9999
And I understand how all that is working: $array[1]->text is the content of the text field in the array object with the index of 1, my second object.
However, I have a field called number and I want to access the object with a certain number and get its corresponding text value.
Example: How can I retrieve the value of text where the number is 9999? I cannot use $array[1]->text since I can never be sure of the object's position in the array. Something like $array['number' => '9999']->text, but I know that's not right. Maybe I need to loop through the array looking for a match?
This looks so simple yet everything I've tried has failed and resulted in various PHP errors. I've been studying the PHP manual here and here, but cannot seem to find anything about what I'm looking to do, or maybe I'm just misapplying what I'm reading. Any guidance is appreciated.
In addition to an answer using best practices following the MVC model, I'm hoping for a link to the proper page in the documentation, as well as pointing out any errors in my wording/terminology above.
EDIT:
This answer contains the actual code I used to solve my problem. Although, Yagi's answer was accepted because it put me in the right direction.
How about using this :
foreach ($array as $row) {
if ($row->number == '9999') {
echo $row->text;
}
}
Loop through the array, and find the number object value of 9999 and get the text
Why don't you just to a query and search for that number (or order by that number?)
Either way, what you need is a multidimensional array search function (that iterates through array of object and returns the found field value combo )
Something like this (put this in helper)
function multi_array_search($array, $field, $value)
{
$results = array();
if (is_array($array))
{
if ($array->$field == $value) //chek the filed against teh value, you can do addional check s(i.e. if field has been set)
$results[] = $array;
foreach ($array as $subarray)
$results = array_merge($results, multi_array_search($subarray, $key, $value)); //recurisve serach
}
return $results;
}
//than in view or in controller, depending where you need it
$result = multi_array_search($array, "number", "9999");
var_dump($result) will return or whether number of foudn instances
array() {
[0]=> object(stdClass)#24 (4) {
["id"]=> string(1) "2"
["foo"]=> string(3) "bar"
["number"]=> string(4) "9999"
["text"]=> string(23) "This is content in 9999"
}
}
you might be looking for something like this...
array_filter($array, function($o){ return $o->number == 9999; } );
http://php.net/manual/en/function.array-filter.php
EDIT
$o is the parameter in the callback function. each element of the array is passed to the callback function. if the function returns false, the element will be filtered out.
$arr = array(
(object) array(
'num' => 33,
'text' => 'hello',
),
(object) array(
'num' => 44,
'text' => 'world',
),
);
$filtered = array_filter($arr, function($o){ return $o->num == 33; });
echo $filtered[0]->text; // hello
as you stated, index will remain, so use array_values or array_shift. here's an example with function
function get_by_num($arr, $num){
return array_shift(array_filter($arr, function($o) use ($num) { return $o->num == $num; }));
}
$obj = get_by_num($arr, 44);
var_dump($obj);
// object(stdClass)#2 (2) { ["num"]=> int(44) ["text"]=> string(5) "world" }
in this case $obj will be either NULL if element is not found, or the first match. $num is transferred along so you can use any value. you can even improve it:
function get_first_match($arr, $field, $val){
return array_shift(array_filter($arr, function($o) use ($field, $val) { return $o->{$field} == $val; }));
}
$obj = get_first_match($arr, 'num', 44);
and now you can search any field. in your case
$obj = get_first_match($array, 'number', 9999);
Thanks to Yagi's answer, I came up with the following very simple solution. I loop through the array and assign the value of text to a new array with an index that matches the value of number. Then in the view file, I can access the text value based on this index.
Controller:
public function view($foo)
{
$data['array'] = $this->sample_model->get_sample($foo);
foreach ($data['array'] as $row) {
$data['result'][$row->number] = $row->text;
};
$this->load->view('view', $data);
}
View:
if (isset($result[9999])) echo $result[9999];

Categories