syntax error when attempting to dynamically write a search query - php

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).

Related

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 = ?";

Need to add a Group By statement to PHP/SQL generated from Codecharge

I am trying to modify some PHP code that was created ages ago in Codecharge, to include a Group By clause in a MYSQL statement.
I have tested my MYSQL query and it works brilliantly in phpmyadmin. When I bring it in to the php page it kicks back an error because the WHERE and ORDER clauses are coded in separate locations, and then called in to the query string. Obviously, when the GROUP BY is left in the SQL it breaks because it is inserting it before the WHERE in the $this chain, so I need to figure out where I can insert the GROUP BY part of the code so it strings it all together in the proper order and the page loads as it should. Below is the 3 sections that pull together the SQL and clauses, and the webpage loads fine. I commented out by version of the SQL as it doesnt work properly without the GROUP BY.
//SetOrder Method #5-0FECF370
function SetOrder($SorterName, $SorterDirection)
{
$this->Order = "book_name";
$this->Order = CCGetOrder($this->Order, $SorterName, $SorterDirection,
"");
}
//End SetOrder Method
//Prepare Method #5-C6449552
function Prepare()
{
$this->wp = new clsSQLParameters($this->ErrorBlock);
$this->wp->AddParameter("1", "urlshow_id", ccsInteger, "", "", $this->Parameters["urlshow_id"], "", false);
$this->wp->Criterion[1] = $this->wp->Operation(opEqual, "ttb_books.show_id", $this->wp->GetDBValue("1"), $this->ToSQL($this->wp->GetDBValue("1"), ccsInteger),false);
$this->Where = $this->wp->Criterion[1];
}
//End Prepare Method
//Open Method #5-33D1EC54
function Open()
{
$this->CCSEventResult = CCGetEvent($this->CCSEvents, "BeforeBuildSelect");
$this->CountSQL = "SELECT COUNT(*) " .
"FROM (ttb_books INNER JOIN ttb_states ON " .
"ttb_books.state_id = ttb_states.state_id) INNER JOIN ttb_statuses ON " .
"ttb_books.status_id = ttb_statuses.status_id";
$this->SQL = "SELECT * " .
"FROM (ttb_books INNER JOIN ttb_states ON " .
"ttb_books.state_id = ttb_states.state_id) INNER JOIN ttb_statuses ON " .
"ttb_books.status_id = ttb_statuses.status_id ";
//$this->SQL = "SELECT ttb_books.book_id, ttb_books.book_name, ttb_books.show_id, ttb_states.state_name, COUNT(ttb_imgs.img_id) AS images " .
//"FROM (ttb_books INNER JOIN ttb_states ON ttb_books.state_id = ttb_states.state_id) " .
//"INNER JOIN ttb_statuses ON ttb_books.status_id = ttb_statuses.status_id " .
//"LEFT JOIN ttb_imgs ON ttb_books.book_id = ttb_imgs.book_id ";
$this->Group = "ttb_books.book_id, ttb_books.book_name, ttb_books.show_id, ttb_states.state_name";
$this->CCSEventResult = CCGetEvent($this->CCSEvents, "BeforeExecuteSelect");
$this->RecordsCount = CCGetDBValue(CCBuildSQL($this->CountSQL, $this->Where, ""), $this);
$this->query(CCBuildSQL($this->SQL, $this->Where, $this->Order));
$this->CCSEventResult = CCGetEvent($this->CCSEvents, "AfterExecuteSelect");
$this->MoveToPage($this->AbsolutePage);
}
//End Open Method
The original version of the code just lists all the book titles, and sorts by book name. My version also includes a COUNT, because I want to not only see all the book titles, but also a page count for each book in the list. Like I said, my new SQL works fine in phpmyadmin, and I'm sure it would on the page too if I could get the Grouping to work properly, too. Thank you for your help!
Ok, here is what I did. I stripped out the $this->Where part of the CCBuildSQL line, and put the WHERE directly in to the sql statement, which allowed me to use my GROUP BY and get the results I was looking for.
function Open()
{
$this->CCSEventResult = CCGetEvent($this->CCSEvents, "BeforeBuildSelect");
$this->CountSQL = "SELECT COUNT(*) " .
"FROM (ttb_books INNER JOIN ttb_states ON " .
"ttb_books.state_id = ttb_states.state_id) INNER JOIN ttb_statuses ON " .
"ttb_books.status_id = ttb_statuses.status_id";
$this->SQL = "SELECT ttb_books.book_id, ttb_books.book_name, ttb_books.owned, ttb_books.show_id, ttb_shows.show_name, ttb_states.state_name, COUNT(img_id) AS images " .
"FROM ttb_books " .
"INNER JOIN ttb_states ON ttb_books.state_id = ttb_states.state_id " .
"INNER JOIN ttb_statuses ON ttb_books.status_id = ttb_statuses.status_id " .
"INNER JOIN ttb_shows ON ttb_books.show_id = ttb_shows.show_id " .
"LEFT JOIN ttb_imgs ON ttb_books.book_id = ttb_imgs.book_id WHERE ttb_books.show_id=" . $this->Parameters["urlshow_id"] .
" GROUP BY ttb_books.book_id, ttb_books.book_name, ttb_books.owned, ttb_books.show_id, ttb_shows.show_name, ttb_states.state_name " ;
$this->CCSEventResult = CCGetEvent($this->CCSEvents, "BeforeExecuteSelect");
$this->RecordsCount = CCGetDBValue(CCBuildSQL($this->CountSQL, $this->Where, ""), $this);
$this->query(CCBuildSQL($this->SQL, "", $this->Order));
$this->CCSEventResult = CCGetEvent($this->CCSEvents, "AfterExecuteSelect");
$this->MoveToPage($this->AbsolutePage);
}
It looks like you're not in the IDE and directly altering the generated code. Go into the CodeCharge IDE, choose the control you want to modify, then create a Custom Code Event and put your adjusted SQL there.
http://docs.codecharge.com/studio50/html/index.html?http://docs.codecharge.com/studio50/html/ProgrammingTechniques/HowTo/CustomizingDataSource/ModifyOrderBy.html?toc

mysql dynamic queries without clause where

In the following example there is a base query. Other parameters can be dynamically added to complete the query.
However, my base query has no clause WHERE.
What is the best way to deal with it.
If I use in the base query, for example, WHERE 1 = 1, it seems to solve, but I have some doubts that is a correct solution.
$myQuery = "SELECT fr.oranges, fr.aplles, fr.bananas,
FROM fruits fr
LEFT JOIN countrys ct ON fr.id_fruit = ct.id_fruit";
if(!empty($countrys){
$myQuery .= " AND countrys = ? ";
}
if(!empty($sellers){
$myQuery .= " AND seller = ? ";
}
$myQuery .=" GROUP BY fr.id_fruit ORDER BY fr.fruit ASC";
Edited: I fixed a writing gap from $empty to empty.
The WHERE 1=1 is a simplistic hack that works well because it simplifies your code. There is a great post here which explains the performance implications of WHERE 1=1. The general consensus is it will have no effect on performance.
Also, slight note ($empty) is probably not a function you've defined. I think you want empty(). You could write it like this:
$myQuery = "SELECT fr.oranges, fr.aplles, fr.bananas,
FROM fruits fr
LEFT JOIN countrys ct ON fr.id_fruit = ct.id_fruit";
$where = [];
if(!empty($countrys){
$where[] = "countrys = ?";
}
if(!empty($sellers){
$where[] = "seller = ?";
}
if (!empty($where)) {
$myQuery .= " WHERE " . implode(" AND ", $where);
}
$myQuery .= " GROUP BY fr.id_fruit ORDER BY fr.fruit ASC";
You can use an array to control your SQL like this:
$where = [];
if(!$empty($countrys){
$where[] = " countrys = ? ";
}
if(!$empty($sellers){
$where[] = " seller = ? ";
}
if(count($where) > 0) {
$myQuery .= " WHERE ".implode('AND', $where);
}

Ignore function on if condition PHP

I have some code but I want it to ignore 'customer::$data['vehicle_id']' when category_id = 1, 4, 9.
I've struggled with the code below and to add another function is out of my capabilities, so any advice would be great. Thanks in advance.
If vehicle_id is not selected it works fine.
if (empty($_GET['manufacturer_id'])) {
$manufacturers_query = database::query(
"select distinct m.id, m.name from ". DB_TABLE_PRODUCTS ." p
left join ". DB_TABLE_MANUFACTURERS ." m on m.id = p.manufacturer_id ".
(!empty($_GET['category_id']) ? " left join " . DB_TABLE_PRODUCTS_TO_CATEGORIES . " pc on pc.product_id = p.id " : "").
(!empty(customer::$data['vehicle_id']) ? " left join " . DB_TABLE_PRODUCTS_TO_VEHICLES . " ptv on ptv.product_id = p.id " : "").
"where p.status
and manufacturer_id
". (!empty($_GET['category_id']) ? "and pc.category_id = " . (int)$_GET['category_id'] : "") ."
". (!empty(customer::$data['vehicle_id']) ? "and ptv.vehicle_id = " . (int)customer::$data['vehicle_id'] : "") ."
order by m.name asc;"
);
I've tried using this:
". (!empty(customer::$data['vehicle_id']) && (!empty($_GET['category_id']) || !array_intersect(array(1, 4, 9), $_GET['category_id'])) ? "and ptv.vehicle_id = " . (int)customer::$data['vehicle_id'] : "") ."
EDIT:
while($manufacturer = database::fetch($manufacturers_query)) {
$box_filter->snippets['manufacturers'][] = array(
'id' => $manufacturer['id'],
'name' => $manufacturer['name'],
'href' => document::ilink('manufacturer', array('manufacturer_id' => $manufacturer['id'])),
);
}
I have taken your rather messy code and refactored it so it is readable, maintainable and better in a lot of small and big ways. It's by no means perfect, but now it can be reasoned about.
I also eliminated the SQL Injection opportunities for you, but you still need to redesign your database::query() function so it accepts an array of parameters to be used with your sql query in a prepared statement execution. I used named placeholders in your query to make it readable.
Doing the refactor this way, allowed me to add a boolean flag I can set if your ignore condition is true ($_GET['category_id'] equals one of [1,4,9])
if (empty($_GET['manufacturer_id']))
{
$ignoreVehicleId = false;
$params = [];
$query = "select distinct m.id, m.name
from ${DB_TABLE_PRODUCTS} p
left join ${DB_TABLE_MANUFACTURERS} m on m.id = p.manufacturer_id ";
if( !empty($_GET['category_id'])
{
$query .= " left join ${DB_TABLE_PRODUCTS_TO_CATEGORIES} pc on pc.product_id = p.id ";
if(in_array($_GET["category_id"], [1,4,9]) // <--- This array should be better documented to not use MAGIC NUMBERS. What is 1,4 or 9?
{
$ignoreVehicleId = true;
}
}
if( $ignoreVehicleId === false && !empty( customer::$data['vehicle_id'])
{
$query .= " left join ${DB_TABLE_PRODUCTS_TO_VEHICLES} ptv on ptv.product_id = p.id ";
}
$query .= "where p.status and manufacturer_id ";
/*
* In the following two IF's named parameters for prepared statements are being used.
* You need to refactor the database::query() function to accept a params array.
* Read up on using prepared statements with mysqli_* or better, PDO.
*
* DO NOT BUILD QUERIES WITH VARIABLES ANY OTHER WAY!!!
*
* If you do you are asking to be pwned by someone using your less than secure
* practises to do SQL Injection.
*/
if( !empty($_GET['category_id'])
{
" and pc.category_id = :category_id ";
$params[":category_id"] = (int)$_GET['category_id'];
}
if( $ignoreVehicleId === false && !empty(customer::$data['vehicle_id'])
{
" and ptv.vehicle_id = :vehicle_id ";
$params[":vehicle_id"] = (int)customer::$data['vehicle_id'];
}
$query .= " order by m.name asc;"
$manufacturers_query = database::query($query, $params);
}

php does not work with apostrophe in mysql query on linux server

I'm shucked with a strange problem. when i execute this query from my phpmyadmin it works fine and returns 2 results . But When we are executing this Query form php page it returns 0 result.
$query = "SELECT distinct(vtiger_products.product_no) FROM `vtiger_products`
INNER JOIN vtiger_crmentity VC ON VC.crmid = vtiger_products.productid
inner join vtiger_tree_product vtp on vtiger_products.productid = vtp.productid";
$custom_conditions = ' cf.cf_1399 = "'.$_REQUEST['size'].'"';
$temp ='Where vtiger_products.hisotrization_status='Current'
AND vtiger_products.productid > 0
AND VC.deleted = 0
AND vtp.nodeid in (425,426,427,428,430,431,457,458,459,460,480,488,502,510,514,515,516,517,518,519,520,521,525,526,527,528,529)';
if ($custom_conditions) {
$query .= " inner JOIN vtiger_productcf cf on cf.productid = vtiger_products.productid ";
$conditions .= " AND ( " . str_replace('""','\""',str_replace("''","\''",$custom_conditions)) . " ) ";
}
$query = $query.$temp . $conditions;
SELECT distinct(vtiger_products.product_no) FROM `vtiger_products`
INNER JOIN vtiger_crmentity VC ON VC.crmid = vtiger_products.productid
inner join vtiger_tree_product vtp on vtiger_products.productid = vtp.productid
inner JOIN vtiger_productcf cf on cf.productid = vtiger_products.productid
Where vtiger_products.hisotrization_status='Current'
AND vtiger_products.productid > 0
AND VC.deleted = 0
AND vtp.nodeid in (425,426,427,428,430,431,457,458,459,460,480,488,502,510,514,515,516,517,518,519,520,521,525,526,527,528,529)
AND ( cf.cf_1399 = "20'" );
Waiting for your response Thanks
You can pass the the php variables into the query by using function mysql_real_escape_string(Escapes special characters in a string for use in an SQL statement).
e.g.mysql_real_escape_string($user);
Plain and simple:
Wrong:
$query = '... set test = 'blah' where ...'; (' before blah terminates the string)
Solution 1:
$query = '... set test = \'blah\' where ...'; (escaping)
Solution 2:
$query = "... set test = 'blah' where ..."; (double quotes aren't terminated by single quotes)
Please note that "Hello, $test !" evaluates $test while 'Hello, $test !' does not.

Categories