Cannot update all columns using looping - php

i have some data to update, and I want to update all the rows in my table using that data. So I tried to get all my data, then loop through my data and set the rows using new data, but it only works for the first row. How do I update all my rows?
this is my code, i using activerecord to update:
$replaceid = $_POST['pid'];
$product = ProductModel::find()->where(['createdby'=>$uid])->orWhere(['modifiedby'=>$uid])->all();
if(isset($product)) {
foreach ($product as $p) {
$p->createdby = $replaceid;
$p->modifiedby = $replaceid;
$p->update(false);
}
}
this is only update createdby but for modifiedby still same.. what's wrong here?

This can be done completely on the database-side, therefore negating any issues you might have in PHP
ProductModel::query()->where(['createdby'=>$uid])->orWhere(['modifiedby'=>$uid])->update(['createdby' => $replaceid, 'modifiedby'=> $replaceid]);

Related

Optimize Query on Models

I have a problem with displaying a bunch of data from my database. Getting data from many tables.
My query before was getting all the data in one query then I had managed to find a way on how to optimize it but I'm not satisfied.
foreach($query->result_array() as $row ){
$drreturn = $this->getDRReturnAmount($row["idno"],$date1);
$return_amount[] = $drreturn->return_amount;
$checkDRServiceNoPayment = $this->checkDRServiceNoPayment($row["idno"],$date1,$date2);
if($checkDRServiceNoPayment->num_rows() > 0) {
$minus_item_amount[] = 0;
$getProductPurchase = $this->getProductPurchase($row["idno"],$date1,$date2);
$minus_item_amount[] = $getProductPurchase->amount;
}
}
btw I'm using datatable. what I did before was I didn't use an array and I put the model functions inside the foreach but it seems that nothing happened even tho I used array.

How to get all inserted records ids in codeigniter?

How to get all inserted records ids in codeigniter ?? I am using insert_batch function in for inserting multiple records but codeigniter $this->db->insert_id() function returns only last record id.
//But i need all inserted records ids. If any one has idea please help.
//In codeigniter this function returns only last inserted record id.
function insertStudent(){
$data[] = array('firstname'=>'firstname1','lastname'=>'lastname1');
$data[] = array('firstname'=>'firstname2','lastname'=>'lastname2');
$result = $this->db->insert_batch( 'student', $data );
return $this->db->insert_id();
}
This can be achieved by using first id and count.
Get count of data that you are inserting. (e.g. 2 in your example)
Get first insert id by $this->db->insert_id() (e.g. say 30)
Now get last insert recorded id by = first record id - (count - 1) (e.g. 30 + (2-1) = 31)
Now you can query to get data between id's 30 and 31.
If you absolutely must have the insert_id for each inserted row, the simplest most failproof way would be to loop multiple inserts rather than making one big fat insert.
Looping through multiple inserts will allow you to get all insert_ids. It will also allow you to not loose all the data if one of the rows fails inserting and the database rejects them all because of that.
My best solution is to update the DB_driver.php.
From
public function is_write_type($sql)
{
return (bool) (preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
}
To:
public function is_write_type($sql)
{
return (bool) (preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql) && !preg_match('/ RETURNING /i', $sql));
}
The really safest way is:
Add a column code in your table.
Create a code before batch inserting [id session user]-[current time stamp] should be enough.
Batch insert all elements with that code into code column
Query a Select searching for that code, you will have all elements inserted at batch insert
Here is an efficient method:
Since your records have result ID's, I'm going to assume they also auto-increment.
If this is the case, you do this and still use insert_batch.
Here is what you do:
You take a count of the items you are inserting:
$count = count($data);
Run your batch insert:
$this->db->insert_batch('student', $data);
Get the first inserted ID of your batch:
$first_id = $this->db->insert_id();
Add the count (minus 1) to your insert ID to get the last records ID.
$last_id = $first_id + ($count-1);
There you go! You now have first and last ID's of your inserted records, and by extension, everything else in between.
function insertStudent(){
$data[] = array('firstname'=>'firstname1','lastname'=>'lastname1');
$data[] = array('firstname'=>'firstname2','lastname'=>'lastname2');
$result = $this->db->insert_batch( 'student', $data );
$a= $this->db->get('student');
$data = $a->result_array();
echo($data[0]['id']);
}
Hope So this will help you.

CodeIgniter MVC and Looping through a MySQL table

I'm trying to create a iterate through a row in a MySQL table in one of my CodeIgniter projects, how could I "loop" through the table? Is it just a simple for loop like in other languages?
EDIT:
The answer is as followed:
$query = $this->db->get('mytable'); // select table "mytable" from database
foreach ($query->result() as $row) { // loop thru table and access each row's field
// by using $row->fieldname
}
Maybe something like this
//$this->db->limit(10); // Optional if you want to limit, read about it
$result = $this->db->get('server'); //return all rows
foreach ($result as $row) {
$row->status = 'inactive'; // change value of status attribute or whatever
$this->db->update('server', $row)
}
Or maybe use $this->db->update_batch(); to update a stack of rows at one time.
I encourage you to read the CI database class documentation too.
Another suggestion, is to do all the business logic inside a model instead of a controller. But it's a matter of personal preference maybe.

Updating database according to check-boxes checked

I've the following table layout in my database with some data.
I'm taking input by check-boxes so user can select all applicable accident road conditions and it to database. I would say it is okay if you're adding a new record you just loop through the checkboexs checked and insert them in DB
The first information is now saved in the database, now user decided to change the road conditions for any reasons user came back and change it the to the following.
Now my question, how should I update my table. The first thing that came into my mind was to delete the record that were already there and insert the new one's.
My real issue here is, assume user have choose the 3 items before but changed it two or one then how would i delete the those are not checked you know what I'm saying. Below is some code snippets that I've been trying.
$accidentRoadConditions = AccidentRoadConditions::findAccidentRoadConditions($acc_det_id);
$wc_array = [];
while ($roadConditions = $accidentRoadConditions ->fetch(PDO::FETCH_OBJ)) {
$wc_array[] = $roadConditions ->rc_id;
}
Above I'm selecting all the road conditions that is already stored in the database.
if (isset($_POST['rta_ad_rc'])) {
foreach ($_POST['rta_ad_rc'] as $rc_id) {
//AccidentRoadConditions::save(array(null, $ad_lsid, $rc_id));
// $tmprory = AccidentRoadConditions::findByADAndRCIds($acc_det_id, $rc_id);
// if(!$tmprory){
// AccidentRoadConditions::save(array(null, $acc_det_id, $rc_id));
// }
if(in_array($rc_id, $wc_array)){
$errors[] = "in array <br />";
unset($wc_array[0]);
}
}
}
So my question is how to update values in database according to what was checked by user and deleting those which were unchecked which were checked before. Getting bit complicated so simply how to update database according to above mention scenario.
Any Idea?
I think you need to do the following
Store the selected checks in an array
Check in the database if any of those are already saved or not
if yes, skipped them otherwise add them into an array
$old_rc_array = [];
$new_rc_array = [];
while ($roadConditions = $accidentRoadConditions->fetch(PDO::FETCH_OBJ)) {
$old_rc_array[] = $roadConditions->rc_id;
}
if (isset($_POST['rta_ad_rc'])) {
foreach ($_POST['rta_ad_rc'] as $rc_id) {
if(in_array($rc_id, $old_rc_array)){
unset($old_rc_array[array_search($rc_id, $old_rc_array)]);
}else{
$new_rc_array[] = $rc_id;
}
}
}
foreach ($old_rc_array as $rc_to_delete) {
AccidentRoadConditions::deleteByADIdAndRCId($hidden_acc_det_id, $rc_to_delete);
}
foreach ($new_rc_array as $rc_to_insert) {
AccidentRoadConditions::save(array(null, $hidden_acc_det_id, $rc_to_insert));
}
I think this is what you should do.
Create composite unique constraint on ad_id and rc_id
Delete all the rows not in the selected checkbox ids.
Try to insert all the rows but user INSERT IGNORE. This will insert the record if it does not exist or it will just ignore it. As you are using some framework see how you can do that.
If you can not then just wrap it using try/catch and ignore if the error is related to constraint violation.
This way You don't need to check if the values exist and also there will not be any unnecessary inserts.

Using PHP with a MySQL db, how can I select everything from a row if i dont know what the columns are?

I have a table but I dont know what the columns are except for 1 column. There is only 1 permanent data value for each row, the rest of the columns are added and removed elsewhere. This isnt a problem for the query, i just do:
SELECT * FROM table
but for the php function bind_result() i need to give it variables for each column, which i do not know.
I think that once I have the columns in an array, I can do anther query and use call_user_func_array to bind the result to the array.
This seems like it would come up a lot so im wondering is there a standard way of doing this?
Couldn't you just do:
$result = mysql_query("SELECT * FROM table");
while ($row = mysql_fetch_assoc($result))
{
foreach ($row as $field => $value)
{
...
}
}
You could do
show columns from table;
And then parse that string to grab your column names.
You can also try the describe command, which is used to list all of the fields in a table and the data format of each field. Usage:
describe TableName;
you can use
$metadata = $prep_statement->result_metadata()
after you executed the statement and then loop through all result fields using something like
while( $field = $metadata->fetch_field() ) { }
the properties of $field are documented here: http://www.php.net/manual/en/mysqli-result.fetch-field.php

Categories