My mission this week has been to create a sales graph for my Drupal 6, Ubercart and Ubercart Marketplace installation.
I settled on the charts_graphs module and decided to use the Bluff library to graph the data. Although the supported module views_charts allows you to create a wide range of charts, it wasn't able to retrieve the dataset that I needed to graph the sales data. If anyone wants the details of why not, just ask and I'll do my best to elaborate.
So I found an example of the php needed to generate a bluff graph:
<?php
$canvas = charts_graphs_get_graph('bluff');
$canvas->title = "Bluff Chart";
$canvas->type = "line"; // a chart type supported by the charting engine. See further in the doc for the list.
$canvas->y_legend = "Y Legend";
$canvas->colour = '#D54C78';
$canvas->theme = 'keynote';
$canvas->series = array(
'Some Value' => array(9,6,7,9,5,7,6,9,7),
'Page Views' => array(6,7,9,5,7,6,9,7,3),
);
$canvas->x_labels = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
$out = $canvas->get_chart();
return $out;
}
?>
This code then generates this graph...
The next stage of course is to get the data from a MySQL query into the graph. This is where I'm outside of my comfort zone because I haven't really done anything previously with PHP.
So after some digging around I found this post with an example that gave me something to work with. I then used views to help get me started with the SQL. I'm so close I can taste it but this last issue has had me snagged and I can't think of any more searches to do... I'm sure you can relate with that feeling :)
So this is the code I've developed so far:
<?php
global $user;
$uname = $user->uid;
$sql = "SELECT DATE_FORMAT((FROM_UNIXTIME(uc_orders.created) + INTERVAL 3600 SECOND), '%d/%m/%Y') as OrderDate, round(SUM(uc_order_products.cost * uc_order_products.qty),2) AS SellerCommission,
round(SUM(uc_order_products.price * uc_order_products.qty),2) AS CustomerPrice
FROM uc_order_products
LEFT JOIN node node_uc_order_products ON uc_order_products.nid = node_uc_order_products.nid
LEFT JOIN uc_orders uc_orders ON uc_order_products.order_id = uc_orders.order_id
INNER JOIN users node_uc_order_products__users ON node_uc_order_products.uid = node_uc_order_products__users.uid
WHERE (node_uc_order_products__users.uid = $uname )
AND (uc_orders.created >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL DAYOFMONTH(CURDATE())-1 DAY)))
AND (uc_orders.order_status in ('payment_received', 'completed'))
GROUP BY DAY(FROM_UNIXTIME(uc_orders.created))
ORDER BY MONTH(FROM_UNIXTIME(uc_orders.created)) desc, DAY(FROM_UNIXTIME(uc_orders.created)) desc
LIMIT 31";
$result = db_query($sql,$uname);
while($row = db_fetch_array($result))
{
$sellercommission[] = (int) $row[SellerCommission];
$customerprice[] = (int) $row[CustomerPrice];
$orderdate[] = (string) $row[OrderDate];
}
$canvas = charts_graphs_get_graph('bluff');
$canvas->title = "Volume of sales";
$canvas->type = "line"; // a chart type supported by the charting engine. See further in the doc for the list.
$canvas->y_legend = "Y Legend";
$canvas->colour = '#FFFFFF';
$canvas->width = '450';
$canvas->height = '300';
$canvas->theme = '';
$canvas->series = array(
'Seller Commission' =>array_values($sellercommission),
'Customer price' =>array_values($customerprice),
);
$canvas->x_labels = array_values($orderdate);
$out = $canvas->get_chart();
return $out;
?>
This code generates a perfect graph, all but the x-axis only displays "//" for the dates...
When I run the query on the database this is the result set that I get. Obviously I replace the placeholder with a UID:
09/09/2013 1328.13 1897.32
07/09/2013 455.00 650.00
What I can't work out is the type for "$orderdate[] ...." that I should be using. I've tried varchar, int (displays 0), date (breaks it and displays nothing), datetime (breaks it again)... Or perhaps I am retrieving the wrong data as OrderDate in the SQL. Any ideas would be greatly appreciated...
So I finally worked it out (complete fluke and don't understand the difference) but this is the final code that worked:
<?php
global $user;
$uname = $user->uid;
$sql = "SELECT concat(DAY(FROM_UNIXTIME(uc_orders.created)),'/',MONTH(FROM_UNIXTIME(uc_orders.created)),'/', YEAR(FROM_UNIXTIME(uc_orders.created))) as OrderDate, round(SUM(uc_order_products.cost * uc_order_products.qty),2) AS SellerCommission,
round(SUM(uc_order_products.price * uc_order_products.qty),2) AS CustomerPrice
FROM uc_order_products
LEFT JOIN node node_uc_order_products ON uc_order_products.nid = node_uc_order_products.nid
LEFT JOIN uc_orders uc_orders ON uc_order_products.order_id = uc_orders.order_id
INNER JOIN users node_uc_order_products__users ON node_uc_order_products.uid = node_uc_order_products__users.uid
WHERE (node_uc_order_products__users.uid = $uname )
AND (uc_orders.created >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL DAYOFMONTH(CURDATE())-1 DAY)))
AND (uc_orders.order_status in ('payment_received', 'completed'))
GROUP BY DAY(FROM_UNIXTIME(uc_orders.created))
ORDER BY MONTH(FROM_UNIXTIME(uc_orders.created)) desc, DAY(FROM_UNIXTIME(uc_orders.created)) asc
LIMIT 31";
$result = db_query($sql,$uname);
while($row = db_fetch_array($result))
{
$sellercommission[] = (int) $row[SellerCommission];
$customerprice[] = (int) $row[CustomerPrice];
$orderdate[] = (string) $row[OrderDate];
}
$canvas = charts_graphs_get_graph('bluff');
$canvas->title = "Volume of sales";
$canvas->type = "line"; // a chart type supported by the charting engine. See further in the doc for the list.
$canvas->y_legend = "Y Legend";
$canvas->colour = '#FFFFFF';
$canvas->width = '450';
$canvas->height = '300';
$canvas->theme = '';
$canvas->series = array(
'Seller Commission' =>array_values($sellercommission),
'Customer price' =>array_values($customerprice),
);
$canvas->x_labels = array_values($orderdate);
$out = $canvas->get_chart();
return $out;
?>
I basically changed the way I asked for the "OrderDate" in the SQL.... Also corrected a few other minor details...
Related
I'm pulling multiple rows from a table and formatting them to this standard: 3 Swords, 5 Daggers, etc.
Well When I try to put that data into a json Array, It's only pulling the last result as this [{"weapons":"You Used: 3 Rusty Dagger's, "}] Which it should say: [{"weapons":"You Used: 3 Rusty Dagger's, 2 Swords"}]
Here's The Query I'm currently using, Which will show perfectly inside of the while loop:
$get_weapons = mysql_query("SELECT
O.player_id,
O.item_id,
O.name,
O.attack,
O.defense,
O.type,
O.owned,
(SELECT
sum(owned) FROM items_owned
WHERE owned <= O.owned AND player_id=$id) 'RunningTotal'
FROM items_owned O
HAVING RunningTotal <= $mob_avail
ORDER BY attack DESC");
// Get Weapon Info
while($weapon = mysql_fetch_array($get_weapons)){
$weapon_id = $weapon['item_id'];
$weapon_name = $weapon['name'];
$weapon_attack = $weapon['attack'];
$weapon_defense = $weapon['defense'];
$weapon_owned = $weapon['owned'];
// Formatting Weapons Message
$weapon_message = 'You Used: '.$weapon_owned.' '.$weapon_name.'\'s, ';
}
$data[] = array('weapons'=>$weapon_message);
echo json_encode($data);
I understand that the $data array is outside of the while loop, But I'm only needing a total of one arrays, so I'm kind of stuck on what to do to fix this issue. Any help would be awesome
You should add one static variable before append the results into the message.
Here is the reference answer:
$get_weapons = mysql_query("SELECT O.player_id, O.item_id, O.name, O.attack, O.defense, O.type, O.owned, (
SELECT sum(owned) FROM items_owned WHERE owned <= O.owned AND player_id=$id) 'RunningTotal' FROM items_owned O HAVING RunningTotal <= $mob_avail ORDER BY attack DESC");
// Initialize the message
$weapon_message = 'You Used: ';
// Get Weapon Info
while($weapon = mysql_fetch_array($get_weapons)){
$weapon_id = $weapon['item_id'];
$weapon_name = $weapon['name'];
$weapon_attack = $weapon['attack'];
$weapon_defense = $weapon['defense'];
$weapon_owned = $weapon['owned'];
// Formatting Weapons Message
$weapon_message = $weapon_message.$weapon_owned.' '.$weapon_name.'\'s, ';
}
$data[] = array('weapons'=>$weapon_message);
echo json_encode($data);
apologize firstly for my questionable coding in php/mysql however this is all self taught (possibly not best practice)
All my code seems to work , however when the results are written to the page any $dxcall that is not in the $qrzdata database gets filled with the last result all other data displays fine. I have tried changing the like $dxcall to = $dxcall. I have also tried combining the fetch arrays too incase my issues was there too. But clearly my code does not know how to handle where there is not data match in the qrzdata database and to move on.
$frqry is the main data, all the other mysql_query's be it the $squares and $qrzdata are matching what comes from $frqry. Hope this makes sense !!
Here is my code
$frqry = mysql_query("select * from spots where freq between '69900' and '70300' ORDER BY datetime desc limit 30");
While ($r0 = mysql_fetch_array($frqry))
{
$freq = $r0["freq"];
$dxcall = $r0["dxcall"];
$datetime = $r0["datetime"];
$comments = $r0["comments"];
$spotter = $r0["spotter"];
$dt = date('d-m-y H:i ', $datetime);
$qra = $r0["loc"];
$squares = mysql_query("select * from squares where callsign like '$dxcall' limit 1");
while ($r1 = mysql_fetch_array($squares))
{
$qra = $r1["loc"];
}
$qrzdata = mysql_query("select * from qrzdata where callsign = '".$dxcall."' limit 1");
While ($r2 = mysql_fetch_array($qrzdata))
{
$country = $r2["country"];
$firstname = $r2["firstname"];
$city = $r2["city"];
}
Any help is greatly appreciated. Thank you.
You need to learn about the power of the JOIN ;)
Your whole code could be rewritten in one single query :
disclaimer: not tested, but you certainly get the idea
SELECT * FROM spots
JOIN squares ON (squares.callsign = spots.dxcall) -- this comes in stead of your first inner loop
JOIN qrzdata ON (qrzdata.callsign = spots.dxcall) -- this is your second loop
WHERE freq BETWEEN 69900 AND 70300 -- remove quotes, you are dealing with integers, not strings (hopefully)
You have to reset your vars!
While ($r0 = mysql_fetch_array($frqry))
{
$qra = '';
$country = '';
$firstname = '';
$city = '';
or you will allways get the last value
I'm trying to accomplish the following situation:
$mysql_query = "
SELECT *
FROM st_users
WHERE
`user_comp_supervisor_id` = '$team_supervisor' AND
`user_exempt_from_goals` = '0'
ORDER BY 'calculate_progress_percent()' ASC
";
I know that I can't accomplish ordering by a function in a MySQL statement, but I'm trying to figure out how to take all the returned records, and then order them in order of highest to lowest from a php function result. Any ideas would be greatly appreciated; I've been trying to wrap my head around this for a few hours now... :-(
function diy_calc_progress_percent($user_id,$period_id,$period_week_number)
{
$this->user_id = $user_id;
$this->period_id = $period_id;
$this->period_week_number = $period_week_number;
if ($this->period_week_number == 1)
{
$this->week_id = mysql_result( mysql_query(" SELECT `period_week_one` FROM `st_comp_periods` WHERE `period_id` = '$this->period_id' "),0 );
}
else if ($this->period_week_number == 2)
{
$this->week_id = mysql_result( mysql_query(" SELECT `period_week_two` FROM `st_comp_periods` WHERE `period_id` = '$this->period_id' "),0 );
}
else
{
echo "Week number not valid.";
exit();
}
$this->week_start_date = mysql_result( mysql_query(" SELECT `week_start_date` FROM `st_comp_weeks` WHERE `week_id` = '$this->week_id' "),0 );
$this->week_end_date = mysql_result( mysql_query(" SELECT `week_end_date` FROM `st_comp_weeks` WHERE `week_id` = '$this->week_id' "),0 );
$this->user_department = $this->user_info($this->user_id,"user_comp_department_id");
$this->user_week_diy_goal = mysql_result( mysql_query(" SELECT `goal_diy_department` FROM `st_comp_department_goals` WHERE `goal_department_id` = '$this->user_department' AND `goal_week_id` = '$this->week_id' "),0 );
$this->calc_totals_result = mysql_query("SELECT SUM(record_total_diy_revenue) AS user_week_total FROM `st_entered_records` WHERE `record_user_id` = '$this->user_id' AND `record_date` BETWEEN '$this->week_start_date' AND '$this->week_end_date'");
$this->calc_totals_row = mysql_fetch_assoc($this->calc_totals_result);
$this->user_week_total = $this->calc_totals_row['user_week_total'];
$this->user_week_one_percent = ($this->user_week_total / $this->user_week_diy_goal) * 100;
$this->user_week_one_percent = number_format( (float)$this->user_week_one_percent, 2, '.', '' );
return $this->user_week_one_percent;
}
You probably will have to do some array juggling.
First get all your entries FROM st_users into a first array (mysql_query)
Then you could run through that array, and for each entry you do the calculate_progress_percent() and build up a second array in which you could add the additional info ("user_progress_percent").
After this you can sort the new array ba your new info ("user_progress_percent").
And here is some quick and dirty code-suggestions – code is however not tested… of course…:)
First:
$mysql_query = "SELECT * FROM st_users
WHERE `user_comp_supervisor_id`='$team_supervisor' AND
`user_exempt_from_goals` = '0'";
Then something like this:
$i = 0;
while($tmp = mysql_fetch_array($mysql_query)) {
$my_second_array[$i]['user_id'] = $tmp['user_id'];
$user_id = $my_second_array[$i]['user_id'];
diy_calc_progress_percent($user_id,$period_id,$period_week_number);
$my_second_array[$i]['user_result'] = $diy_calc_progress_percent_result;
$i++;
}
And then sorting that second array should be possible as described here:
Sort Multi-dimensional Array by Value
…hope this helps at some point…
What I am trying to do is show a small widget on the home page to let a user know when their membership expires. Here is my current code
$subExpire = Engine_Api::_()->getDbtable('subscriptions', 'payment');
$db2 = $streamTable->getAdapter();
$stmt2 = $db2->query("select * from engine4_payment_subscriptions where `user_id`='$user_id'");
$arr2 = $stmt2->fetch();
if ($arr2['expiration_date']=="NULL")
{
$exp = "NEVER";
}
echo $exp;
I think the major issue has to do with Engine_Api::_()->getDbtable('subscriptions', 'payment');
Ultimately once it comes back with a date I would like to calculate how many days left in the membership from the current date.
Any suggestions?
PS, $user_id is defined and does return a numeric value
One more thing, the actual table name is engine4_payment_subscriptions
That´s a strange way of making the query in social engine, try this:
$table = Engine_Api::_()->getDbtable('subscriptions', 'payment');
$select = $table->select()->where('user_id = ?', $user_id);
$arr2 = $table->fetchAll($select);
if ($arr2['expiration_date']=="NULL")
{
$exp = "NEVER";
}
echo $exp;
i have this file C:\\xampp\htdocs\exact\sample_pie.php that contains a graph. here's the code:
<?php
include("phpgraphlib.php");
include("phpgraphlib_pie.php");
include("connection.php");
$graph=new PHPGraphLibPie(400,200);
$link = mysql_connect('localhost', 'root', '');
mysql_select_db('exact');
$querypa = "SELECT COUNT(nature) FROM approved WHERE nature='Parade'";
$resultpa = mysql_query($querypa);
$printpa = mysql_result($resultpa,0);
$querycs = "SELECT COUNT(nature) FROM approved WHERE nature='Community Service'";
$resultcs = mysql_query($querycs);
$printcs = mysql_result($resultcs,0);
$queryga = "SELECT COUNT(nature) FROM approved WHERE nature='General Assembly'";
$resultga = mysql_query($queryga);
$printga = mysql_result($resultga,0);
$querypl = "SELECT COUNT(nature) FROM approved WHERE nature='Play/Showcase/Socio-Cultural Show/Film Showing'";
$resultpl = mysql_query($querypl);
$printpl = mysql_result($resultpl,0);
$queryco = "SELECT COUNT(nature) FROM approved WHERE nature='Competition/Sportsfest'";
$resultco = mysql_query($queryco);
$printco = mysql_result($resultco,0);
$queryfr = "SELECT COUNT(nature) FROM approved WHERE nature='Fund Raising'";
$resultfr = mysql_query($queryfr);
$printfr = mysql_result($resultfr,0);
$queryse = "SELECT COUNT(nature) FROM approved WHERE nature='Seminar/Convention/Conference/Training'";
$resultse = mysql_query($queryse);
$printse = mysql_result($resultse,0);
$totalAct=$printpa+$printga+$printpl+$printcs+$printco+$printfr+$printse;
$avepa=($printpa/$totalAct)*100;
$avecs=($printcs/$totalAct)*100;
$avega=($printga/$totalAct)*100;
$avepl=($printpl/$totalAct)*100;
$aveco=($printco/$totalAct)*100;
$avefr=($printfr/$totalAct)*100;
$avese=($printse/$totalAct)*100;
$pa=number_format($avepa,2);
$cs=number_format($avecs,2);
$ga=number_format($avega,2);
$pl=number_format($avepl,2);
$co=number_format($aveco,2);
$fr=number_format($avefr,2);
$se=number_format($avese,2);
$data=array("Parade"=>$pa, "General Assembly"=>$ga, "Play/Showcase/Socio-Cultural Show/Film Showing"=>$pl, "Community Service"=>$cs, "Competition/Sportsfest"=>$co, "Fund Raising"=>$fr, "Seminar/Convention/Conference/Training"=>$se);
$graph->addData($data);
$graph->setTitle("Total Activities per Nature of Activity");
$graph->setPrecision(2);
$graph->setLabelTextColor("0,0,0");
$graph->setLegendTextColor("0,0,0");
$graph->setGradient("210,245,255","pastel_purple");
$graph->createGraph();
?>
how can i get the graph as a .jpg through php script? i tried this file_get_contents("C:\\xampp\htdocs\exact\sample_pie.php");
but it only outputs this:
$pa, "General Assembly"=>$ga, "Play/Showcase/Socio-Cultural Show/Film Showing"=>$pl, "Community Service"=>$cs, "Competition/Sportsfest"=>$co, "Fund Raising"=>$fr, "Seminar/Convention/Conference/Training"=>$se); $graph->addData($data); $graph->setTitle("Total Activities per Nature of Activity"); $graph->setPrecision(2); $graph->setLabelTextColor("0,0,0"); $graph->setLegendTextColor("0,0,0"); $graph->setGradient("210,245,255","pastel_purple"); $graph->createGraph(); ?>
please help me. thanks.
Using file_get_contents() like that is only going to retrieve the script itself. That text is what the file contains and that's what file_get_contents() does; exactly what it says on the tin.
Try looking at the documentation for PHPGraphLib or in the source code failing that. There should be some sort of save method you can call instead of createGraph() or maybe you can just pass a filename parameter to createGraph().
On a sidenote, I should mention that your script is a lot more complicated than it should be. Everything between mysql_select_db() and $graph->addData() could be rewritten into something like this:
$data = array(
'Parade' => 0,
'Community Service' => 0,
'General Assembly' => 0,
'Play/Showcase/Socio-Cultural Show/Film Showing' => 0,
'Competition/Sportsfest' => 0,
'Fund Raising' => 0,
'Seminar/Convention/Conference/Training' => 0
);
$sql = "SELECT nature, COUNT(*) AS cnt
FROM approved
WHERE nature IN ('" . implode("','", array_keys($data)) . "')
GROUP BY nature";
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$data[$row['nature']] = $row['cnt'];
}
$totalAct = array_sum($data);
foreach ($data as $nature => &$value)
{
$value = number_format(100 * $value / $totalAct, 2);
}
For the rest, consult the documentation of your graph library as Ollie Saunders suggested.
<img src="/exact/sample_pie.php" />
You may want to use header() to set the appropriate Content-type from within sample_pie.php.