I'm trying to run a raw SQL query, inside a Controller class, and I'm having trouble to figure out why I can't bind more than one parameter. Take a look at the snippet below:
$sql = "select
u.id,
u.name,
u.email,
r.name as role
from user u
inner join role r on r.id = u.role_id
left join user_group_user ugu on ugu.user_id = u.id and ugu.user_group_id = ".$user_group_id."
where (u.name like :search or u.email like :search or r.name like :search)
and ugu.user_id is null and u.id not in( :notIn )
order by u.name, r.name";
$users = $this->db->query($sql, ['search' => '%'.$search.'%', 'notIn'=>$notInStr ])->fetchAll();
The $notIn variable has a value like 1,2,3. If I do the same thing only with the parameter :search the query works. When I try with both parameters (:search and :notIn) the query returns but the :notIn seems to not have effect in the query. It looks like it is not being bound.
How can I run this query considering both parameters?
Thanks for any help
UPDATE:
The binding is actually working but it is binding the :notIn as a string, so the executed query is .... not in ('1,2,3')
I have solved my problem just making sure that everything is a number and just concatenating in the query: ...u.id not in( ".$notInStr." )
Standard pdo library which phalcon is using and which phalcon db is wrapping doesn't accept array as bound parameter. You would need to use phalcon models.
Make use of Phalcon\Mvc\Model\Query\Builder. There is a inWhere method, that accepts array as parameter.
Remember to never use not filtered data that You get from end-user, like You just did. This makes Yours application vulnerable to SQLInjection attacks.
Related
I tested the code below it works fine on phpmyadmin
SELECT registered_user_tbl.username, follow.follower_id FROM registered_user_tbl
INNER JOIN follow
ON follow.follower_id= 5 and registered_user_tbl.user_id= 5
I now want to implement the array version on my pdo project but it is not working kindly check and review query below
$this->db->select("SELECT registered_user_tbl.username, follow.follower_id FROM registered_user_tbl
INNER JOIN follow
ON follow.follower_id= :fid and registered_user_tbl.user_id= :fid",
(":fid" =>$user));
The 2nd parameter to your select() method should probably be an array so the round brackets are incorrect, for your data parameters.
And you cannot reuse :fid twice in the parameter substitution.
So try this
$this->db->select(
"SELECT registered_user_tbl.username, follow.follower_id
FROM registered_user_tbl
INNER JOIN follow ON follow.follower_id= :fid1
and registered_user_tbl.user_id= :fid2",
[":fid1" =>$user, ":fid2" =>$user]
);
If i give hard coded value inside query it works, but not in case of sub query or column given.
Here is small example of issue i am facing :
Following both query is a type of sub query, like its part of another query, so don't think that where is table 'm' and something else, as it is working already.
So, my query like :
1)
SELECT GROUP_CONCAT(CONCAT(a_u.first_name,' ', a_u.last_name)) AS associated_admin_u
FROM users a_u
WHERE a_u.id IN(m.associated_admin)
GROUP
BY m.id
And m.associated_admin will return a quoted string like '1,10' so this will not work because of its a string.
2)
SELECT GROUP_CONCAT(CONCAT(a_u.first_name,' ', a_u.last_name)) AS associated_admin_u
FROM users a_u
WHERE a_u.id IN(1,10)
GROUP
BY m.id
If i write hard code like 1,10 it works, because it is not a string
So first one is not works because that query is part of another query as a sub query.
And i am sure this question couldn't be duplicate as i am facing it like in this way so any help would be appreciate, thanks reader!
Based on your comments, you need something like:
SELECT GROUP_CONCAT(CONCAT(a_u.first_name,' ', a_u.last_name)) AS associated_admin_u
FROM users a_u
WHERE FIND_IN_SET(a_u.id, TRIM(BOTH '\'' FROM m.associated_admin))
GROUP
BY m.id
This will first trim the quotes from m.associated_admin and then use FIND_IN_SET instead of IN so that you can use a string with comma-separated values.
You can just create a subquery in IN for example:
SELECT group_concat(CONCAT(a_u.first_name,' ', a_u.last_name)) AS associated_admin_u
FROM users a_u WHERE a_u.id IN(
SELECT id FROM mytable WHERE id IN(1,10)
) GROUP BY m.id
I would like to know how can I execute a query, inside a phalcon controller, using parameters.
My SQL Query:
SELECT a.*, getApplicationData(a.id) as json_data
FROM application a
INNER JOIN application_data d on d.application_id = a.id
WHERE a.form_id=1
AND d.firstname LIKE '%:searchQuery:%' ;
Here is how I'm trying to execute (I found it in Phalcon's doc, but the example was not inside a controller).
$applications = $this->db->query(
$sqlQuery,
array('searchQuery'=>$searchQuery)
)->fetchAll();
I know that since you have the ORM I shouldn't be querying the DB like this, but for the feature I'm working on it has to be like this, this query is dymanic.
My question is how to pass the parameter for the :searchQuery: in the query.
Thanks in advance for any help.
You almost got it right. You only had to add the percents (%) in the bind array.
$sqlQuery = 'SELECT * FROM events WHERE title LIKE :searchQuery';
$applications = $this->db->query(
$sqlQuery,
array('searchQuery'=> '%' . $searchQuery . '%')
)->fetchAll();
Also notice how I binded the :searchQuery in the $sqlQuery. It only uses single : instead of surrounding the parameter. This is because Raw queries use directly the DB connection in our case it is PDO.
More examples can be found here: https://docs.phalconphp.com/en/latest/api/Phalcon_Db_Adapter_Pdo.html
The query below is running well and runs quite fast for what it does. However it is displaying some very strange behaviour as outlined below.
However in PHP it seems to decide by itself which ids it will work for. I am certain that the code is correct. I am using PDO in PHP and binding the variables as required.
So for instance if I pass it the author_id 600 it will work, but if I pass it the author_id 2 it won't work and brings back no records. But if I echo the query and paste it into MySQL and run it, it works for both the ids. It would seem that the PDO is failing to bind the variable on some ids. I have echoed the id variable and it does indeed contain the proper id.
Has anyone else experienced this behaviour? I find it very very unusual.
SELECT
GROUP_CONCAT(a.author_id) AS author_ids
FROM
references_final AS rf
INNER JOIN (reference_authors AS ra INNER JOIN authors_final AS a ON (ra.author_id = a.author_id))
ON (rf.reference_id = ra.reference_id)
GROUP BY rf.reference_id HAVING :author_id IN (author_ids)
Hey I am having the same problem With BindParam and ID value in my PDO Statement
$retrieveUsersToken = $dataBase->prepare('SELECT TheUsersTable.token AS token, TheUsersTable.myID AS myID,
FROM TheUsersTable INNER JOIN TheCategoryListTable ON TheUsersTable.myID = TheCategoryListTable.userID
WHERE TheUsersTable.myID != :userID AND TheCategoryListTable.category = :category');
$retrieveUsersToken->bindParam( ':category', $_POST['category'], PDO::PARAM_STR);
$retrieveUsersToken->bindParam( ':userID', $_POST['creatorID'], PDO::PARAM_INT);
myID != userID never works
neighter does TheCategoryListTable.category = :category when :category contain space
Looks like the Inner Join is creating troube in both our situations.
It's not really an answer but maybe binValue works better.
Now that I've read all the DQL docs I still have some doubts, I'm
trying to do some nested condictions in my DQL however playing around
with DQL I can't seem to be able to archive them
To make myself more clear:
I have this DQL query
$q = Doctrine_Query::create()
->select('c.nombre,c.webpage')
->addSelect('COUNT(m.marca_id) as total_marcas')
->from('Corporativos c')
->leftJoin('c.Marcas m')
->groupBy('c.corporativo_id')
->where('ISNULL(c.deleted_at)')
->orwhere('c.nombre LIKE :nombre', array(':nombre'=>'%'.$srch))
->orWhere('c.nombre LIKE :nombre', array(':nombre'=>'%'.$srch.'%'))
->orWhere('c.nombre LIKE :nombre', array(':nombre'=>$srch.'%'))
->orderBy('c.nombre ASC')
->limit(0,20);
now this generates the following MySQL query:
SELECT c.corporativo_id AS c__corporativo_id, c.nombre AS c__nombre,
c.webpage AS c__webpage, COUNT(m.marca_id) AS m__0 FROM corporativos c
LEFT JOIN marcas m ON c.corporativo_id = m.corporativo_id WHERE
(ISNULL(c.deleted_at) OR c.nombre LIKE :nombre OR c.nombre
LIKE :nombre OR c.nombre LIKE :nombre) GROUP BY c.corporativo_id ORDER
BY c.nombre ASC
However I'm getting a set of results where either deleted_at is null
or the other conditions is completed, I'd like to make the
isnull(deleted_at) obligatory, if we were talking in terms of SQL the
query would look like this:
SELECT c.corporativo_id AS c__corporativo_id, c.nombre AS c__nombre,
c.webpage AS c__webpage, COUNT(m.marca_id) AS m__0 FROM corporativos c
LEFT JOIN marcas m ON c.corporativo_id = m.corporativo_id WHERE
(ISNULL(c.deleted_at) AND (c.nombre LIKE :nombre OR c.nombre
LIKE :nombre OR c.nombre LIKE :nombre)) GROUP BY c.corporativo_id
ORDER BY c.nombre ASC
you can see that I just changed the first OR statement for an AND and
added a couple of parenthesis to group the LIKE conditions.
Is it posible to archivie this in DQL using the same ->where()
notation avoiding writing down the whole condition ?
thanks :)
Not sure how recently this change was made, but for anyone like me coming to this question looking for answers long after this question was asked, the query builder now has ways to accomplish nested AND/OR logic: andX() / orX() functions.
You can use Doctrine_Query::andWhere, but i think this will factor your statement the wrong way, so you could build your query like
->where('c.nombre LIKE :nombre', array(':nombre'=>'%'.$srch))
->andWhere('ISNULL(c.deleted_at)')
->orWhere('c.nombre LIKE :nombre', array(':nombre'=>'%'.$srch.'%'))
->andWhere('ISNULL(c.deleted_at)')
->orWhere('c.nombre LIKE :nombre', array(':nombre'=>$srch.'%'))
->andWhere('ISNULL(c.deleted_at)')
which is kind of creepy.
Here is another solution with modifies Doctrine to be capable of custom bracketing: http://danielfamily.com/techblog/?p=37