Count all products with search function - php

I’ve been trying to call a function and it just doesn’t seem to work.
So, this is function count_all_products_q. This is needed for pagination.
function count_all_products_q($options=[]) {
global $db;
$visible = $options['visible'] ?? false;
$search_statement = isset($_POST['search']) ? $_POST['search'] : '';
if ($search_statement == '') {
$search_statement = isset($_GET['search']) ? $_GET['search'] : '';
}
$search = h(db_escape($db, $search_statement));
$sql = "SELECT COUNT(id) FROM products ";
if ($search != '') {
$search = h(db_escape($db, $search_statement));
$sql .= "WHERE (`prod_name` LIKE '%".$search."%') ";
}
if($visible) {
$sql .= "AND visible = true ";
}
$sql .= "ORDER BY position ASC";
$result = mysqli_query($db, $sql);
confirm_result_set($result);
$row = mysqli_fetch_row($result);
mysqli_free_result($result);
//[0] - I want only one number.
$count = $row[0];
return $count;
}
search.php
$products_count = count_all_products_q(['visible' => $visible]);
//if count is nothing ('') redirect to....
if($products_count == '') {
redirect_to(url_for('/index.php'));
}
This part doesn’t work if($products_count == '') when I click search by mistake, instead of redirection, I have Database query failed (search.php?search=).
Am I missing something, did I do something wrong? Thanks for your attention!
UPDATE2 everything works!
search.php
$visible = $visible ?? true;
$search_statement = isset($_POST['search']) ? $_POST['search'] : '';
if ($search_statement == '') {
$search_statement = isset($_GET['search']) ? $_GET['search'] : '';
}
$search = h(db_escape($db, $search_statement));
if($search == '') {
redirect_to(url_for('/index.php'));
}
$products_count = count_all_products_q(['visible' => $visible]);

You have problem with the code where you are concatenating "WHERE" condition.
if($visible) then "WHERE" which is wrong and will give query error if this condition fails. Also $options['visible'] ?? false; this code may cause issue depending on the version on PHP. You can change your conditions like this to make it work in all scenarios.Followed by rest of the logic.
$sql = "SELECT COUNT(id) FROM products WHERE 1 ";
if($visible) {
$sql .= "AND visible = true ";
}
if ($search != '') {
$search = h(db_escape($db, $search_statement));
$sql .= "AND (prod_name LIKE '%".$search."%') ";
}

In case there is no visible is false ans search has text your query will be broken
In this case you should
if($visible) {
$sql .= "WHERE visible = true ";
}
if ($search != '') {
$search = h(db_escape($db, $search_statement));
$sql .= $visible ? 'AND ' : 'WHERE';
$sql .= " (`prod_name` LIKE '%".$search."%') ";
}
Not tested but I hope you can see your problem.

Print your query with echo $sql or with echo $this->db->query()
Run directly in mysql and check why it is getting failed.
May you have generate wrong query.

Related

how to Search Result Record Paging

This code is working fine for searching with POST method, how to pagination search results?
I have attach images. First image searching with this field:
Searching result in which I want paging:
<? php
include('connection.php');
if (isset($_POST['search'])) {
$fields = array('EJAMAATID', 'GNAME', 'MOBNO', 'EMAILID', 'DNNO', 'GCNTRYID', 'PINCODE', 'GCITYID', 'DNTYPE');`search field`
$conditions = array();
foreach($fields as $field) {
if (isset($_POST[$field]) && $_POST[$field] != '') {
$conditions[] = "`$field` LIKE '%".mysql_real_escape_string($_POST[$field]). "%'";`condition`
}
}
$query = "SELECT * FROM donation ";
$orderby = "ORDER BY DNDATE desc";
$datebetween = "AND DNDATE >='$start' AND DNDATE<='$end'";
if (count($conditions) > 0) {
$yakin5 = implode(' AND ', $conditions);
$query. = "WHERE ".$yakin5.$datebetween.$orderby;
}
}
$jo = (isset($query)) ? $query : '';
$don4 = mysql_query($jo);
while ($roww = mysql_fetch_array($don4)) {
}
?>

Issue in using arrays as parameters of method of PHP custom class

To explain my issue, here is a simple code at first:
public function sql($data) {
if (is_array($data)) {
$cells = $data['cells'];
$from = $data['from'];
$where = $data['where'];
$joins = $data['joins'];
$order_by = $data['order_by'];
$o_type = $data['order_by_type'];
$limit = $data['limit'];
/*****************************/
if ($cells == '') { $cells = "*"; }
if ($where != '') { $where = "where ".$where; }
if ($oredr_by != '') { $order_by = "order by ".$order_by." ".$o_type; }
if ($limit != '') { $limit = "limit ".$limit; }
//
$sql = "select ".$cells." from ".$from." ".$joins." ".$where." ".$order_by." ".$limit;
$run = mysqli_query($_SESSION['con'], $sql);
}else{
$run = mysqli_query($_SESSION['con'], $data);
}
}
When I start using this method, I pass a multidimensional array as a parameter, like this:
$sql = $class->sql([ "from" => "table", "order_by" => "id", "order_by_type" => "asc" ]);
/* This will generate and run this query: select * from table order by id asc */
// Notice that I've only used 3 keys, not the all above.
In Apache server, it works OK perfectly when I just use some of the keys of array, but in XAMPP it doesn't because it says that I have to pass all the parameters (cells, from, where, joins, ...) even if they are empty.
Please help me to resolve this, and thanks.
You can use isset to check if an array key is present, then get it's value like.
public function sql($data) {
if (is_array($data)) {
$cells = '';
if(isset($data['cells']) {
$cells = $data['cells'];
}
....
/*****************************/
if ($cells == '') { $cells = "*"; }
if ($where != '') { $where = "where ".$where; }
if ($oredrby != '') { $orderby = "order by ".$orderby." ".$od_type; }
if ($limit != '') { $limit = "limit ".$limit; }
$sql = "select ".$cells." from ".$table." ".$joins." ".$where." ".$orderby." ".$limit;
$run = mysqli_query($_SESSION['con'], $sql);
}else{
$run = mysqli_query($_SESSION['con'], $data);
}
}
Or simply just do error_reporting(1) before calling this function or in your index.php.
The problem is this.
$arr = ["a"];
echo $arr["b"];
You will get an error notice.
Notice: Undefined index: b
If you want to avoid this use it in this way.
$arr = ["a"];
$arr = ["b"] = "";
echo $arr["b"];
Change $from to $table, you have not $table variable
$from = $data['from'];
to
$table = $data['from'];
Also you have spelling mistake biggest spelling mistake which is very difficult to find.orderby and oredrby

SELECT Query, WHERE selects all when "" is empty

The Aim
Hi, I'm trying to shorten my code by building the query dynamically based on the $_GET. Current I have every possible If statement with the relevant SELECT query. However I would like to create a dynamic system for feature updates.
Current Progress
//Set Filter based on url
if ($_GET[GAME] != "") { $gameFilter = $_GET[GAME]; } else { $gameFilter = ''; }
if ($_GET[Region] != "") { $regionFilter = $_GET[Region]; } else { $regionFilter = ''; }
if ($_GET[Console] != "") { $consoleFilter = $_GET[Console]; } else { $consoleFilter = ''; }
$result = get_matchfinder($gameFilter, $regionFilter, $consoleFilter);
//The Function
function get_matchfinder($gameFilter, $regionFilter, $consoleFilter) {
//Set Varibles
$database = 'matchFinder';
$order = 'DESC';
$limit = '20';
//Query Function
$connection = connection();
$sql = 'SELECT * FROM '. $database .' WHERE game = "'.$gameFilter.'" AND region = "'.$regionFilter.'" AND console = "'.$consoleFilter.'" ORDER BY ID '. $order .' LIMIT '. $limit .'';
$response = mysqli_query($connection, $sql);
//Return
return $response;
}
Problem
Currenly it works when all of the filters are active but if one of them isn't the whole query fails, I know thats because it is try to SELECT something matching ''.
So my questions is how do I make it search for all when that filters is not set?
You should build the query parts depending on the length of the filter:
$sql = '
SELECT * FROM '.$database.'
';
$filters = array();
if (strlen($gameFilter) > 0) {
$filters[] = 'game = "'.mysqli_escape_string($connection, $gameFilter).'"';
}
if (strlen($regionFilter) > 0) {
$filters[] = 'region = "'.mysqli_escape_string($connection, $regionFilter).'"';
}
if (strlen($consoleFilter ) > 0) {
$filters[] = 'console= "'.mysqli_escape_string($connection, $consoleFilter).'"';
}
if (count($filters) > 0) {
$sql .= ' WHERE '.implode(' AND ', $filters);
}
if (strlen($oder) > 0) {
$sql .= ' ORDER BY ID '.$order;
}
if ($limit > 0) {
$sql .= ' LIMIT '.$limit;
}
$response = mysqli_query($connection, $sql);
What you're doing there is building up an array of conditions, based on the length of the condition. If the condition's input is an empty string, it isn't added to the array. At the end, if there are any filters, use implode to bind the conditions into a string. The way implode works, if there's only one condition, the glue string isn't used.
It also bears mentioning that you are exposing yourself to SQL injection. The above code shows the use of mysqli_escape_string to escape the input, but you should look in to parameterized queries to take full precaution: http://php.net/manual/en/mysqli.quickstart.prepared-statements.php -- the above sample would only be slightly different if you used paraterized queries, but significantly more safe.
Documentation
strlen - http://php.net/manual/en/function.strlen.php
implode - http://php.net/manual/en/function.implode.php
Mysql parameterized queries - http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
You would have to build your search dynamically
You could start your base query with
$sql='SELECT * FROM '. $database .' WHERE 1=1'
Then, if $gameFilter!="", append to your existing $sql string with "and game=$gameFilter"
The syntax for appending would be like this
if ($gameFilter!="")
{
$sql.=' and game=$gameFitler'
}
and so on checking for all of your search conditions.
Make you string like this
$sql = 'SELECT * FROM '. $database .' WHERE 1=1 {0} {1} {2}'
if ( $gameFilter <> '')
$sql = str_replace("{0}", "AND game = '".$gameFilter."'" , $sql);
else
$sql = str_replace("{0}", "" , $sql);
if ( $regionFilter <> '')
$sql = str_replace("{1}", "AND region = '".$regionFilter."'" , $sql);
else
$sql = str_replace("{1}", "" , $sql);
if ( $consoleFilter <> '')
$sql = str_replace("{2}", "AND console = '".$consoleFilter."'" , $sql);
else
$sql = str_replace("{2}", "" , $sql);

Filter MYSQL query with form options

I have a form with multiple inputs which are my filters.
This is my code (not all of it, just the part I want to fix):
$req_resumo = '';
$req_status = '';
$req_usuario = '';
$n_req = 0;
$parametros = "";
// Checks which fields are filled and increases the number of filters for future usage
if (isset($_POST['usuario']) && $_POST['usuario'] != "") {
$req_usuario = $_POST['usuario'];
$n_req++;
}
if (isset($_POST['resumo']) && $_POST['resumo'] != "") {
$req_resumo = $_POST['resumo'];
$n_req++;
}
if (isset($_POST['status']) && $_POST['status'] != "") {
$req_status = $_POST['status'];
$n_req++;
}
// Then (there is some code between these parts)
if ($n_req > 0 && $funcao != 'usuario') $parametros.= " where ";
if ($req_usuario != "") {
$parametros.= " usuario = '$req_usuario' ";
if ($n_req > 1) $parametros.= " and ";
}
if ($req_resumo != "") {
$parametros.= " resumo = '$req_resumo' ";
if ($n_req > 1 && ($req_status != "") || ($req_data_inicial != "")) $parametros.= " and ";
}
if ($req_status != "") {
$parametros.= " status = '$req_status' ";
}
// This will create the query and add the parameters string at the end.
$tot = mysqli_query($con, "SELECT * FROM solicitacoes $parametros");
This code looks ugly, and even for me (begginer), it doesn't feels right, does not sounds like the way of coding.
So, is there any better and easier way of building this code?
Give this a try. From my testing locally (without db) looked right.
$n_req = 0;
$_POST['usuario'] = 'test';
$_POST['resumo'] = 'test2';
$_POST['status'] = 'test3';
if (!empty($_POST['usuario'])) {
$req_usuario = $_POST['usuario'];
$where[] = " usuario = ? ";
$params[] = $req_usuario;
$n_req++;
}
if (!empty($_POST['resumo'])) {
$req_resumo = $_POST['resumo'];
$where[] = " resumo = ? ";
$params[] = $req_resumo;
$n_req++;
}
if (!empty($_POST['status'])) {
$req_status = $_POST['status'];
$where[] = " status = ? ";
$params[] = $req_status;
$n_req++;
}
$sql_where = !empty($where) ? ' where ' . implode(' and ', $where) : '';
echo $sql_where;
$tot = mysqli_prepare($con, "SELECT * FROM solicitacoes $sql_where");
if(!empty($params)) {
//foreach($params as $param) {
// mysqli_stmt_bind_param($tot, "s", $param);
//echo $param;
//}
$params = array_merge(array($tot),
array(str_repeat('s', count($params))),
array_values($params));
print_r($params);
call_user_func_array('mysqli_stmt_bind_param', $params);
// adapated from https://stackoverflow.com/questions/793471/use-one-bind-param-with-variable-number-of-input-vars and http://www.pontikis.net/blog/dynamically-bind_param-array-mysqli may need to be altered
}
echo "SELECT * FROM solicitacoes $sql_where";
mysqli_execute($tot);
If all three values are populated your query should be
SELECT * FROM solicitacoes where usuario = ? and resumo = ? and status = ?
The ? are populated with the values by the driver later in the process. This prevents the user(s) from adding in malicious code to manipulate the SQLs processing.
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28Parameterized_Queries.29
How can I prevent SQL injection in PHP?
I also didn't see where $funcao was set..
You can comment out the mysqli functions and decomment out the echo lines to see what the code does. That is how I confirmed queries were being built as expected.
$predicates = array();
if ($_POST['usuario'] != "") {
$predicates[] = "usuario = '{$_POST["usuario"]}'";
}
if ($_POST['resumo'] != "") {
$predicates[] = "resumo = '{$_POST["resumo"]}'"
}
if ($_POST['status'] != "") {
$predicates[] = "status = '{$_POST["status"]}'"
}
if (count($predicates) == 0) {
// handle case when nothing specified in POST
} else {
$tot = mysqli_query($con, "SELECT * FROM solicitacoes WHERE "
. implode(" and ", $predicates) );
}
I may not have all your logic exactly as required ... but the ideas are there. Use implode() to insert and between the predicates of your WHERE clause (it'll figure out how many are needed, if any). Also, since it is your HTML form that is submitting the POST, you can be certain that at least some value is being passed for each POST variable (so isset() is not required).

PHP PDO prepare query issue

The below works as long as the two fields are selected. If neither are selected it works, however my issue is when only one of the fields is selected, it doesn't work. It throws the unbound parameters issue.
I've tried setting a false value of 0 to both of the variables, however that won't work because then the query would be select from where = 0.
Ideas?
public static function searchProfile($status, $fundamt)
{
$database = DatabaseFactory::getFactory()->getConnection();
$sql = "SELECT profile_id, profile_name, profile_url, finance_fundingtype, finance_equitypercent, finance_loanrate, finance_loanlength, finance_fundingamount, info_tradingstatus, info_elevatorpitch, info_patentable, info_industry, info_industry1, info_industry2, info_industry3, info_industry4, seeker_logo_url FROM profile_seeker WHERE profile_status = '1' ";
if ($status) {
$sql .= "AND info_tradingstatus IN (:status) ";
}
if ($fundamt) {
$sql .= "AND finance_fundingamount <= :fundamt ";
}
$query = $database->prepare($sql);
$query->execute(array(':status' => $status, ':fundamt' => $fundamt));
$profiles = array();
$profiles[$profile->profile_id] = new stdClass();
$profiles[$profile->profile_id]->profile_id = $profile->profile_id;
$profiles[$profile->profile_id]->profile_name = $profile->profile_name;
$profiles[$profile->profile_id]->profile_url = $profile->profile_url;
$profiles[$profile->profile_id]->finance_fundingtype = $profile->finance_fundingtype;
$profiles[$profile->profile_id]->finance_equitypercent = $profile->finance_equitypercent;
$profiles[$profile->profile_id]->finance_loanrate = $profile->finance_loanrate;
$profiles[$profile->profile_id]->finance_loanlength = $profile->finance_loanlength;
$profiles[$profile->profile_id]->finance_fundingamount = $profile->finance_fundingamount;
$profiles[$profile->profile_id]->info_tradingstatus = $profile->info_tradingstatus;
$profiles[$profile->profile_id]->info_elevatorpitch = $profile->info_elevatorpitch;
$profiles[$profile->profile_id]->info_patentable = $profile->info_patentable;
$profiles[$profile->profile_id]->info_industry = $profile->info_industry;
$profiles[$profile->profile_id]->info_industry1 = $profile->info_industry1;
$profiles[$profile->profile_id]->info_industry2 = $profile->info_industry2;
$profiles[$profile->profile_id]->info_industry3 = $profile->info_industry3;
$profiles[$profile->profile_id]->info_industry4 = $profile->info_industry4;
$profiles[$profile->profile_id]->seeker_logo_url = $profile->seeker_logo_url;
}
return $profiles;
You could try to check if the variables are set and that they hold a value that is not 0 and this has a string length longer than 0:
if (isset($status) && $status !== 0 && strlen($status) > 0) {
$sql .= "AND info_tradingstatus IN (:status) ";
}
if (isset($fundamt) && $fundamt!== 0 && strlen($fundamt) > 0) {
$sql .= "AND finance_fundingamount <= :fundamt ";
}
You could also try to bind the parameters manually:
$query = $database->prepare($sql);
if (isset($status) && $status !== 0 && strlen($status) > 0) {
$query ->bindParam(':status',$status);
}
if (isset($fundamt) && $status !== 0 && strlen($fundamt) > 0) {
$query ->bindParam(':fundamt',$fundamt);
}
$query->execute();
Your binding error comes because you forgot to use the same if exists statement on your bindings.
Change this...
if ($status) {
$sql .= "AND info_tradingstatus IN (:status) ";
}
if ($fundamt) {
$sql .= "AND finance_fundingamount <= :fundamt ";
}
and
$profiles[$profile->profile_id]->finance_fundingamount = $profile->finance_fundingamount;
$profiles[$profile->profile_id]->info_tradingstatus = $profile->info_tradingstatus;
To this...
if (isset($status) && $status != '') {
$sql .= "AND info_tradingstatus IN (:status) ";
}
if (isste($fundamt) && $fundamt != '') {
$sql .= "AND finance_fundingamount <= :fundamt ";
}
and
if (isset($status) && $status != '') {
$profiles[$profile->profile_id]->finance_fundingamount = $profile->finance_fundingamount;
}
if (isste($fundamt) && $fundamt != '') {
$profiles[$profile->profile_id]->info_tradingstatus = $profile->info_tradingstatus;
}
This will stop the binding if one or both of the text boxes are empty.

Categories