ZF2 custom db query using SUM - php

Can someone give me a hint what I am doing wrong?
public function getPaymentSumByTypeAndProject($project_id,$type) {
$type = (int) $type;
$project_id = (int) $project_id;
$rowset = $this->tableGateway->select(array('total_amount' => new Expression('SUM(payment.amount)')))->where(array('type' => $type, 'project_id' => $project_id));
$row = $rowset->toArray();
if (!$row) {
throw new \Exception("Busted :/");
}
return $rowset;
}
I want to make the same query:
SELECT SUM(amount) FROM payment WHERE type='$type' AND project_id ='$project_id';
Edit:
I made small progress, i have figured out how to sum whole column
public function getPaymentSumByTypeAndProject($project_id, $type) {
$type = (int) $type;
$project_id = (int) $project_id;
$resultSet = $this->tableGateway->select(function (Select $select) {
$select->columns(array(new \Zend\Db\Sql\Expression('SUM(amount) as amount')))->where('type="0"');
});
return $resultSet;
Maybe someone could help me to figure out how to add condition: "WHERE type='$type' AND project_id='$project_id'" ?

I know this is an old question, but I came across it and figured I'd throw in my two cents:
public function getPaymentSumByTypeAndProject($project_id, $type) {
// This TableGateway is already setup for the table 'payment'
// So we can skip the ->from('payment')
$sql = $this->tableGateway->getSql();
// We'll follow the regular order of SQL ( SELECT, FROM, WHERE )
// So the query is easier to understand
$select = $sql->select()
// Use an alias as key in the columns array instead of
// in the expression itself
->columns(array('amount' => new \Zend\Db\Sql\Expression('SUM(amount)')))
// Type casting the variables as integer can take place
// here ( it even tells us a little about the table structure )
->where(array('type' => (int)$type, 'project_id' => (int)$project_id));
// Use selectWith as a shortcut to get a resultSet for the above select
return $this->tableGateway->selectWith($select);
}
Also, an adapter can be retrieved from a table gateway like this:
$adapter = $this->tableGateway->getAdapter();
But you don't really need it anymore when you select using the above mentioned method.

Ok now this is working, tell me is this how it;s should be done?
public function getPaymentSumByTypeAndProject($project_id, $type) {
$type = (int) $type;
$project_id = (int) $project_id;
$adapter = $this->tableGateway->adapter;
$sql = new Sql($adapter);
$select = $sql->select();
$select->from('payment');
$select->where(array('type'=>$type,'project_id'=>$project_id));
$select->columns(array(new \Zend\Db\Sql\Expression('SUM(amount) as amount')));
$selectString = $sql->getSqlStringForSqlObject($select);
$resultSet = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE);
return $resultSet;
}

use This one
$select = $this->getSql()->select()
->columns(array('amount' => new \Zend\Db\Sql\Expression('SUM(amount)')))
->where("type ='$type'")
->where("project_id ='$project_id'");
$resultSet = $this->selectWith($select);
$row = $resultSet->current();
// echo $select->getSqlString();die; //check query use this line
if(!$row){
return False;
}
return $row->amount;

try to make like that instead of (int) $type
intval($type);
and
intval($project_id);
and in your sql
change your variables to
'".$type."'
AND
'".$project_id."'

Related

returned array being assigned as null to variable in PHP

I have a function in PHP which calls another class function in order to assign a value to one of it's variables $related.
The original function requiring the value uses the requestACLForAccess() function to add a specific variable filter to the $headers variable:
The listRecords function:
public function listRecords($api)
{
header("Access-Control-Allow-Origin: *");
if ($this->authenticationProcedure() !== false) {
$headers = apache_request_headers();
$access = $this->requestACLForAccess($headers['module'], $headers['oauth_token'], $_SERVER['REQUEST_METHOD']);
if(gettype($access) == "array"){
$headers['filter'][0][$access[1]]['$equals'] = $access[2];
}
$listObject = new FilterApi();;
return $listObject->filterList($api, $headers);
}
}
The function requestACLForAccess being called :
protected function requestACLForAccess(
$targetModule,
$token,
$req_type,
$getSpecialFlag = false,
$targetId = null
) {
$row = $this->checkTokenValid("token", $token);
if (!empty($row) || $row !== false) {
$related = \Sugarcrm\Sugarcrm\custom\clients\base\CustomACL::checkRelated($row['module'], $targetModule, $row['id'], $req_type, $getSpecialFlag, $targetId);
die(gettype($related)); // For debugging
return $related;
}
else {
return false;
}
}
The function that was called is in another file called customACL.php. Within that function, a certain conditional statement returns an array $arr which should be assigned to the particular variable above. The function being called:
public static function checkRelated($module, $targetModule, $id, $req_type, $getSpecial, $targetId)
{
$bean = \BeanFactory::retrieveBean($module, $id);
if($bean->designation == self::ADMIN_NAME && !(in_array($targetModule, self::RECORD_RELATION_MODULES))){
return self::ACL_ADMIN;
} else{
//first check if a relational table between modules exists
$query = "select table_name from information_schema.tables where table_name like '%{$module}%{$targetModule}%' OR table_name like '%{$targetModule}%{$module}%'";
$result = $GLOBALS['db']->query($query);
$row = $result->fetch_assoc();
if (empty($row)) { //if no table exists
return self::ACL_ADMIN;
} else { //find out table name
$table_name = $row['table_name'];
if ($req_type == 'PUT' || $req_type == 'DELETE' || $req_type == 'GET') { //check if record has relation
$acl_access = self::checkRecordRelated($table_name, $id, $module, $req_type, $targetId, $targetModule);
}
}
}
}
For my specific call, this function then goes to a checkRecordRelated() function within the same file:
protected static function checkRecordRelated($table_name, $id, $module, $req_type, $targetId, $targetModule)
{
//find out module column name in relational table
$query = "select column_name from information_schema.columns where table_name = '$table_name' and column_name like '%{$module}_id%' or column_name like '%{$module}s_id%'";
$result = $GLOBALS['db']->query($query);
$row = $result->fetch_assoc();
if (empty($row)) {//if no column name
return self::ACL_NON_ADMIN;
} else {//return module column name
$column_name = $row['column_name'];
}
if ($req_type == 'GET') {//if special GET request
//find if related records exist in relational table for listing
$findRelatedRecords = "select * from $table_name where $column_name = '$id' and 'deleted' = 0";
$result = $GLOBALS['db']->query($findRelatedRecords);
$row = $result->fetch_array();
if (empty($row)) {//if NON_ADMIN exist
return self::ACL_NON_ADMIN;
} else {//if exist
$arr = array(self::ACL_ADMIN, $table_name, $id);
return $arr;
}
}
}
}
Up until the point where I have defined the variable $arr, checking with gettype() returns an array and printing the variable gives me (as expected) a complete array with the values I've added. However, as soon as the value is returned to the original function and assigned to the variable $related, the array somehow becomes NULL and the gettype() also returns NULL.
Update: I've added the missing functions to make it clearer, I hope it makes sense
Could anyone tell me what naive mistake am I doing here? Why is this happening?
Well this is embarrassing, I forgot to return the $aclaccess variable in the checkrelated() function which is why it was showing null. Adding the return value was the solution.

Need reorder sort_column Yii2

I need to reorder the column sort_order.
It is, select the position where to allocate the category and
recalculate the table.
For example, if I select category 3, insert at next and reorder sort_order.
I tried this code but something is wrong:
public function actionUp($id) {
$model = $this->loadModel($id);
$prev = Category::find()
->andWhere(['<', 'sort_order', $model->sort_order])
->orderBy(['sort_order' => SORT_DESC])
->limit(1)->one();
$current = $model->sort_order;
$model->sort_order = $prev->sort_order;
$prev->sort_order = $current->sort_order;
$model->save();
$prev->save();
return $
this->redirect(['index']);
}
How I can reorder this column?
Thank you for any help.
public function actionUp($id, $newPosition=null) {
$model = Category::findOne($id);
if(!$model)
throw new UserException('We were unable to find a matching record');
$prev = Category::find()
->andWhere(['<', 'sort_order', $model->sort_order])
->orderBy(['sort_order' => SORT_DESC])
->limit(1)->one();
if($prev)
$prevOrder = $prev->sort_order;
else
$prevOrder = 0;
$currentOrder = $model->sort_order;
If($newPosition)
$model->sortOrder = $newPosition;
else
$model->sort_order = $prevOrder;
$prev->sort_order = $currentOrder;
$model->save();
$prev->save();
return $this->redirect(['index']);
}
actionUp and Down work well, thank you very much
And when I'm going to add a new category, how can I indicate the position, based o parent_id?
public function create(CategoryCreateForm $form): Category
{
$channel = Category::create(
$form->parentId,
$form->name,
$form->code,
$form->description
);
$category = $this->categories->get($form->parentId);
$next = Category::find()
->andWhere(['<', 'sort_order', $category->sort_order])
->orderBy(['sort_order' => SORT_DESC])
->limit(1)->one();
if ($next)
$nexOrder = $next->sort_order;
else
$nexOrder = 0;
$currentOrder = $category->parent_id;
if ($newPosition)
$category->parent_id =$newPosition;
else
$category->parent_id = $nexOrder;
$next->sort_order = $currentOrder;
$prev->save();
$this->categories->save($category);
return $category;
}
It does not work this way, what is wrong.
I have this, in the Categoryservice
public function moveUp($id){
$model = $this->categories->get($id);
$prev = Category::find()
->andWhere(['<', 'sort_order', $model->sort_order])
->orderBy(['sort_order' => SORT_DESC])
->limit(1)->one();
if($prev)
$prevOrder = $prev->sort_order;
else
$prevOrder = 0;
$currentOrder = $model->sort_order;
$model->sort_order = $prevOrder;
$prev->sort_order = $currentOrder;
$prev->save();
$this->categories->save($model);
}
You were right, one of the categories did not have sort_order, it was null, and it gave the error.
I have one more question, how can it do the same but, when creating to choose where to position it?

Codeigniter get mysql value

Can someone please guide me how I can fetch mysql row's value for "pk" to the $response variable to be able to allow the script to unfollow users automatically. I have already tried the script and it does unfollow when an pk id is provided but I want to automatically fetch it from mysql to be able to run it. Thank you for any help provided.
These are the methods I tried with no success:
$this->db->select('pk');
$this->model->from(INSTAGRAM_FOLLOW_TB);
$this->db->where("id = '11'");
$query1 = $this->db->get();
$result = $query1->result();
Main ID that only unfollow this ID- created by Mushfik Media,
$response = $i->unfollow($result);
I have also tried
$accounts = $this->model->fetch("*", INSTAGRAM_ACCOUNT_TB, "id = '11'");
$response = $i->unfollow($accounts->pk);
But didn't work. $NEED MYSQL DATA VALUE is where the value is supposed to be echoed but doesn't
case 'unfollow':
try {
$result = $i->getSelfUsersFollowing();
if(!empty($result) && $result->status == "ok" && !empty($result->users)){
$response = $i->unfollow($NEED MYSQL DATA VALUE);
$response = $response->status;
$CI =& get_instance();
$CI->load->model('Schedule_model', 'schedule_model');
$lang = $CI->db->insert(INSTAGRAM_FOLLOW_TB, array(
"pk" => $row->pk,
"name" => $row->username,
"type" => $data->schedule_type,
"uid" => $data->uid,
"account_id" => $data->account,
"account_name" => $data->name,
"created" => NOW
));
}
} catch (Exception $e){
$response = $e->getMessage();
}
break;
Maybe something like this to get your pk:
$query1 = $this->db->select('pk')
->from(INSTAGRAM_FOLLOW_TB)
->where('id', 11)
->get();
if( $query1->num_rows() == 1 ){
$row = $query1->row();
$response = $i->unfollow( $row->pk );
}
Regarding your information that you are trying to use $this when not in object context, because you are in a helper, you need to get the CI super object. So, if you were trying to use $this->db, you would do this:
$CI =& get_instance();
// Now you can use $CI->db
// and anything you would normally
// access via $this in a controller
// or model
OK, finally to show an example of how to order or limit a query:
$query1 = $this->db->select('pk')
->from(INSTAGRAM_FOLLOW_TB)
->where('id', 11)
->order_by('your_timestamp_field', 'ASC') // This would order by timestamp in ascending order
->limit(1) // This would limit to a single row
->get();

Bug in PHP code

Am working on a student portal, below is the code i used for students position but, every user keeps getting 1st position. Every student seems to have 1st position, when they check their results from the front view. Cant seem to figure out where the problem is from in the code
function get_position($student, $class, $session, $term){
$this->db->select('*');
$this->db->from('result');
$this->db->where(array( 'class_id'=>$class, 'Session'=>$session, 'Term'=>$term));
$this->db->order_by('Total', 'asc');
$other_results = $this->db->get()->result_array();
$this->db->select("*");
$this->db->from('result');
$this->db->where(array('class_id'=> $class, 'Session'=>$session, 'Term'=>$term, 'StudentID'=>$student ));
$student_result = $this->db->get()->result_array();
$student_total = $this->get_student_total($student_result);
$position =1;
foreach($other_results as $res){
if($student_total < $res['Total']){
$position++;
}
}
return $position;
}
function get_student_total($result){
$total = 0;
foreach($result as $res){
$total+= $res['Total'];
}
return $total;
}
}
?>
I am assuming that the result table may have many records for a given studentID. Several test scores (Totals) for each student during the term right?
This should do the trick
public function get_position($student, $class, $session, $term)
{
//I like to use db method chaining.
$ranking = $this->db->select('StudentID')
->select_sum('Total', 'sumScore')
->from('result')
->where(array('class_id' => $class, 'Session' => $session, 'Term' => $term))
->group_by('StudentID')
->order_by('sumScore', 'desc')
->get()->result_array();
//The code above retrieves results from a query statement that looks like this:
//SELECT `StudentID`, SUM(`Total`) as sumScore
//FROM `result` where `class_id` = $class and `Session` = $session and `Term` = $term
//GROUP BY `StudentID`
//order by `sumScore` desc
$position = 1;
foreach($ranking as $rank)
{
if($rank['StudentID'] !== $student)
{
++$position;
}
else
{
return $position;
}
}
return NULL; //to indicate studentID was not found
}

Query array on model codeigninter

I am a student who learns CodeIgniter, I have a school assignment about the database, I create a project, and run query in my model just like this.
class Send_model extends CI_Model{
function hello(){ $table = $this->db->query("SELECT * FROM (`tbl1`) LEFT JOIN `tbl2` ON `tbl2`.`id` = `tbl1`.`child_id` LEFT JOIN `tbl3` ON `tbl3`.`id` = `tbl1`.`child_id` ");
foreach($table->result() as $row){
$modbus[]= $row->modbus;
$data []= $row->data;
$alert[]= $row->alert;
};
$param0 = '&'.$modbus[0].'='.$data[0].':'.$alert[0];
$param1 = '&'.$modbus[1].'='.$data[1].':'.$alert[1];
$param2 = '&'.$modbus[2].'='.$data[2].':'.$alert[2];
$param3 = '&'.$modbus[3].'='.$data[3].':'.$alert[3];
$param4 = '&'.$modbus[4].'='.$data[4].':'.$alert[4];
$param5 = '&'.$modbus[5].'='.$data[5].':'.$alert[5];
$param6 = '&'.$modbus[6].'='.$data[6].':'.$alert[6];
$param7 = '&'.$modbus[7].'='.$data[7].':'.$alert[7];
$param8 = '&'.$modbus[8].'='.$data[8].':'.$alert[8];
$param9 = '&'.$modbus[9].'='.$data[9].':'.$alert[9];
$param10 = '&'.$modbus[10].'='.$data[10].':'.$alert[10];
$param11= '&'.$modbus[11].'='.$data[11].':'.$alert[11];
$param12 = '&'.$modbus[12].'='.$data[12].':'.$alert[12];
$param13 = '&'.$modbus[13].'='.$data[13].':'.$alert[13];
$param14 = '&'.$modbus[14].'='.$data[14].':'.$alert[14];
$param15 = '&'.$modbus[15].'='.$data[15].':'.$alert[15];
$param16 = '&'.$modbus[16].'='.$data[16].':'.$alert[16];
$param17 = '&'.$modbus[17].'='.$data[17].':'.$alert[17];
$param18 = '&'.$modbus[18].'='.$data[18].':'.$alert[18];
$sent = $param0.$param1.$param3.$param4.$param5.$param6.$param7.$param8.$param9.$param10.$param11.$param12.$param13.$param13.$param14.$param15.$param16.$param17;
return $sent;
}
my controller just like this
class Send extend CI_Controller{
function data ()
{
$this->load->model('send_model');
$send = $this->model->send_model->hello();
echo $sent;
}
}
i have a problem,if tbl1 add data then i have to write adding code to my script
can anyone help me to simplify this code?
It is because you're hard-coding to send only 19 rows of data by creating 19 $param variables. In a dynamic condition, you may have an empty record-set or hundreds of records. Modify the structure of your foreach loop to the following:
$param = array();
foreach($table->result() as $row){
$param[] = '&'.$row->modbus.'='.$row->data.':'.$row->alert;
}
return $param;
Hope it answers your question.

Categories