I am doing a simple shopping application were user may choose books from the store based on the title, price, quantity etc. At the moment all details of the books are kept in an associative array which looks like this:
$menu = array(
array ('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss'),);
}
What I am trying to achieve is merge or remove duplicated entries of book id's also each book title will be printed in one single row containing 'title', 'id', 'price'
for example:
Alex qty:2 price 4.95
David qty:2 price 5.95
and so on...
And this is my cart file:
$buy = array();
$qty = 0;
$total = 0;
foreach ($_SESSION['buy'] as $id) {
foreach ($menu as $book ) {
if ($book['id'] == $id) {
$buy[] = $book;
$total += $book['price'];
}
}
}
}
if (count($buy) > 0)
if (count($book) > 0)
{
echo"<table>";
echo"<tr><th>Item Description</th><th>Quantity</th><th>Price</th></tr>";
foreach ($buy as $book){
$f_price = sprintf("%0.2f", $book["price"]);
echo"<tr><td>" .$book["title"] ."</td>";
echo"<td>" .$qty."</td><";
echo"<td>" .$f_price."</td></tr>";
}
echo"<tr><td>Total</td><td>".$total."</td></tr>";
echo"</table>";
}
I will be extremely grateful for any help or advice cause I spent long long time to resolve this problem trying use unique functions, for statements foreach loop but in vain I am still novice also please try to be a little tolerant . Cheers!
Untested but this should do what you want using array_count_values to obtain the quantities you were looking for along with a few changes to make the script more efficient and easier to manage.
<?php
//the ids of the items the user wants to buy
$ids=$_SESSION['buy'];
//Your database of items
$menu = array(
array ('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss')
);
//Create a reverse look-up for the database
$lookUp=array();
foreach($menu as $i=>$v)$lookUp[$v['id']]=$menu[$i];
//populate the cart with items, their quantities, and a total
$cart = array();
$total = 0;
foreach (array_count_values($ids) as $id=>$quantity)
{
if (!array_key_exists($id, $lookUp))continue;
$item=$lookUp[$id];
$itemTotal=$item['price']*$quantity;
$total+=$itemTotal;
$cart[]=array_merge($item,array('quantity'=>$quantity,'itemTotal'=>$itemTotal));
}
if(count($cart) > 0)
{
echo '<table>';
echo '<tr><th>Item Description</th><th>Quantity</th><th>Price</th><th>Item Total</th></tr>';
foreach ($cart as $item)
{
echo sprintf('<tr><td>%s</td><td>%s</td><td>%0.2f</td><td>%0.2f</td></tr>',
$item["title"],$item['quantity'],$item['price'],$item['itemTotal']);
}
echo '<tr><td colspan="3" style="text-align:center;">Total</td><td>'.$total.'</td></tr>';
echo '</table>';
}
If it's just based off the id, when you build the array, store the book id as the key in the larger array, so your end array would be:
$books = array(
1=> array ('id' => '1', [...]),
2=> array ('id' => '2', [...])
);
You could also add some code that checks when you try to assign a value to that array to see if the key is already set.
if(!isset($books[$book_id])){
//Add to the array
}else{
//Maybe display an error?
}
PS: Category only has one a in it.
It's a pretty cumbersome way to make a stock overview of the books in your collection, but that aside :)
If i was to work with an array like that, (and i would never do that :)) i would first select all unique keys, and then go through them one by one, counting the number of times it occur in the $menu array.
As follows:
$unique_books = array_unique($menu);
foreach($unique_books as $book){
$qty = array_keys($menu, $book["id"])
$book["qty"] = $qty;
$stock = $book;
}
As you can see, now $stock will be the unique array, with a qty added to it, containing the number of times, the id was seen in $menu.
This is just a fast code block, and should be testet, but the theory works i think. As i mentioned before, the way you'r making this in the first place, is not very smart, and you should really reconsider the whole thing imo :)
If you don't wanna duplicates simple use the book_id as the key of buy array
Example:
$menu = array(
array('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss')
);
$session=array(1,2,2,2,1);
$buy = array();
foreach ($session as $id) {
foreach ($menu as $book) {
if ($book['id'] == $id) {
if(isset($buy[$id])){
$buy[$id]['qty']++; // increase quantity
$buy[$id]['total'] += $book['price']; // total price only for this id
$buy['total'] += $book['price']; // All ids price total
}else{
$buy[$id] = $book; // assign new id to the buy array
$buy[$id]['qty'] = 1; // quantity reset to 1
$buy[$id]['total'] = $book['price']; // id price
$buy['total'] += $book['price']; // total price
}
}
}
}
print_r($buy);
You can test it here!
http://codepad.org/wH2WskLG
Instead of merging duplicates you should add book id and qty as array row to session.
On session start..
if (!isset($_SESSION['buy']))
$_SESSION['buy'] = array();
When adding new..
$new_book = $added_book; // just for example
$qty = $added_qty; // Added qty
// Check if book already exists in shopping cart and update qty
if (array_key_exists($new_book['id'], $_SESSION['buy'])) {
$_SESSION['buy'][$new_book['id']] += $qty;
} else {
$_SESSION['buy'][$new_book['id']] = $qty;
}
Then on shopping cart view just loop thru your items..
foreach($menu as $book ) {
if (array_key_exists($book['id'], $_SESSION['buy'])) {
// User bought this book..
$qty = $_SESSION['buy'][$book['id']];
}
}
Related
I am scraping an ecommerce website and need to get some data from products, like product name, price, ...
For that, I have:
...
// library includes...
$html = file_get_html($link);
foreach($html->find('.productBoxClass') as $element){
foreach($element->find('.productTitle') as $product) {
$product = $product->plaintext;
}
foreach($element->find('.price') as $price) {
$price = $price->outertext;
}
// and so on...
}
I wanna save this data in a database. So, I want to save all the data in an array for after verify each product if I have to insert or just update. I am intending to populate an multi-dimensional array with this data:
Each position of the array with another array containing the information about one product... To make it easier to save in the database after...
Any help?
This seems like an abnormal data structure or you should be looping through it differently. But if it is an abnormal structure and the product and price aren't grouped together, they are just listed in the same order, then this should work:
$products = [];
$i = 0;
foreach($element->find('.productTitle') as $product) {
$products[$i++]['product'] = $product->plaintext;
}
$i = 0;
foreach($element->find('.price') as $price) {
$products[$i++]['price'] = $price->outertext;
}
Note the $i++ as the key which will increment $i each loop.
If the product and pricing are grouped together in an element, then you should be looping on that element and there should be no need for a foreach for product and price.
Please check the below code, let me know your thoughts...
<?php
// library includes...
$html = file_get_html($link);
$productArr = array();
foreach($html->find('.productBoxClass') as $element){
$tempArr = array('title' => '','price' => 0,'other' => ''); // declare temp array for stroing each product nodes
foreach($element->find('.productTitle') as $product) {
$tempArr['title'] = $product->plaintext; // To do check for empty text here
}
foreach($element->find('.price') as $price) {
$tempArr['price'] = $price->outertext; // To do validate the price
}
foreach($element->find('.other-features') as $price) {
$tempArr['other'] = $price->outertext; // To do validate the price
}
// and so on... with $tempArr['key']
// then assign
$productArr[] = $tempArr; // save temp array in global product array
}
// Product array
echo '<pre>';print_r($productArr);die;
Use in first foreach the count item:
...
// library includes...
$html = file_get_html($link);
// Array declaration
$products = array();
foreach($html->find('.productBoxClass') as $i => $element){
foreach($element->find('.productTitle') as $product) {
$products[$i]['name'] = $product->plaintext;
}
foreach($element->find('.price') as $price) {
$products[$i]['price'] = $price->outertext;
}
// and so on...
}
And will result:
Array
(
[0] => Array
(
[name] => Product 1
[price] => 1.00
)
[1] => Array
(
[name] => Product 1
[price] => 1.00
),
...
)
I have an array filled with the result of a query which is as follows:
$ticket[] = array(
'ticket_id' => $row->ticket_id,
'user_id' => $row->user_id,
'raffle_ticket_num' => $row->raffle_ticket_num
);
Now, in a while loop, I check in all arrays inside $tickets if my variable $number equals 'raffle_ticket_num'. I do this with the following code (from #Fuzzy Tree):
$ticket_num=1;
while ($ticket_num <= $total_slots){
foreach($ticket as $test) {
if($test['raffle_ticket_num'] == $ticket_num) {
echo $ticket_num.' claimed by '.$test['user_id'];
}
else{
echo $ticket_num;
}
}
$ticket_num++;
}
The problem that I'm having now is that because I'm using a foreach loop, if more than one results are found, it causes it to echo each result as much as there are rows in $ticket[]... So with 2 rows it echos everything 2 times (because of the foreach). Does anyone know a solution or alternatives for this?
You can see it live here: http://tinyurl.com/hxbhx7y .The bold numbers are slot 21 and 38 which are taken and showing the user_id (1). But as you can see it shows each number 2 times (because foreach has 2 results)
EDIT: Post updated with #Fuzzy Tree's answer
Version 1
foreach see answer by #FuzzyTree
Version 2
array_filter
$number = 1;
$winners = array_filter($tickets, function ($ticket) use ($number) {
return $ticket['raffle_ticket_num'] == $number;
});
// $winners now has all winning tickets.
var_dump($winners);
// Bonus pick a random winner
shuffle($winners);
var_dump(current($winners));
So best and easiest way to do it prepare your tickets array outside of raffles loop.
Solution
<?php
$tickets[] = array(
'ticket_id' => 1,
'user_id' => 2,
'raffle_ticket_num' => 15
);
$tickets[] = array(
'ticket_id' => 2,
'user_id' => 2,
'raffle_ticket_num' => 25
);
$tickets[] = array(
'ticket_id' => 3,
'user_id' => 1,
'raffle_ticket_num' => 21
);
$raffles = range(1, 50);
// Preparing tickets array. Now when I think Flattened is not the best word to describe it :)
$ticketsFlattened = array();
foreach ($tickets as $ticket) {
$ticketsFlattened[$ticket['raffle_ticket_num']] = $ticket;
}
// Could be while if you want
foreach ($raffles as $number) {
if (array_key_exists($number, $ticketsFlattened)) {
echo sprintf(
"Ticket %s is clamed by %s, ticket id %s %s",
$number,
$ticketsFlattened[$number]['user_id'],
$ticketsFlattened[$number]['ticket_id'],
PHP_EOL
);
} else {
echo sprintf("Ticket %s unclaimed %s", $number, PHP_EOL);
}
}
If you need to print the matching user_id and ticket_id then use a foreach to check each ticket one by one and when you see a ticket with the matching #, you can print the other details
foreach($tickets as $ticket) {
if($ticket['raffle_ticket_num'] == $number) {
print 'In array';
print $ticket['user_id'];
print $ticket['ticket_id'];
//break; //uncomment if you just want one
}
}
I have 4 arrays :
qb_array = { sku, stock } size:20803
valid_array = { sku, name, price, status } size:199803
by intersect qb_array && valid_array, base one sku then I have :
intersect_sku_array { sku } size:18795
Now, there are some data that I want to grab out of my first 2 arrays.
From qb_array, I want stock
From valid array - I want name, price, and status
Then I decide to create my 4th-array and called it :
4 - inserted_array ( because I will use this array to insert into my database )
I tried to construct it, and now I am stuck.
Here is my approach :
First, I did
foreach ($intersect_sku_array as $key ) {
$inserted_array[] = $key;
}
So far, over here is good - everything is working when I dd($inserted_array); I see all the stuffs in it.
Then, moving on to add the other 3 from my valid_array
foreach ($valid_array as $key => $value ) {
if ( in_array( $key , array_map('strtolower', $intersect_sku_array ) )){
$inserted_array[] = $value['name'];
$inserted_array[] = $value['price'];
$inserted_array[] = $value['status'];
}
}
Then I did dd($inserted_array); at the end, it is hanging on me.
After about 5 mn I got this error :
Maximum execution time of 300 seconds exceeded
Is it because I have too much data, or my code is stuck in the infinite loop some how ?
Can someone please explain all of these in details ?
Maybe this would help:
foreach($intersect_sku_array as $sku)
{
$qbRow = qb_array[array_search($sku,$qb_array)];
$validRow = valid_array[array_search($sku,$valid_array)];
inserted_array[] = array($sku, $qbRow[1], $validRow[1], $validRow[2], $validRow[3]);
}
Although I think it would be easier for you to use named arrays like the following:
qb_array = ['sku' => ['stock'=> 'actual stock']];
valid_array = ['sku' => ['name'=> 'actual name', 'price' => 'actual price', 'status' => 'actual status']];
Like so.
For one thing you are running the lowercasing inside the loop, which is certainly not the best way to save time.
Then you are constructing a "flat" array that will contain (sku, name, price, status) quadruplets (and no stock) in sequence.
I would rather have the database do a join on both tables, since SQL is a much better tool than PHP for that kind of job.
Now if for some reason you can't do that, better use sku as a key for your two arrays.
foreach ($qb_array as $val) $k_qb[strtolower($val['sku']) = $val['stock'];
foreach ($valid_array as $val) $k_va[strtolower($val['sku']) = array ($val['name'], $val['price'], $val['status']);
(if you must lowercase something, better do it late than never, but frankly this should also be done in the database, unless you're forced to work with garbage data)
Then you can do the join manually without any intermediate intersection array, like so:
forach ($k_qb as $sku => $stock) // use smallest array
{
if (!isset($k_va[$sku])) continue; // skip non-matching records
$record = $k_va[$sku];
$inserted_array[] = array (
'sku' => $sku,
'stock' => $stock,
'name' => $record[0],
'price' => $record[1],
'status' => $record[2]);
}
The order of the algorithm will be NlogM instead of MN if M and N are the sizes of both your arrays.
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
I got a marker with a category, say : "luggage" i would like to know what parent categories is luggage to set a specific marker on a map.
I created a top categories list of each category i need to display. Something like :
$education = [ "adultedu", "collegecounseling", "collegeuniv", "educationservices", "elementaryschools", "highs|chools", "preschools", "privatetutors", "religiousschools", "specialed", "specialtyschools", "artschools", "cprclasses", "cookingschools", "cosmetology_schools"]
I got the same lists for transports, shopping, health etc...
What is the best way to search in which category my keyword is from ?
Use an array and iterate through while using in_array:
$arrays = array(
'education' => &$education,
'transport' => &$transport,
'shopping' => &$shopping,
'health' => &$health
);
$searchingFor = 'foo';
$searchingForCategory = null;
foreach ($arrays as $category => $array) {
if (in_array($searchingFor, $array)) {
$searchingForCategory = $category;
break;
}
}
var_dump($searchingForCategory); //education / transport / shopping / health / NULL
You have to check each array with in_array() function.
if (in_array('luggage', $education)) {
// found
}
Also you can add all top categories to one array, lets say $topCategories ;)
Then you can check all with simple loop:
$foundInCategory = '';
foreach ($topCategories as $name => $subCategories) {
if (in_array('luggage', $subCategories)) {
$foundInCategory = $name;
break;
}
}
It'll add category name in which subcategory was found to variable $foundInCategory.