Cakephp Minimum value query - php

I have this issue with Cakephp where I can retrieve min value from score field but I cannot seem to get id for the same row using group aswell. Below is my code. What am I doing wrong?
function index() {
$this->Leaderboard->recursive = 0;
$this->set('leaderboards', $this->paginate());
$min = $this->Leaderboard->find('all',
array(
'fields' => array('MIN(Leaderboard.score) as min_score')
));
$minimum = $min[0][0]['min_score'];
pr($min);
echo $minimum;
if (!empty($this->data)) {
$this->Leaderboard->create();
if($this->data['Leaderboard']['score'] > $minimum){
if ($this->Leaderboard->save($this->data)) {
$this->Session->setFlash(__('The leaderboard has been saved', true));
$this->Leaderboard->delete($min[0]['Leaderboard']['id']);
} else {
$this->Session->setFlash(__('The leaderboard could not be saved. Please, try again.', true));
}
} else {
$this->Session->setFlash(__('Score not high enough for leaderboard',true));
}
}
$users = $this->Leaderboard->User->find('list');
$trips = $this->Leaderboard->Trip->find('list');
$this->set(compact('users', 'trips'));
}

U have to use sub-query for getting id for the same row as that of minimum one ..
Query would something like this
SELECT id
FROm Leaderboard
WHERE score IN (
SELECT MIN(score)
FROM Leaderboard
);
and how to use sub-queries in cakephp take a look at http://book.cakephp.org/view/1030/Complex-Find-Conditions
I have done the same task but in other way
$minimum = $this->Leaderboard->find('first',array(
'fields'=>array('MIN(score) as MinimumScore')));
$data = $this->Leaderboard->find('first',array(
'fields'=>array('id'),
'conditions'=>array('score'=>$minimum[0]['MinimumScore'])));
and now u can access id as
$id = $data['Leaderboard']['id'];
Hope this help

You can try something like this. ** Disclaimer -- I didn't test this code, but it's too long to fit in a comment, so...
$min = $this->Leaderboard->find('first', array(
'fields' => array('Leaderboard.id', 'Leaderboard.score'),
'order' => 'Leaderboard.score ASC'
)
);

Related

Sum of Foreach Loop

I'm trying to total a bill balance with a program I'm working on in PHP.
The code I use to pull the pricing is as such.
public function PackagePricing($arg) {
$query = <<<SQL
SELECT packageID
FROM customer_packages
WHERE active = :true
AND customerID = :arg
SQL;
$resource = $this->db->db->prepare( $query );
$resource->execute( array (
":true" => 1,
":arg" => 1,
));
foreach($resource as $row) {
self::GetPricing($row['packageID']);
}
}
public function GetPricing($arg) {
$query = <<<SQL
SELECT price
FROM products
WHERE id = :arg
SQL;
$resource = $this->db->db->prepare( $query );
$resource->execute( array (
":arg" => $arg,
));
$totalBill = 0;
foreach($resource as $row) {
$totalBill+= $row['price'];
}
echo $totalBill;
}
Now by my understanding this should work, but what I'm getting in turn is:
On the right you can see the billing total and rather than totaling out it's giving me each individually.
The error seems quite obvious. Here's your sequence in different words :
Get all packages ID.
Foreach package ID, get the price of the item (only one result is returned)
For that single result, add up all the prices (you only get one). Print it and go back to 2.
What you see is not 2 prices that have been added as strings in some sort of way. You simply prints subsequently 2 different prices. 10 & 30
GetPricing should return a price, and the foreach loop that calls it should make the sum.
$total = 0;
foreach($resource as $row)
{
$total += self::GetPricing($row['packageID']);
}
Hope this helps.

Get the next element in an array (PHP)

I have two models set up for an array. Basically, what I want to achieve is to get the first next entry from the database based on the order ID I have set up.
So, I send the ID 4, I find the entry with the ID 4 which has the order ID 15. Then I want to get the first next item after it, which should have the order ID 16. I tried incrementing with +1 after the order ID, but it just doesn't work.
With my current code I get the same array twice.
function first($id_domain) {
$this->db->select ( '*' );
$this->db->from ( 'domains' );
$this->db->where ( 'id_domain', $id_domain);
$result = $this->db->get ();
return $result->result_array ();
}
function second ($result) {
$this->db->select ( '*' );
$this->db->from ( 'domains' );
$this->db->where ( 'order', $result[0]['order'] + 1 ); //code that should get me the next entry, but doesn't work...
$this->db->where ( 'parent', $result[0]['parent'] );
$result2 = $this->db->get ();
return $result2->result_array ();
}
The problem is not due to your code, but it may be due to the records in the database: either they are non-existing for that specific condition or your matching is not entirely correct.
If you are using CodeIgniter I suggest you to alter your second function to this:
function second($result) {
$whereConds = array(
'order' => intval($result[0]['order'] + 1),
'parent'=> $result[0]['parent']
);
//if you don't have firephp print/echo/var_dump as you normally would
$this->firephp->log($whereConds);
$query = $this->db->get_where('domains', $whereConds);
$this->firephp->log($this->db->last_query());
if ($query->num_rows() <= 0) {
$this->firephp->log('No results');
return array();
} else {
return $query->result_array();
}
}
This way you can track the problem accurately.
Btw, you can also use the $offset parameter in the get_where to get the next id (perhaps just with the parent condition, since you know they are ordered sequentially):
$limit=1;
$offset=intval($result[0]['order'] + 1);//adjust depending on the parent condition below: it can be just an integer such as 2
$whereConds = array(
'parent'=> $result[0]['parent']
);
$query = $this->db->get_where('domains', $whereConds, $limit, $offset);

CakePHP's "saveAll" need over 3 minutes to save?

I am making an application using CakePHP. I made an action which uses saveAll function.
And I thought it works well, because it doesn't need so much data, but it took over 3 minutes to save using saveAll, or other save function.
Does anyone find my mistakes?
phpMyadmin's columns:
id, rank, school_detail_id, total_score, school_name,
(there is about 300~400 data)
public function rank_update(){
$check_scores = $this->ClubScore->find('all', array('fields'=>array('id','total_score')));
$check_scores2 = Set::sort($check_scores, "{n}.ClubScore.total_score","DESC");
$rank_id=0;
$temp_score=0;
$temp = null;
$for_count=0;
foreach ($check_scores2 as $check_score):
if($temp_score != $check_score['ClubScore']['total_score']){
$rank_id++;
$temp_score = $check_score['ClubScore']['total_score'];
// make ranking by score. same score is same ranking.
}
$this->ClubScore->id = $check_score['ClubScore']['id'];
$this->ClubScore->saveField('rank', $rank_id);
endforeach;
}
Divide the query from foreach to simpler approach
get distinct total_score in desc order
$data = $this->ClubScore->find('all', array('fields'=>array('DISTINCT total_score'), 'order' => 'total_score DESC'));
and then simply save the key as rank for each total_score using updateAll and foreach
Thank you very much Abhishek and AgRizzo ,Nunser!!
Now, I've completely solved this problem. It takes only 1 or 2 seconds!!!!!
Here is the source code.
public function rank_update(){
$data = $this->ClubScore->find('all', array('fields'=>array('DISTINCT total_score'), 'order' => 'total_score DESC'));
$check_scores = $this->ClubScore->find('all', array('fields'=>array('id','total_score')));
$check_scores2 = Set::sort($check_scores, "{n}.ClubScore.total_score","DESC");
$ii = 0;
$temp = 0;
foreach($check_scores2 as $scores):
if($data[$ii]['ClubScore']['total_score']
== $scores['ClubScore']['total_score']){
$temp=$ii+1;
}else{
$ii++;
$temp=$ii+1;
}
$update_arr[] = array(
'ClubScore' => array(
'id' => $scores['ClubScore']['id'],
'rank' =>$temp,
)
);
endforeach;
$update_arr = Set::sort($update_arr, "{n}.ClubScore.id","ASC");
var_dump($update_arr);
foreach($update_arr as $update_arrs):
$this->ClubScore->updateAll(
array(
'ClubScore.rank' => $update_arrs['ClubScore']['rank'],
),
array(
'ClubScore.id' => $update_arrs['ClubScore']['id'],
)
);
endforeach;
}
Thank you very much.
Best regards.

How to check records already exist in database when u save new record?

I want to add the new records in table if proudct_id and plan_id is already exist in same row then the error occur otherwise it save the record. I have written following lines of code but no success, if there is any help so please, thanks. I am doing it in cakephp
function admin_product_plan_add(){
$exists = $this->ProductPlan->find('all');
$this->set('exists',$exists);
foreach ($exists as $exists){
$plan_id = $exists['ProductPlan']['plan_id'];
$product_id = $exists['ProductPlan']['product_id'];
}
$conditions = array('ProductPlan.product_id' => $plan_id, 'ProductPlan.plan_id' => $product_id);
$data = $this->ProductPlan->find('all' , array('conditions'=>$conditions));
if (isset($data) && !empty($data))
{
echo '<p>User have already add this product plan!</p>';
}else{
if ($this->ProductPlan->save($this->data)){
$this->Session->setFlash('You have successfully add the product plan');
$this->redirect(array('controller' => 'productplans','action' => 'admin_product_plan_list'));
}
}
}
Use hasAny()
something like:
public function admin_product_plan_add(){
if($this->ProductPlan->hasAny(array("product_id" => $this->data['ProductPlan']['product_id'],'plan_id' => $this->data['ProductPlan']['plan_id']))){
// USER ALREADY HAVE THIS PRODUCTPLAN
} else {
//CREATE NEW PRODUCTPLAN
}
}
or something like that.
Hope this helps
One solution is to use a uniq index over these two rows. So when someone tries do add another row with the same data on these two rows, mysql throws an error and the data is not inserted.

User reporting Library

I would like to build (or find) a php reporting library that I can use to allow my users to report any type of content as bad. Actually, if they could report content as good (which I guess would mean a rating system) that would be even better. So if anyone knows of a library like this I would love to hear about it.
Anyway, this is how I imagine the database working and I would like to know if this sounds correct.
ID - ID of row
USER_ID - ID of the user voting/reporting
ITEM_ID - UNIQUE table row ID of the item reported (post, other user, link, etc...)
TYPE - the name of the table this pertains to (posts, users, links, etc...)
DATE - datetime of report
VALUE - I guess this could be an UP vote or DOWN vote
By including the [TYPE] column I can use this voting system across all content types on my site instead of just one (like forum posts). By storing the user_id I can be sure that only one vote/report is cast per item per user.
Well, I went ahead and built it like I said. Frank was right, it wasn't too hard. Here is the code incase anyone else wants to use it on a MVC that supports AR styled DB calls like CodeIgniter or MicroMVC:
/*
* Multi-table user voting model
*/
class votes extends model {
public static $table = 'votes';
function cast( $user_id = NULL, $item_id = NULL, $type = NULL, $vote = TRUE) {
$where = array(
'user_id' => $user_id,
'item_id' => $item_id,
'type' => $type
);
//Try to fetch this row
$row = $this->db->get_where(self::$table, $where );
//Look for an existing vote row
if( $row && ! empty($row[0]) ) {
//Fetch row
$row = $row[0];
//If they already voted this way... then we're done!
if( $row->vote == $vote) {
return;
}
//Else update the row to the new vote
$row->vote = $vote;
$row->date = convert_time(time());
$this->db->update( self::$table, $row, array('id' => $row->id) );
return;
}
//Else create a new vote for this item
$row = array(
'user_id' => $user_id,
'item_id' => $item_id,
'type' => $type,
'date' => convert_time(time()),
'vote' => $vote,
);
$this->db->insert( self::$table, $row);
}
}

Categories