PHP: Rotating through an array - php

I've got a website on which I want to display items. These items are stored in a database in the following format:
ID Item Active
1 My item 0
2 My item 1
7 My item 1
8 My item 1
10 My item 0
Note here that the IDs are not necessarily evenly spaced. Each item is either active(1) or inactive(0). I want 3 items to be active at a time and every time my script is called I want the next item to become active and the oldest item to become inactive like so:
ID Item Active
1 My item 0
2 My item 0
7 My item 1
8 My item 1
10 My item 1
and so:
ID Item Active
1 My item 1
2 My item 0
7 My item 0
8 My item 1
10 My item 1
I'm currently struggling with the algorithm to consider the third case above. I can't just pick the highest ID that's active and move to the next item and set that active and at the same time pick the lowest one that's active and make it inactive.
Here's my code so far:
{
for ($i=0;$i<sizeof($videos);$i++)
{
echo $i."]";
if ($videos[$i]->active == 1)
{
if (!isset($first_active))
{
echo "mooh";
echo "[";
echo $first_active = $i;
echo "]";
}
if ( ($i < (sizeof($videos)-1)) && ($videos[$i+1]->active == 0) )
{
$videos[$i+1]->active = 1;
$videos[$i+1]->update();
echo "#".$first_active."|".$videos[$first_active]->id()."#";
$videos[$first_active]->active = 0;
$videos[$first_active]->update();
$first_active = null;
echo "|".$videos[$i+1]->id();
break;
}
elseif ($i == (sizeof($videos)-1))
{
$videos[0]->active = 1;
$videos[0]->update();
$videos[$first_active]->active = 0;
$videos[$first_active]->update();
$first_active = null;
echo "|".$videos[0]->id();
break;
}
}
}
}
This works until I get to the end, e.g. ID 10. It then correctly makes ID 1 active. In the next call, it makes ID 7 active and ID 1 inactive.
Any idea how I can 1) fix my code, 2) tackle this problem smarter?

Sounds to me like you actually need to store the last activation date instead of a simple on/off flag.
You can use two database queries, one to get the full list in order of ID, and another that specifically only gets the first 3 entries sorted by active date. Loop through your full list to get all the entries in order, then test the ID of each one with the ID of your 3 active to test if it is currently active. Then, setting a new item active is as simple as just updating the date/time of the active column on the item you want.
If you really want to keep the active on/off flag, then do so, just make another column with a last active date/time.

Related

How to check if a value is greater than within an array

I have the following SQL statement:
$query = "SELECT item, COUNT(*) as number FROM shop GROUP BY item";
This will give me the following result:
item number
item1 23
item2 15
item3 4
I want to use this to make menu items, so normally the menu would look:
item1
item2
item3
But I want to do a check if an item has less than 10 records, that I don't want to display this item.
So in this example, the menu would be like:
item1
item2
Any idea how to achieve this?
I would like to do this in PHP because I need all the items in the query but will only want to show them which are greater then 10 and need the other items later on.
If you want to do this in PHP then you can do like this
function filterArray($value){
return ($value.number > 10);
}
$filteredArray = array_filter($yourDBArray, 'filterArray');
foreach($filteredArray as $k => $v){
//your desired array
}
In terms of speed Mysql option is good as suggested above.
Just change your query from
SELECT item, COUNT(*) as number FROM shop GROUP BY item
to
SELECT item, COUNT(*) as number FROM shop GROUP BY item HAVING number>=10
As you really need to perform this in PHP you could use array_filter() which, using a closure, will remove items which number is less than 10:
$more_than_ten = array_filter($items, function ($i) { return $i['number'] >= 10; });
Doing it with SQL would be a better solution (about performances). In case you'd need it, you could use the HAVING clause (you can't perform a WHERE number >= 10):
SELECT
item,
COUNT(*) as number
FROM shop
GROUP BY item
HAVING number >= 10
I noticed php is tagged. For the sake of options, here's how I'd go about separating the unneeded data in php if you were to get it from the database as-is:
foreach ($data as $item) {
$num = (int) $item['number']; // force of habit
if ($num >= 10) {
// display it
}
}
I'd probably separate the data at the database step, but this works if it's the route you want to take.
There is two options to filter the data so only the rows with more then 10 will appear.
At the SQL query
__
SELECT item, COUNT(*) as number FROM shop GROUP BY item HAVING number > 9
This will cause you to recieve only the requested rows from the database
Filter with PHP - every time you want to print the menu or testing it out, just can the value of 'number' in the array reutrned from the query. You can also allocate new array and insert all the values that contains 'number' that bigger then 10.

PHP 2D array fails to increment qty

I have a problem updating a multidimensional array in PHP. I'm trying to implement am e-commerce website for a project and I am having problems with the shopping cart implementation.
Basically, I use a session to track the items the user adds to the shopping cart. Here's my logic in plain Pseudo code that is executed once the user clicks the add button after specifying a quantity to add for a product:
RETRIEVE 'cartItems' 2D array from SESSION array
IF 'cartItems' array does not exist in the session create new empty array and add the cartItem sub array to it with the qty and productID
ELSE Loop through the array retrieved from the SESSION array, find the product ID that matches the given product ID (index 0) and update the qty for that subarray (index 1).
Here is my PHP script addToCart.php which in turn calls another function in another script file that is included in it:
<?php
require_once("cart_utility.php");
session_start();
// Script for adding a given product to the client's cart through the use of Ajax and sessions
// retrieve values from ajax request
$productID = $_GET["productID"];
$qty = $_GET["qty"];
$cartItems = null;
// use sessions to add the items to the user's cart
// retrieve the multi-dimensional cart array if it exists, otherwise create one and add it
if(isset($_SESSION["cartItems"])){
$cartItems = $_SESSION["cartItems"];
}
else{
$cartItems = array();
}
addQtyForProduct($productID, $qty, $cartItems);
$_SESSION["cartItems"] = $cartItems;
print "Session cartItems after function return: ";
var_dump($_SESSION["cartItems"]);
// return info string with new qty of cart items
print ("success-" . getTotalCartItems($cartItems));
?>
And here's the other script file that does the handling of inserting and updating the array:
<?php
// Utility functions for retrieving items from the 2D cart items array
/* The array structure is given as (example values):
* | productID | qty |
* 0 | 1 | 3 |
* 1 | 2 | 1 |
* 2 | 5 | 8 |
* 3 | 8 | 3 |
*/
// increments the qty for the given product. If it does not exist then it is added into the main session array
// $cartItems: the main 2D array with the structure given above, pass by reference to change the array
function addQtyForProduct($productID, $qty, &$cartItems)
{
foreach($cartItems as $cartItem)
{
var_dump($cartItem);
if($cartItem[0] == $productID){
//print "Quantity given to increment: $qty";
//var_dump($cartItem);
print "Qty in current session array: $cartItem[1]";
$cartItem[1] += $qty;
print "New qty in cartItem array: $cartItem[1]";
return;
}
}
// not found, therefore add it to the main items array
array_push($cartItems, array($productID, $qty));
}
// returns the total number of items in the cart
function getTotalCartItems($cartItems)
{
$total = 0;
foreach($cartItems as $cartItem)
$total += $cartItem[1];
return $total;
}
?>
I have placed some var_dump statements and can confirm that upon returning from the function 'addQtyForProduct', the array is not updated. But why? I pass the array by reference to directly alter it's contents.
It successfully adds on the first time when there is no existing array but fails to increment if the array exists.
Also, the values are successfully incremented in the 'addQtyForProduct' function but the array somehow is not updated when it returns from the function.
I would gladly appreciate some help on this. I've been trying to understand this for days now and It's driving me nuts.
As read on this page you should use references. Add a & in front of your $cartItem and your script should work. Right now PHP stores a 'copy' of every value in your array in $cartItem, rather than it's reference. So currently you are editing a copy of the original, rather than the original array.

Building a specific array from a table of data

I have a table of data as such:
id | item | parent_id
1 item 1 0
2 item 2 0
3 item 3 2
4 item 4 3
5 item 5 1
...
The id is autoincrementing, and the parent_id reflects the id on the left. You may have come accross a database table design like this before.
The parent_id is not sequential as you can see.
I need to get this table data into an array in the format where all parents become a potential heading with their children underneath.
So I am looking at a structure like this:
Item 1
Item 5
Item 2
Item 3
Item 4
etc
In PHP I need an array structure that can display the above. But I am having a serious brain fart!
Can anyone help me with the array structure?
you may write somethin like this:
$a = Array(item1 => Array(item5), item2 => Array(item3 => Array(item4)))
or
$a = Array(item1 => parentid, item2 => parentid2 ....)
in the first example one item is the key for all ist children stored in the Array, in the other example all items are stored using an item key and an int value. this int value is the key for the parent item. which method you use depends on what you want to do with this Array. maybe both of my ideas are not good enough for your Needs. if thats the case, tell me what you need.
First of all, i will suggest you to read this, it's very useful for hierarchical structured data and there are available queries which will help you to get parents, children, etc ... and so and so.
Now to answer your question, try this :
$result = array();
while($data = mysql_fetch_assoc($query)) {
$id = $data['id'];
$parent = $data['parent_id'];
$keys = array_keys($result);
if(in_array($parent, $keys)) {
$result[$parent] = array_merge($result[$parent], array($id => $data['item']));
} else {
$result = array_merge($result, array($id => $data['item']));
}
}

How to retrieve the next item in a list of MySQL records?

I'm working with symfony using Propel trying to create functionality for back and next buttons:
$c = new Criteria();
$c->add(CartPeer::CATEGORY, $category);
$c->add(CartPeer::ITEM_ID, $item->getItemId(), Criteria::GREATER_THAN);
$c->addAscendingOrderByColumn(CartPeer::ITEM_NAME);
$this->next = CartPeer::doSelectOne($c);
Now, this works fine if the item's identifiers are in ascending order, but usually this is not the case.
How can I modify this code so it selects the item immediately after the current $item in the list of records returned instead of selecting one with the next ascending numerical ID?
Example:
Record: 0 | ItemID: 5
Record: 1 | ItemID: 2
Record: 2 | ItemID: 7 <-- $item
Record: 3 | ItemID: 4 <-- I want this to be $next
Record: 4 | ItemID: 9
I don't actually use Symfony, but if you're using an even remotely recent version of Propel with it then you have access to the paginate() method which may be a lot better in the end for you.
$pager = CartQuery::create()
->filterByCategory($category)
->orderBy(CartPeer::ITEM_NAME)
->paginate($pageToLoad, $resultsPerPage);
foreach($pager as $result) {
// do something with the record
}
if ($pager->haveToPaginate()) {
// build some paging items using PropelModelPager methods:
if (!$pager->isFirstPage()) {
echo "<a href='?page=".$pager->getPreviousPage()."'>Previous</a>";
}
if (!$pager->isLastPage()) {
echo "<a href='?page=".$pager->getNextPage()."'>Next</a>";
}
}
If you really want to do it your way, you may want to eliminate the restriction by ItemId entirely and simply add an offset along with your limit:
// This will be however many results have already been shown (page size?)
$offset = 10;
$c = new Criteria();
$c->add(CartPeer::CATEGORY, $category);
$c->addAscendingOrderByColumn(CartPeer::ITEM_NAME);
$c->setOffset($offset);
$this->next = CartPeer::doSelectOne($c);

Google analytics api. To sort result while in the loop

i need help with google analytics gapi class with php. (http://code.google.com/p/gapi-google-analytics-php-interface)
I want to output how many times each item in catalog was viewed. The page for the item generates with id for example:
/item.php?id=1
/item.php?id=2
ect.
So everything goes right with my code until i want to order by the most viewed item, since i am using loop, to generate random filters:
$filter = "pagePath == /item.php?id=".$i++."";
I am not able to use sort in gapi "requestReportData".
With the code shown below everyting outputs right, but i don't know how to sort everything so it will shown results from the most viewed item till least.
The code:
$ga = new gapi(ga_email,ga_password);
$dimensions = array('pagePath');
$metrics = array('pageviews');
$termFrom = 2011-06-01;
$termUntil = 2011-06-30;
echo '<strong>ITEMS VIEW STATISTIC</strong><br />';
for ( $i='1'; $i<'20';)
{
$filter = "pagePath == /item.php?id=".$i++."";
$ga->requestReportData(table_id,$dimensions,$metrics,'-pageviews',$filter, $termFrom, $termUntil);
foreach($ga->getResults() as $result)
{ $j= $i-1; $b=$j-1;
echo $z++.') Items which ID is:'.$j++.' and NAME is: '.$ItemsNamesArray[$b]['item_name'].' was viewed: '.$result->getpageviews() . ' times<br />';
}
}
It outputs:
ITEMS VIEW STATISTIC
1) Items which ID is:1 and NAME is:
Book was viewed: 9 times
2) Items which ID is:2 and NAME is:
Box: 1 times
3) Items which ID is:3 and NAME is:
Table: 3 times
4) Items which ID is:4 and NAME is:
House: 27 times
I want it to output:
ITEMS VIEW STATISTIC
1) Items which ID is:4 and NAME is:
House was viewed: 27 times
2) Items which ID is:1 and NAME is:
Book was viewed: 9 times
3) Items which ID is:3 and NAME is:
Table was viewed: 3 times
4) Items which ID is:2 and NAME is:
Box was viewed: 1 times
You can use regular expressions for filters to get all your twenty items at once and have Google Analytics sort them:
$ga = new gapi(ga_email,ga_password);
$dimensions = array('pagePath');
$metrics = array('pageviews');
$termFrom = '2011-06-01';
$termUntil = '2011-06-30';
$filter = 'pagePath=~/item\.php\?id=[0-9]*' // Matches all item URLs
$sort = '-pageviews'; // Sorted by desc. pageview count
$maxResults = 20; // First 20 entries
$ga->requestReportData(table_id, $dimensions, $metrics, $sort, $filter, $termFrom, $termUntil, 1, $maxResults);
foreach($ga->getResults as $i => $result){
// Do your magic for each item
}
This is untested, the regular expression in the filter should match correctly, though.
I assumed you want the twenty most-viewed item URLs.

Categories