Codeigniter Select and (conditional) Update Query - php

I am using Codeigniter 3, PHP and MySQL.
I'm trying to select a record from a MySQL database, and depending on the result run an update query.
If result = 0, update.
If result = 1, do nothing.
My code so far is;
public function addData($itemId) {
$gDescription = 'test';
$gPreviewLink = 'test';
$gThumbnail = 'test';
$gPageCount = 'test';
$this->db->select('g_data');
$this->db->from('item');
$this->db->where('item_id', $itemId);
$query = $this->db->get();
$result = $query->result();
// var_dump($result) returns array(1) { [0]=> object(stdClass)#22 (1) { ["g_data"]=> string(1) "0" } }
$data = array(
'item_description' => $gDescription,
'item_preview_link' => $gPreviewLink,
'item_thumbnail' => $gThumbnail,
'item_pageCount' => $gPageCount,
'g_data' => '1',
'g_data_timestamp' => 'NOW()'
);
// if result = 0 update
if($result == '0') {
$this->db->where('item_id',$itemId);
$this->db->update('item', $data);
}
}
Is there any reason the data won't update in my database? I'm not receiving any error messages.
Any help would be appreciated.

$query->result() returns an array of objects where each object is a row from the table. (As you can see in the var_dump in your comments)
Without other changes your conditional should be
if($result->g_data == '0') { ...
That said, you should have checked earlier in the method that the database atually returned results. Also, you don't need more than one row so don't use result() use 'row()' instead
...
$query = $this->db->get();
// The following will set $result to the value of "g_data" if there
// are rows and to "0" if there are none.
$result = $query->num_rows() > 0 ? $query->row()->g_data: '0';
...
If you do the above then the conditional can remain as you have it coded
if($result == '0') {...

Executing the SELECT query means making an unnecessary extra trip to the database. Just build your 0 criteria into your UPDATE query -- if it is not satisfied, then no rows will be affected.
Code:
$data = [
'item_description' => $gDescription,
'item_preview_link' => $gPreviewLink,
'item_thumbnail' => $gThumbnail,
'item_pageCount' => $gPageCount,
'g_data' => '1'
];
$this->db->where([
'item_id' => $itemId,
'g_data' => 0
]);
$this->db->set('g_data_timestamp', 'NOW()', false);
$this->db->update('item', $data);
// return (bool)$this->db->affected_rows();
All done in a single query execution. I also took the liberty of demonstrating how to pass a MySQL function as a value using set()'s third parameter.

Related

Tinyint field not being set

I am trying to set the value of a tinyint field to 1, 2, or 3, but it's not being set. I am pretty new at mySQL, so I am probably making a mistake somewhere, but I can't see it.
I called the function and all the other fields are being set, just not tinyint, which keeps showing as 0.
$this->db->update('jobattachment', ['redline' => $tid], ['id' => $attachmentid], ['editing' => '2']);
I have tried removing the quotes around the 2 and also setting a variable and doing ['editing'] => $editingLevel, but nothing works.
Code for update:
public function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
{
// Combine any cached components with the current statements
$this->_merge_cache();
if ($set !== NULL)
{
$this->set($set);
}
if ($this->_validate_update($table) === FALSE)
{
return FALSE;
}
if ($where !== NULL)
{
$this->where($where);
}
if ( ! empty($limit))
{
$this->limit($limit);
}
$sql = $this->_update($this->qb_from[0], $this->qb_set);
$this->_reset_write();
return $this->query($sql);
}
This is the limit code:
public function limit($value, $offset = 0)
{
is_null($value) OR $this->qb_limit = (int) $value;
empty($offset) OR $this->qb_offset = (int) $offset;
return $this;
}
Your update() function takes 4 parameters, the last of which is an optional limit. When you call it, you are passing 4 parameters, but the last one is an array (['editing' => '2']). My guess is $limit is supposed to be an integer, so your code might generate something like ... LIMIT 5.
So it looks like there is something wrong with how you are passing parameters.
Right now, here's how the variables are set up by the parameters passed to update():
$table = jobattachment
$set = ['redline' => $tid]
$where = ['id' => $attachmentid]
$limit = ['editing' => '2']
My guess is that all the last 3 are supposed to be in $set - you are passing in 3 column names, each with a new value to save.
Again, we can't see your actual set() code, but probably it expects an array of key/value pairs. So you would call update() like this (re-formatted to make it clear that you are passing just 2 parameters, vs 4 previously)
$this->db->update('jobattachment', [
['redline' => $tid],
['id' => $attachmentid],
['editing' => '2']
]);
Now $set is a multi-dimensional array of data to save.

How to get bindings with datatype using Laravel 5.*

i'm trying to make a subquery something like
SELECT COUNT (*) as total_count FROM ($sql) as count_table
here the method:
public function getTotal($query = null)
{
if (is_null($query)) {
return $this->total;
}
$sql = $query->toSql();
$bindings = $query->getBindings();
foreach ($bindings as $binding) {
$bind = gettype($binding) === '' ? "'" . $binding . "'" : $binding; //is not working as expected
$sql = preg_replace('/\?/', $bind, $sql, 1);
}
dd($sql);
$sql = str_replace('\\', '\\\\', $sql);
$total = \DB::connection('sqlsrv')->select(\DB::raw("select count(*) as total_count from ($sql) as count_table"));
return $total[0]->total_count;
}
the problem is when i preg_replace all ? in the sql query i get only the values without the datatype.
my getBindings():
array:14 [▼
0 => 0
1 => "D"
2 => 0
3 => 0
4 => "CZ"
5 => "00000"
6 => "15000"
7 => "D"
8 => 0
9 => 0
10 => 0
11 => "AT"
12 => "0000"
13 => "2000"
]
in this array i have some integers and strings and i would like to bind exact the same datatypes.
i have tried to check the strings with gettype() but this is not working.
In Laravel 5.6.12, the fromSub() function was added to the query builder that does what you're trying to do.
Untested, but I think your function would look something like:
public function getTotal($query = null)
{
if (is_null($query)) {
return $this->total;
}
return \DB::connection('sqlsrv')
->selectRaw('count(*) as total_count')
->fromSub($query)
->value('total_count');
}
If you're not on 5.6.12 yet, your specific query could be handled wholly using the selectRaw statement, which takes bindings as the second parameter. In this case, your function would look something like:
public function getTotal($query = null)
{
if (is_null($query)) {
return $this->total;
}
return \DB::connection('sqlsrv')
->selectRaw('count(*) as total_count from ('.$query->toSql().') as count_table', $query->getBindings())
->value('total_count');
}
Note: if you haven't seen it before, the value() function executes the query, takes the first row, and then gets the value of the specified column from that first row. Just a little cleaner than using get() or first() and then accessing the property.

fetchAll Only returns one row, but counts all? Symfony / Doctrine

I am trying to return an array result from a query - but I'm only getting the first row back.
The count returns 5 (which is the number of the rows that matches the query) - what am I missing in order to display those?
public function getFailType($email)
{
$q = $this->getEntityManager()->getConnection()->createQueryBuilder();
$q->select('dnc.comments, count(dnc.reason) as total')
->from(MAUTIC_TABLE_PREFIX.'lead_donotcontact', 'dnc')
->where('dnc.channel_id = :channelId')
->groupBy('dnc.comments')
->setParameter('channelId', $email);
$results = $q->execute()->fetchAll();
$count = count($results);
$dnc = isset($results) ? $results[0] : null;
if ($dnc === null) {
return false;
}
return [
'count' => $count,
'total' => $dnc['total'],
'comments' => $dnc['comments'],
];
}
Returns the following:
$printout->getFailType($objectId)['count'] = 5
$printout->getFailType($objectId)['total'] = 20
$printout->getFailType($objectId)['comments'] = Contact unsubscribed via email

code igniter - how to update the database if a query result returns rows

I am constructing a query in codeigniter. If the conditions are met, I want to update the appropriate row in the database, and if they are not, I want to insert a new row. This is my code:
$query = $this->db->get_where('extra_examples', array('question' => $data['question'],'tag' => $data['tag'] ));
if ($query->num_rows() > 0){
$this->db->update('extra_examples', $data);
return ($this->db->affected_rows() > 0);
} else {
$this->db->insert('extra_examples', $data);
return $this->db->insert_id();
}
The insert works fine, and the update works if there is only one row in the entire database, but the update seems to change all rows in the database if there are more than one rows. I want it to change only the row where question = data['question'] and tag = data['tag].
What am I doing wrong?
I think this line has the issue:
$this->db->update('extra_examples', $data);
This line simply updates table with values $data. So, whenever condition is true, this will get executed and update all the rows. Try to put some condition on $data, so that only selected rows get affected.
What you can do is :
$data = array(
// put array data
);
$this->db->where('id', $id); // check where to put
$this->db->update('mytable', $data);
$query = $this->db->get_where('extra_examples', array('question' => $data['question'],'tag' => $data['tag'] ));
if ($query->num_rows() > 0){
$this->db->where(array('question' => $data['question'],'tag' => $data['tag'] ))
$this->db->update('extra_examples', $data);
return ($this->db->affected_rows() > 0);
} else {
$this->db->insert('extra_examples', $data);
return $this->db->insert_id();
}

Nested query in codeigniter

there are somethings wrong at
$this->db->where("Mark_ID,(SELECT Mark_ID FROM mark WHERE Course_ID=$Course_ID && Matric_No=$Matric_No)");
in my model?any suggestion idea?thank you.
function update_record($Course_ID,$Matric_No)
{
if($Course_ID && $Matric_No != NULL)
{
$data = array(
//'Course_ID' => $this->input->post('Course_ID'),
'Matric_No' => $this->input->post('Matric_No'),
'Student_Name' => $this->input->post('Student_Name'),
'Result_Mark_1' => $this->input->post('Result_Mark_1'),
'Result_Mark_2' => $this->input->post('Result_Mark_2'),
'Result_Mark_3' => $this->input->post('Result_Mark_3'),
'Result_Mark_4' => $this->input->post('Result_Mark_4'),
'Result_Mark_5' => $this->input->post('Result_Mark_5')
);
$this->db->where("Mark_ID,(SELECT Mark_ID FROM mark WHERE Course_ID=$Course_ID && Matric_No=$Matric_No)");
$this->db->update('mark', $data);
}
}
You need to use IN() clause
$subquery="SELECT Mark_ID FROM mark WHERE Course_ID=$Course_ID && Matric_No=$Matric_No";
$this->db->where("Mark_ID IN($subquery)",null,FALSE);
But you are using subquery from same table to update you will face the error of
you can't specify target table in update query
For this you need to give new alias to your subquery like
$subquery="SELECT t.Mark_ID FROM(
SELECT Mark_ID
FROM mark
WHERE Course_ID=$Course_ID && Matric_No=$Matric_No
) t ";
$this->db->where("Mark_ID IN($subquery)",null,FALSE);
I think you can use below code for get your result.
$this->db->select("Mark_id");
$this->db->where("Course_ID",$Course_ID);
$get_id = $this->db->get($this->tbl_user)->row();
after getting mark id simply pass it to below query.
$this->db->where('Mark_id', $get_id->Mark_id);
$this->db->update($this->tbl_user,$data);
I suggest you to make your life easier by forgetting about nested queries. If you still want to use nested query, answer posted above is correct. You need to use IN
function update_record($Course_ID,$Matric_No)
{
if($Course_ID && $Matric_No != NULL)
{
$data = array(
//'Course_ID' => $this->input->post('Course_ID'),
'Matric_No' => $this->input->post('Matric_No'),
'Student_Name' => $this->input->post('Student_Name'),
'Result_Mark_1' => $this->input->post('Result_Mark_1'),
'Result_Mark_2' => $this->input->post('Result_Mark_2'),
'Result_Mark_3' => $this->input->post('Result_Mark_3'),
'Result_Mark_4' => $this->input->post('Result_Mark_4'),
'Result_Mark_5' => $this->input->post('Result_Mark_5')
);
// pre update query
$this->db->select('Mark_id');
$this->db->where('Course_ID', $Course_ID);
$this->db->where('Matric_No', $Matric_No);
$tmp_result = $this->db->get();
$result = $tmp_result->row();
$mark_id = $result->Mark_id;
//updation
$this->db->where("Mark_ID",$mark_id);
$this->db->update('mark', $data);
}
}

Categories