First of all I'm new to the framework. Check the query I'm trying to transcript using the CI database object.
$where = "(".$this->tbl.".invoiceNumber = '".substr($searchFor,3)."'
OR EXISTS (SELECT 1 FROM op_orders_products WHERE idProduct = ".(is_numeric(substr($searchFor,3)) ? substr($searchFor,3) : '-1')."
AND idOrder = ".$this->tbl.".id)
)";
Should I do a separate subquery? Would like to make it all in one.
This is how I started. I wanna make sure the variables are binded and not passed as strings as in the original query.
$this->db->group_start()
->where($this->tbl.".invoiceNumber", substr($searchFor, 3))
->or_group_start()
// I'm missing this EXISTS select subquery
->group_end()
->group_end()
Thanks a lot for the help.
There is no EXISTS equivalent in Codeigniter's Query Builder Class that I'm aware of. So I'd just write it like this:
$this->db->group_start()
->where($where)
->group_end()
see documentation here
binding:
with CodeIgniter you can bind variables to your query like this:
$sql = "SELECT * FROM table WHERE a= ? AND b= ?";
$query = $this->db->query($sql, array($a,$b));
This binds variables $a and $b to the corresponding positions (?) inside the query string.
escaping
$this->db->escape()
this function escapes string data and adds single quotes around it.
Related
hy I'm new in laravel 4 and I have found code like this
$sub = Abc::where(..)->groupBy(..); // Eloquent Builder instance
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery())
->count();
my quetion is
1. what the meaning mergeBindings($sub->getQuery()) and give me example for using mergeBindings
assume your first query is like this:
$sub = Abc::where('type', 1)->groupBy(..);
then when we convert it to sql:
$sub->toSql();
this will return query string some thing like this:
SELECT * FROM abc where abc.type = ? GROUp BY ...
you can see the "?" as the type value which will be binded (replaced by 1) when the PDO executes that query string
So when we use that sub query in another query as you do in
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery())
->count();
you have converted the first sub query to sql string, BUT the second query does not know any thing about your first sub query binding which in this example the value 1
so we need to merge the binding from the first sub query into the last query
so that the last query when executes it will know the value 1 and binds it to the
where clause in replace of "?", and your final executed query will be something like this
(SELECT count(*) from abc where type = 1 GROUP BY ...) as sub
and thats it the use of mergeBindings() method
i hope this makes things clear for your question.
thanks,
After years of reading it's time to ask first question :)
My problem is that after migrating the code from mySQLi to PDO we have got a problem as it seems PDO adds the apostrophes to the query.
PHP code goes like that:
$sort = $_GET['sort']; << table column name (mySQL VARCHAR only columns)
....
$query = 'SELECT * FROM table WHERE xxx > 0';
$query .= ' ORDER BY :sort ASC ;';
$qry_result= $db->prepare($query);
$qry_result->execute(array(':sort'=>$sort));
mysqli version went smoothly but now queries (mysql log file) looks like this:
SELECT * FROM table where xxx > 0 ORDER BY 'SORT_VAR_VALUE' ASC;
^ 2 problems ^
So the table is NOT sorted, as sort order (from mySQL point of view) is wrong.
phpinfo() does not get any results for search on "magic" nor "quotes" btw.
Any idea ??
The placeholders in PDO statements are for values only. If you want to add actual SQL to the query you need to do it another way.
First, you should sanitize $sort and surround it with backticks in the query.
$sort = preg_replace('/^[a-zA-Z0-9_]/', '', $sort);
Then you could double quote the query string and PHP will replace $sort with it's value for you:
$query = "SELECT * FROM table WHERE xxx > 0 ORDER BY `$sort` ASC";
Or you could replace it with preg_replace like so:
$query = 'SELECT * FROM table WHERE xxx > 0 ORDER BY `:sort` ASC';
$query = preg_replace('/:sort/', $sort, $query, 1);
I would use the preg_replace method because it allows you to reuse the query if you assign the results from preg_replace to another variable instead of overwriting the original variable.
by default pdo binds values as strings.
To fix this you will want to check that the column is actually a valid name and then add it to the query, you can do it the following way:
function validName($string){
return !preg_match("/[^a-zA-Z0-9\$_\.]/i", $string);
}
if(validName($sort)){
$db->prepare("SELECT * FROM table where xxx > 0 ORDER BY $sort ASC");
}
With PDO it's not possible to bind other things that variables in the WHERE statement. So you have to hard code the names of the columns you order by.
See How do I set ORDER BY params using prepared PDO statement?
or Can PHP PDO Statements accept the table or column name as parameter? for further explanations.
I'm trying to count all of the rows from an item list where the id matches a user input. I am switching all of my code from mysql to PDO as I have learned it is much better.
The code below is what I found to work in my situation.
$id = '0';
$sql="SELECT count(*) FROM item_list WHERE item_id = $id";
$data=$connMembers->query($sql)->fetchcolumn();
echo $data;
However, It is not safe for a live site due to sql injections.
I want to know how can I change it to work whare it sanatizes the user input.
I would prefer using a prepare and execute functions so the variables are kept seperately.
So is there something I can do?
This is where you start binding parameters. I prefer to do it using ? and one array for inputs.
Assuming $connMembers is your PDO object:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ?";
$input=array($id); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
To add more variables to your sql, just add another ? to the query and add the variable to your input.
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ? AND item_name=?";
$input=array($id, $name); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
OR you can use bindParam:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = :itemID";
$statement=$connMembers->prepare($sql);
$statement->bindParam(':itemID', $id);
/*Here I am binding parameters instead of passing
an array parameter to the execute() */
$statement->execute();
$data=$statement->fetchObject();
var_dump($data);
I have a following query
$this->db->set('registerStep', $param)
->where('id = ',$user_id)
->update($this->table_name);
Above Query is producing below sql code. even though I'm supplying only one where condition.
UPDATE `users` SET `registerStep` = 2 WHERE `id` = 33 AND `id` = '165'
I think active record is using some cached where condition, is there any way I can free where condition.
I tried using
$this->db->flush_cache();
But it's not helping.
http://codeigniter.com/user_guide/database/active_record.html#update
->where('id = ',$user_id)
is incorrect.
->where('id',$user_id)
is correct.
Your query is fully correct. But I believe what you used a $this->db->where() before current query. Use the following code and you will see all the previously defined "where" statements:
print_r($this->db->ar_where);
$this->db->set('registerStep', $param)
->where('id = ',$user_id)
->update($this->table_name);
I'm trying to retrieve a count of all unique values in a field.
Example SQL:
SELECT count(distinct accessid) FROM (`accesslog`) WHERE record = '123'
How can I do this kind of query inside of CodeIgniter?
I know I can use $this->db->query(), and write my own SQL query, but I have other requirements that I want to use $this->db->where() for. If I use ->query() though I have to write the whole query myself.
$record = '123';
$this->db->distinct();
$this->db->select('accessid');
$this->db->where('record', $record);
$query = $this->db->get('accesslog');
then
$query->num_rows();
should go a long way towards it.
try it out with the following code
function fun1()
{
$this->db->select('count(DISTINCT(accessid))');
$this->db->from('accesslog');
$this->db->where('record =','123');
$query=$this->db->get();
return $query->num_rows();
}
You can also run ->select('DISTINCT `field`', FALSE) and the second parameter tells CI not to escape the first argument.
With the second parameter as false, the output would be SELECT DISTINCT `field` instead of without the second parameter, SELECT `DISTINCT` `field`
Since the count is the intended final value, in your query pass
$this->db->distinct();
$this->db->select('accessid');
$this->db->where('record', $record);
$query = $this->db->get()->result_array();
return count($query);
The count the retuned value
Simple but usefull way:
$query = $this->db->distinct()->select('order_id')->get_where('tbl_order_details', array('seller_id' => $seller_id));
return $query;