SQL in a prepared statement with inner join SQL statement - php

my query is working but I don't know how to put it in a prepared statement
This is my query(working)
SELECT P.first_name, P.middle_name, P.last_name, P.lrn, P.section
FROM students P INNER JOIN student_load C ON P.lrn = C.lrn
WHERE subject_code = 12332654
This is my prepared statement(I'm new to the prepared statement so I don't know much)
function get_total_all_records()
{
include('../config.php');
//IM NOT SURE IF THE PROBLEM IS HERE($statement)
$statement = $connection->prepare("SELECT P.first_name, P.middle_name,
P.last_name, P.lrn, P.section
FROM students P
INNER JOIN student_load C ON P.lrn = C.lrn");
$statement->execute();
$result = $statement->fetchAll();
return $statement->rowCount();
}
$query = '';
$output = array();
// OR IF THE PROBLE IS HERE($query)
$query = "SELECT P.first_name, P.middle_name, P.last_name, P.lrn, P.section
FROM students P INNER JOIN student_load C ON P.lrn = C.lrn
WHERE subject_code = 12332654";
if(isset($_POST["search"]["value"])){
$query .= 'AND ( lrn LIKE "%'.$_POST["search"]["value"].'%"
OR teacher LIKE "%'.$_POST["search"]["value"].'%"
OR sem LIKE "%'.$_POST["search"]["value"].'%" )';
}

One of the points of preparing a query is that you can use parameters for the parts you want to replace with data. This helps to protect you from SQL Injection Attack which concatenating variables into the string does not.
As your first query has no need of parameters it could quite happily be run using a simple ->query() but the second would be best run using a prepare and execute
$params = [':subjcode'=>$subject_code];
$query = "SELECT P.first_name, P.middle_name, P.last_name, P.lrn, P.section
FROM students P INNER JOIN student_load C ON P.lrn = C.lrn
WHERE subject_code = :subjcode ";
if(isset($_POST["search"]["value"])){
$query .= 'AND ( lrn LIKE :s1
OR teacher LIKE :s2
OR sem LIKE :s3 )';
$params = array_merge($params,
[':s1'=> '%' . $_POST["search"]["value"] . '%'],
[':s2'=> '%' . $_POST["search"]["value"] . '%'],
[':s3'=> '%' . $_POST["search"]["value"] . '%']
);
}
$stmt = $connection->prepare($query);
$stmt->execute($params);
Note I also added a space after :subjcode "; which was missing in your original query

Related

Array from Form Input - Select Statement MySQLi Parameterisation

Turning phrases entered in a Form input into an array to pass into a MySQL select statement where clause using MySQLi. The php code I have achieves this, but I can't workout how to parameterise the query to prevent against sql injection attacks. I've had a look at a few questions on this site, but I'm struggling to relate it to my code.
if(!empty($_POST['Message']))
{
$searchStr = get_post($con,'Message');
$aKeyword = explode(" ", $searchStr);
$query ="SELECT m.ID, m.MessageText FROM MessageMain m LEFT OUTER JOIN Likes l on m.ID = l.PostID WHERE MessageText LIKE '%" . $aKeyword[0] . "%'";
for($i = 1; $i < count($aKeyword); $i++) {
if(!empty($aKeyword[$i])) {
$query .= " OR MessageText like '%" . $aKeyword[$i] . "%'";
}
}
$query .= " GROUP BY m.ID, m.MessageText ORDER BY count(m.id) desc";
$result = $con->query($query);
$rowcount=mysqli_num_rows($result);
If you would like to build the WHERE clause dynamically based on the number of keywords to match you could do it like this:
if (!empty($_POST['Message'])) {
$searchStr = get_post($con, 'Message');
$aKeyword = explode(" ", $searchStr);
$whereClauseArr = [];
foreach ($aKeyword as $keyword) {
if ($keyword) {
$whereClauseArr[] = "MessageText LIKE ?";
$whereValues[] = '%'.$keyword.'%';
}
}
$stmt = $con->prepare(
'SELECT m.ID, m.MessageText
FROM MessageMain m
LEFT OUTER JOIN Likes l on m.ID = l.PostID
WHERE '.implode(' OR ', $whereClauseArr).'
GROUP BY m.ID, m.MessageText ORDER BY count(m.id) desc'
);
$stmt->bind_param(str_repeat('s', count($whereValues)), ...$whereValues);
$stmt->execute();
$result = $stmt->get_result();
}
Although in your case, checking the same column against multiple values would probably be better done with regular expression. This would make your query simpler and potentially also faster depending on the number of keywords you have.
if (!empty($_POST['Message'])) {
$searchStr = get_post($con, 'Message');
$aKeyword = explode(" ", $searchStr);
$aKeyword = array_filter($aKeyword); // Remove empty values
$stmt = $con->prepare(
'SELECT m.ID, m.MessageText
FROM MessageMain m
LEFT OUTER JOIN Likes l on m.ID = l.PostID
WHERE MessageText REGEXP ?
GROUP BY m.ID, m.MessageText ORDER BY count(m.id) desc'
);
$regexString = implode('|', $aKeyword);
$stmt->bind_param('s', $regexString);
$stmt->execute();
$result = $stmt->get_result();
}

php mysql query adds quotes in the end

I have set up a query as such:
$query = 'SELECT SGC.sys_id, TBL.semester, SGC.bonus, SGC.exam, SGC.ca FROM SubjectGradeComponent AS SGC, ';
$query .= '(SELECT `sys_id`, `semester` FROM AcademicYearTerm AS AYT, SubjectYearTermLevel AS SYTL WHERE academic_year = "' . $academic_year . '" AND SYTL.subject_id = ' . $subject_id . ' AND SYTL.form_level = ' . $form_level. ' AND SYTL.yearTerm_id = AYT.yearTerm_id) AS TBL ';
$query .= 'WHERE SGC.sys_id = TBL.sys_id;';
However when I run the query, $mysql->query($query);it returns an empty result with 0 rows. Running the same query on phpmyadmin shows the desired result. I have looked around but do not understand the problem.
$mysql->error does not show any error message either
EDIT:
generated query is like this:
SELECT SGC.sys_id, TBL.semester, SGC.bonus, SGC.exam, SGC.ca FROM SubjectGradeComponent AS SGC, (SELECT `sys_id`, `semester` FROM AcademicYearTerm AS AYT, SubjectYearTermLevel AS SYTL WHERE academic_year = "2018-2019" AND SYTL.subject_id = 1 AND SYTL.form_level = 1 AND SYTL.yearTerm_id = AYT.yearTerm_id) AS TBL WHERE SGC.sys_id = TBL.sys_id;""
Question is where are the "" from?
Looks like you want a JOIN query instead.
You should also use prepared statement with placeholders ? instead of injecting values directly into the query.
$query = "SELECT SGC.sys_id,
AYT.semester,
SGC.bonus,
SGC.exam,
SGC.ca
FROM SubjectGradeComponent AS SGC
JOIN AcademicYearTerm AS AYT
ON SGC.sys_id = AYT.sys_id
JOIN SubjectYearTermLevel AS SYTL
ON SYTL.yearTerm_id = AYT.yearTerm_id
WHERE academic_year = ?
AND SYTL.subject_id = ?
AND SYTL.form_level = ?";

Codeigniter create a prepared statement or use active record for search with concat

I was wondering how I can prevent sql injections with this search query of mine? Unfortunately I had to use the string due to me needing to concatenate the first and last names to search. I have tried prepared statements but they don't seem to work here too. I hope someone can help me with this. Thank you.
My function
public function admin_search($input,$limit,$start){
$sql = "SELECT * FROM agent_accounts as aa LEFT JOIN person as p ON aa.person_id = p.id "
. "WHERE CONCAT_WS('', p.first_name, p.last_name) LIKE '%$input%' "
. "OR p.email LIKE '%$input%' OR p.phone_number LIKE '%$input%' "
. "OR aa.account_number LIKE '%$input%' LIMIT $limit OFFSET $start";
$query = $this->db->query($sql);
if($query->num_rows()>0){
foreach($query->result()as $row){
$documents[] = $row;
}
return $documents;
}else{
return false;
}
}
Codeigniter Active records automatically escape queries to prevent from SQL injection
Like this
$query = $this->db->get_where('table_name', array('id' => $id), $limit, $offset);
But if you use query siblings
Try this :
$sql = "SELECT * FROM agent_accounts as aa LEFT JOIN person as p ON aa.person_id = p.id "
. "WHERE CONCAT_WS('', p.first_name, p.last_name) LIKE ? "
. "OR p.email LIKE ? OR p.phone_number LIKE ? "
. "OR aa.account_number LIKE ? LIMIT ? OFFSET ?";
$query = $this->db->query($sql,array('%{$input}%','%{$input}%','%{$input}%','%{$input}%',$limit,$start));
The question marks in the query are automatically replaced with the values from array.

syntax error when attempting to dynamically write a search query

i am trying to write a dynamic sql query. the query works ok with intergers. however once i tried to insert a string it fails.
below is my query:
public function getList($params['SearchBy'])
{
$select = "
SELECT
u.id, u.firstName,u.lastName,u.city";
$from = "
FROM
user u";
$where = "
WHERE
u.live = 1 ";
if(isset($params['SearchBy']))
{
$where .= 'AND '. implode(' AND ', $params['SearchBy']);
}
$GroupBy = "
GROUP BY
u.id ";
$sql = $select.$from.$where.$GroupBy;
}
for the searchby(), i dynamically produce these values from a search query; i then place these in an array.:
$this->searchBy[$key][] = $key.' = '. $val;
this works perfectly when its an integer. however strings need to have "" . i am not sure to escape the ""so that it shows up in the query.
i.e
$this->searchBy[$topkey][] = $key.' = '. "$val";
i tried doing this but it did not work:
$this->searchBy[$topkey][] = $key.' = '. \"$val\";
would appreciate any advice on how to escape it.
thank you.
below is the raw sql query-derived from the search ;
SELECT
u.id,u.picNo,
u.membershipType,
u.firstName,u.lastName
FROM
user u
LEFT OUTER JOIN
table_messages_between_members sm
ON
u.id = sm.senderId
LEFT OUTER JOIN
list_photos_uploaded_by_members ph
ON
u.id = ph.userId
WHERE
u.live = 1 AND u.membershipType = 1 AND u.city = London
GROUP BY
u.id
ORDER BY
The trivial solution would be
$this->searchBy[$topkey][] = $key.' = "'. $val .'"';
This approach, especially if available public by allowing end user to write/input values, can be a major security threat and you should escape the input values or use PDO (even better).

Inner join and PDO

I have a problem with INNER JOIN and PDO. My query is working just fine when not using INNER JOIN. When adding INNER JOIN to the query nothing shows.
Is this a way to go or am I completely wrong?
Any suggestions?
public function search($searchterm)
{
$query = $this->db->prepare("
SELECT
ad.id AS idet,
ad.lid,
ad.firstname AS firstnamer,
ad.surname AS surnamer,
ad.socialnr AS socialnumber,
ba.class AS classes
FROM `everybody` ad
INNER JOIN `students` ba
ON idet = ba.id
WHERE (`firstname` LIKE :search OR `surname` LIKE :search OR `classes` LIKE :search)");
$searchterm = '%' . $searchterm . '%';
$query->bindParam(':search', $searchterm, PDO::PARAM_STR);
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
echo $row['idet']. ' : '. $row['firstnamer']. ' '. $row['surnamer']. ' - '. $row['socialnumber']. ' Class: '. $row['classes']. '<br />';
}
}
You can't use a column alias in ON or WHERE. It should be
ON ad.id = ba.id
In case there are other SQL errors, you should enable PDO exceptions:
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Try by changing
INNER JOIN `students` ba
ON ad.id = ba.id
/*^^^^*/
WHERE (ad.firstname LIKE :search OR ad.surname LIKE :search OR ad.class LIKE :search)");
/*^^*/ /*^^*/ /*^^*/
Thank you all for your help.
Yes I have enabled exceptions for PDO errors. No error are registered. I have tried your suggestions as posted above. Nothing works.
When not using INNER JOIN, this code works like a charm:
public function search($searchterm)
{
$query = $this->db->prepare("
SELECT
id,
lid,
firstname,
surname,
socialnr
FROM `everybody`
WHERE (`firstname` LIKE :search OR `surname` LIKE :search)");
$searchterm = '%' . $searchterm . '%';
$query->bindParam(':search', $searchterm, PDO::PARAM_STR);
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
echo $row['id']. ' : '. $row['firstname']. ' '. $row['surname']. ' - '. $row['socialnr']. '<br />';
}
}
The difference between the code in my first post and this one, is the absence of INNER JOIN. I hope it will help any one to help me to understand why.
Is this the right approach? Do I need to rethink this and rewrite my function? Please advice in any direction to help me on the right track. You are most helpful. Thanks.

Categories