Updating multiple records in database using Codeigniter - php

Am trying to update multiple records in the database but my case I have a column total, which I want to update to different values. I haven't tried much here but hope I could get a clue on how to go about this.
My controller
public function update_record()
{
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
if ($this->some_model->batch_data('records', $total, $id) == true) {
echo "yes";
} else {
echo "no";
}
}
The Model
public function batch_data($table, $data, $where)
{
$this->db->where_in('id',$where);
$this->db->set('total',$data);
$this->db->update($table);
return true;
}
I have not tested this yet but currently looking for a more and efficient way of doing this.

If you still want to update multiple records using the update_batch method, you could first assign the id and total as key-value arrays, then use the update_batch method.
Controller :
public function update_record()
{
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
$update_data = [];
foreach ($id as $key => $value) {
$update_data[] = [
'id' => $value,
'total' => $total[$key]
];
}
if ($this->some_model->batch_data('records', $update_data) == true) {
echo "yes";
} else {
echo "no";
}
}
Model :
public function batch_data($table, $data)
{
$this->db->update_batch($table, $data, 'id'); // this will set the id column as the condition field
return true;
}
Output :
// preview query output :
// UPDATE `records`
// SET
// `total` =
// CASE
// WHEN `id` = '19821' THEN 8
// WHEN `id` = '19923' THEN 118
// WHEN `id` = '19966' THEN 90
// WHEN `id` = '19967' THEN 100
// ELSE `total`
// END
// WHERE `id` IN ('19821', '19923', '19966', '19967')

As per my comment. This is a method that combines the array in to key/value pairs and updates them 1x1 wrapped in a transaction (so if one query fails nothing changes).
This is the method I would personally use as I don't like update_batchs internal workings (cases).
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
$combined = array_combine($id, $total);
if (count($combined) > 0) {
$this->db->trans_start();
foreach ($combined as $id => $total) {
$this->db->set('total', $total);
$this->db->where('id', $id);
$this->db->update('sometable');
}
$this->db->trans_complete();
return $this->db->trans_status();
}
return true;

Try this, Only for single where condition
Controller:
public function update_record()
{
$tableName = "records";
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
$update_data = [];
foreach ($id as $key => $value) {
$update_data[] = [
'id' => $value,
'total' => $total[$key]
];
}
$whereKey = 'id';
$this->$this->some_model->batch_data($tableName, $updateData, $whereKey);
}
Model:
public function batch_data($tableName, $updateData, $whereKey)
{
$this->db->update_batch($tableName, $updateData, $whereKey);
}

Related

MVC Query doesn't fetch all records from the database

The DB stores several accounts: [winnie, winnie9, winnie10], however the query only returns one record when I fetch the data. What would be the solution?
Model method:
protected function getApprovedUsers($login) {
$sql = "SELECT `email`, `login`, `name`, `reg_date`, `pass`, `role` FROM `approved` WHERE `login` LIKE ?";
$stmt = $this->connect()->prepare($sql);
$stmt->execute([$login]);
if($users = $stmt->fetchAll())
return $users;
return null;
}
Controller call to the Model:
public function getCertainApprovedUser($login) {
$users = $this->getApprovedUsers($login);
if(is_array($users) || is_object($users)) {
foreach ($users as $user) {
return array("email"=>$user["email"], "login"=>$user["login"], "pass"=> $user["pass"],
"name"=> $user["name"], "reg_date"=> $user["reg_date"], "role"=> $user["role"]);
}
}
else {
throw new Exception("Nothing to fetch");
}
}
}
Processing the data so that LIKE statement would work properly (%%):
$record = $userContr->getCertainApprovedUser("%$login%");
$someJSON = array(
[
"login"=>"{$record['login']}",
"email"=>"{$record['email']}",
"name"=>"{$record['name']}",
"reg_date"=>"{$record['reg_date']}"
]
);
$newJSON = json_encode($someJSON);
echo $newJSON;
in the method getCertainApprovedUser(), you are returning a value in the foreach. This breaks immediatly the loop at the first iteration.
Changes your loop to something like :
$result = []; // initialize an empty array
foreach ($users as $user) {
// add a user to that array
$result[] = array("email"=>$user["email"], "login"=>$user["login"], "pass"=> $user["pass"], "name"=> $user["name"], "reg_date"=> $user["reg_date"], "role"=> $user["role"]);
}
// return the array containing the users
return $result;
And then, to build your json, apply the same logic :
$someJSON = [];
foreach ($record as $user)
{
$someJSON[] = [
"login"=>$user['login'],
"email"=>$user['email'],
"name"=>$user['name'],
"reg_date"=>$user['reg_date']
];
}

how to break function array in rows?

I have this php function in codeigniter where it fetches the data from my database:
function fetch_data()
{
$data = $this->projectionchart_model->make_query();
$array = array();
foreach($data as $row)
{
$array[] = $row;
}
$output = array(
'current' => intval($_POST["current"]),
'rowCount' => 10,
'total' => intval($this->projectionchart_model->count_all_data()),
'rows' => $array
);
echo json_encode($output);
}
I want to use the number_format function to some of columns and right now it's building everything in an array. How could I remove the array and list the data individually as variables so I can apply a function to some of them and then output them?
Thank you
Edit: explaining in more detail
This function fetch_data() calls the make_query() function stored in the projectionchart_model file which contains the following:
function make_query()
{
if(isset($_POST["rowCount"]))
{
$this->records_per_page = $_POST["rowCount"];
}
else
{
$this->records_per_page = 10;
}
if(isset($_POST["current"]))
{
$this->current_page_number = $_POST["current"];
}
$this->start_from = ($this->current_page_number - 1) * $this->records_per_page;
$this->db->select("*");
$this->db->from("projection_chart");
if(!empty($_POST["searchPhrase"]))
{
$this->db->like('ae', $_POST["searchPhrase"]);
$this->db->or_like('client', $_POST["searchPhrase"]);
$this->db->or_like('product', $_POST["searchPhrase"]);
$this->db->or_like('week_of', $_POST["searchPhrase"]);
$this->db->or_like('month', $_POST["searchPhrase"]);
$this->db->or_like('type', $_POST["searchPhrase"]);
}
if(isset($_POST["sort"]) && is_array($_POST["sort"]))
{
foreach($_POST["sort"] as $key => $value)
{
$this->db->order_by($key, $value);
}
}
else
{
$this->db->order_by('id', 'DESC');
}
if($this->records_per_page != -1)
{
$this->db->limit($this->records_per_page, $this->start_from);
}
$query = $this->db->get();
return $query->result_array();
}
So the output currently is this:
I want to format the Planned Spend, Cleared and Total Commission with the number_format php function but right now it's all in an array.
How could I accomplish this?

how to implode and insert values into db in codeigniter?

How to implode and insert values into the database in CodeIgniter?
I am creating multiple choice quiz script using CodeIgniter framework. I want to store user results like this:
id userid q_id answer_id time_taken
1 1 1,2,3,4,5 2,3,4,5,3 4,5,7,6,7
in my controller:
public function insert_result()
{
$this->load->model('quiz_models');
$user_id=$this->input->post('user_id');
$qq_id=$this->input->post('questionid');
$answer_id=$this->input->post('AnswerID');
$time_taken=$this->input->post('timetaken');
$question_no=$this->input->post('question_no');
$bd = "$question_no";
switch ($bd) {
case"1":
$data=array('user_id'=>$user_id,
'q_id'=>$qq_id,
'answer_id'=>$answer_id,
'time_taken'=>$time_taken);
$this->quiz_models->insert_result($data);
break;
case"2":
quiz_test();
break;
case"3":
quiz_test();
break;
case"4":
quiz_test();
break;
case"5":
quiz_test();
$this->session->unset_userdata('lastids');
break;
default:
echo "something is wrong";
}
}
public function quiz_test()
{
$this->load->model('quiz_models');
$quiz=$this->quiz_models->quiz_test();
foreach($quiz as $row){
$qid=$row->q_id;
$ans=$row->answer_id;
$time=$row->time_taken;
$a = array("$qq_id","$qid");
$b = array("$answer_id","$ans");
$c = array("$time_taken","$time");
$comma = implode(",",$a);
$comma1 = implode(",",$b);
$comma2 = implode(",",$c);
$data=array('q_id'=>$comma,
'answer_id'=>$comma1,
'time_taken'=>$comma2);
$this->quiz_model->update_result($data);
}
}
}
and Model:
function insert_result($data)
{
$this->dbb->insert('results',$data);
$sectio=$this->db->insert_id();
$this->session->set_userdata('lastids',$sectio);
}
function quiz_test()
{
$ses_id = $this->session->userdata('lastids');
$sql = "SELECT q_id, answer_id, time_taken FROM results WHERE id='$ses_id'";
$query = $this->dbb->query($sql);
$result = $query->result();
return $result;
}
function update_result($data){
$ses_id = $this->session->userdata('lastids');
$this->db->where('id',$ses_id);
$this->db->update('results',$data);
}
when i run it nothing happened,not showing any error where do i mistake?
pls help me what am i doing wrong
First of all - i think you've a major problem in your DB structure
Normalize your Data
You should prevent to store your information in the table like that.
It should be possible to normalize your data properly. If you dont know
how to do that the following link could be interesting:
Normalization in MYSQL
However a possible solution would be to structure your data:
In order to do that - create a save Method in your Model to split between update and insert - this model could look like
class Quiz_Models
{
private $arrPostData;
public function save($arrPostData = false)
{
$this->arrPostData = (!$arrPostData) ? $this->input->post() : $arrPostData;
$id = $this->session->userdata("lastids");
if ($id)
{
$query = $this->db
->select("*")
->from("results")
->where("id",$id)
->get();
if ($query->num_rows() == 1)
{
$this->update($query->row(0));
}
else return false;
}
else
{
$this->insert();
}
if ($this->arrPostData['question_no'] == 10) $this->session->unset_userdata("lastids");
}
private function update($objData)
{
$objCollection = new Quiz_Collection();
$objCollection->userId = $objData->userid;
$objCollection->id = $objData->id;
$arrData = explode($objData->q_id);
foreach($arrData AS $key => $quizId)
{
$objQuiz = new stdClass();
$objQuiz->q_id = $quizId;
$objQuiz->answer_id = explode($objData->answer_id)[$key];
$objQuiz->time_taken = explode($objData->answer_id)[$key];
$objCollection->append($objQuiz);
}
$objQuizFromPost = new stdClass();
$objQuizFromPost->q_id = $this->arrPostData["questionid"];
$objQuizFromPost->answer_id = $this->arrPostData['AnswerID'];
$objQuizFromPost->time_taken = $this->arrPostData['timetaken'];
$objCollection->addQuizFromPost($objQuizFromPost);
$this->db
->where("id",$objCollection->id)
->update("results",$objCollection->getDbData());
}
private function insert()
{
$objCollection = new Quiz_Collection();
$objCollection->userId = $this->arrPostData['user_id'];
$objQuizFromPost = new stdClass();
$objQuizFromPost->q_id = $this->arrPostData["questionid"];
$objQuizFromPost->answer_id = $this->arrPostData['AnswerID'];
$objQuizFromPost->time_taken = $this->arrPostData['timetaken'];
$objCollection->addQuizFromPost($objQuizFromPost);
$this->db->insert("results",$objCollection->getDbData());
$this->session->set_userdata("lastids", $this->db->insert_id());
}
}
as an addition you need a Collection Object (put this below your model)
class Quiz_Collection extends Array_Object
{
public $userId = 0;
public $id = 0;
public function addQuizFromPost($objQuiz)
{
if (intval($objQuiz->q_id) > 0)
{
foreach($this AS $key => $obj)
{
if ($obj->q_id == $objQuiz->q_id)
{
$this->offsetSet($key, $objQuiz);
return true;
}
}
$this->append($objQuiz);
return true;
}
return false;
}
public function sortQuizData($objA, $objB)
{
if ($objA->q_id == $objB->q_id) return 0;
return ($objA->q_id < $objB->q_id) ? -1 : 1;
}
public function getDbData()
{
$this->uasort(array($this,"sortQuizData"));
$arrData = $this->getArrayCopy();
$arrDbData = [
"userid" => $this->userId,
"q_id" => implode(array_map(function($obj){ return $obj->q_id;},$arrData),","),
"answer_id" => implode(array_map(function($obj){ return $obj->answer_id;},$arrData),","),
"time_taken" => implode(array_map(function($obj){ return $obj->time_taken;},$arrData),","),
];
return $arrDbData;
}
}
pS: this is just an instruction how you can do that in a proper way. Pls study this code. If you still don't understand whats going on, feel free to ask.

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
}

how to discover last id after delete and set new autoincrement mysql data line

i have a question, im deleting data from mysql by id in 2 tables, but on sales table i want to keep the same id after delete. And when i add a new sale keep the last deleted id.
For example, i have sale id nr 100 on delete and on create a new sale the id will be 101.
What i want is to keep 100 if i delete.
this is my model based on codeigniter:
public function getAllInvoiceItems($sale_id)
{
$q = $this->db->get_where('sale_items', array('sale_id' => $sale_id));
if($q->num_rows() > 0) {
foreach (($q->result()) as $row) {
$data[] = $row;
}
return $data;
}
}
public function getInvoiceByID($id)
{
$q = $this->db->get_where('sales', array('id' => $id), 1);
if( $q->num_rows() > 0 )
{
return $q->row();
}
return FALSE;
}
public function deleteInvoice($id)
{
$inv = $this->getInvoiceByID($id);
$warehouse_id = $inv->warehouse_id;
$items = $this->getAllInvoiceItems($id);
foreach($items as $item) {
$product_id = $item->product_id;
$item_details = $this->getProductQuantity($product_id, $warehouse_id);
$pr_quantity = $item_details['quantity'];
$inv_quantity = $item->quantity;
$new_quantity = $pr_quantity + $inv_quantity;
$this->updateQuantity($product_id, $warehouse_id, $new_quantity);
}
if($this->db->delete('sale_items', array('sale_id' => $id)) && $this->db->delete('sales', array('id' => $id))) {
return true;
}
return FALSE;
}

Categories