0

I am trying to use PDO to transcribe my code from mysqli.

I am making a simple low to high and vice-versa price filter

Inside preview.php I have a form with radio check buttons that are send to by POST method into search.php file

What I tried in search.php where Validating occurs:

  $sql =  "SELECT * FROM products";
      $cat_id = (($_POST['cat']!= '')?sanitize($_POST['cat']):'');
      if($cat_id == ''){
        $sql .= ' WHERE deleted = 0';
      }else{
        $sql .= "WHERE categories = '{$cat_id}' AND DELETED = 0";
      }
      $price_sort =(($_POST['price_sort'] != '')?sanitize($_POST['price_sort']):'');
      $min_price =(($_POST['min_price'] != '')?sanitize($_POST['min_price']):'');
      $max_price =(($_POST['max_price'] != '')?sanitize($_POST['max_price']):'');

      if($min_price != ''){
        $sql .= " AND price >= '{$min_price}'";
      }

      if($max_price != ''){
        $sql .= " AND price <= '{$max_price}'";
      }

      if($price_sort == 'low'){
        $sql .= " ORDER BY price";
      }

      if($price_sort == 'high'){
        $sql .= "ORDER BY price DESC";
      }
      $sql->execute();

This is returning

Uncaught Error: Call to a member function execute() on a string

Error occurs where on execute, I have tried using prepared statements and binding but I didn't find the solution


Thanks to @Chris and @Cobra_Fast I managed to resolve my full issue by doing:

  1. Making sure my PDO object is preparing the statement
  2. Binding all the parameters (escaping having variable inside query statement)


  $sql =  "SELECT * FROM products";
  $cat_id = (($_POST['cat']!= '')?sanitize($_POST['cat']):'');
  if($cat_id == ''){
    $sql .= ' WHERE deleted = 0';
  }else{
    // $sql .= "WHERE categories = '{$cat_id}' AND DELETED = 0";
    $sql .= "WHERE categories = :cat_id AND DELETED = 0";
  }
  $price_sort =(($_POST['price_sort'] != '')?sanitize($_POST['price_sort']):'');
  $min_price =(($_POST['min_price'] != '')?sanitize($_POST['min_price']):'');
  $max_price =(($_POST['max_price'] != '')?sanitize($_POST['max_price']):'');

  if($min_price != ''){
    $sql .= " AND price >= :min_price";
    $sql->bindParam( ":max_price", $min_price, PDO::PARAM_STR );

  }

  if($max_price != ''){
    $sql .= " AND price <= :max_price";
    $sql->bindParam( ":max_price", $max_price, PDO::PARAM_STR );

  }

  if($price_sort == 'low'){
    $sql .= " ORDER BY price";
  }
  if($price_sort == 'high'){
    $sql .= " ORDER BY price DESC";
  }


  // $veza->query($sql);
  $productQ =$veza->prepare($sql);
  $productQ->bindParam( ":cat_id", $cat_id, PDO::PARAM_STR );
  $productQ->execute();
Lortnok
  • 49
  • 1
  • 9
  • …read the error message carefully. What does it seem to be telling you? Do you see where you're calling `execute()`? Do you see what kind of object you're calling it on? – ChrisGPT was on strike Apr 07 '18 at 22:48
  • That I am doing it wrong way by concating query to a string ? – Lortnok Apr 07 '18 at 22:49
  • Well, building SQL queries by sticking strings together isn't generally safe. You are probably open to SQL injection (I have no idea what `sanitize()` does, but it's almost certainly the wrong thing.) But that's not the problem here. What database API are you trying to use? I don't see any connection info or appropriate function calls anywhere. Strings can't be executed; normally you'd pass a string into an execute function on a database connection object. – ChrisGPT was on strike Apr 07 '18 at 22:51
  • sanitize is the function that hopefully escapes the html entities, I am using PDO, I am not using oop but rather raw php. This code functions fine with mysqli but I am not sure how to handle this with pdo. My connection is set up inside config.php – Lortnok Apr 07 '18 at 22:54
  • 2
    Don't escape HTML entities. That doesn't do anything useful. To protect against SQL injection you need to use parameterized queries (i.e. prepare statements, bind arguments to them, and then execute them—see https://stackoverflow.com/a/4364697/354577). If you're using PDO you need a PDO connection object. Do you have one? – ChrisGPT was on strike Apr 07 '18 at 22:56
  • My database objest is $veza , as defined in config https://pastebin.com/f8mu48Pc , I have tried using bind statements, but I could input bold text in user input while with sanitize function it prevents me , I guess I didn't understand it properly – Lortnok Apr 07 '18 at 22:59
  • Okay, good. I strongly recommend reading the answer I linked in my last comment. I think it contains everything you need to get your code to work. – ChrisGPT was on strike Apr 07 '18 at 23:01
  • What does it matter if you can input bold text? That's not dangerous to a database. – ChrisGPT was on strike Apr 07 '18 at 23:03
  • Well still, I don't want to have that option. And images or video links could be unappropriate if on live server – Lortnok Apr 07 '18 at 23:08
  • Okay, maybe you want to disallow HTML. But it does literally nothing for database security. You _must_ use parameter binding if you're including user input in your query. – ChrisGPT was on strike Apr 07 '18 at 23:09
  • I have found the resolution, maybe you can check how I did the binding you suggested, the only thing I don't quite understand is that it works even without the binding inside if condition – Lortnok Apr 08 '18 at 00:54

1 Answers1

3

string is a primitive type in PHP and doesn't expose any methods at all, so calling execute() on a string confuses PHP since you're trying to use it like a class instance.

It also seems like you're trying to execute an SQL query, which means you need to take the SQL query you just built in $sql and execute it with your database driver.

In case of PDO that could look like this:

$sql = "SELECT * FROM products";
// ...
$pdo->query($sql);
Cobra_Fast
  • 15,671
  • 8
  • 57
  • 102