1

I have looked everywhere for an answer to this and tried everything I have found here on StackOverflow and other sites.

Basically what's happening is that whenever I execute an SQL query, PDO is executing it twice even when execute() is only called once...

Here is my code...

<?php
namespace quizazle;

class sql{
  private $username = 'x';
  private $passwd = '';
  private $port = 3306;
  private $host = 'x';
  private $name = 'x';
  private $charSet = 'utf8mb4';

  private $db = null;

  public function __construct(){
    $this->db = new \PDO("mysql:host=$this->host;dbname=$this-    >name;charset=$this->charSet", $this->username, $this->passwd);
    $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $this->db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
    $this->db->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
  }

  private function bind($q, $p){
    try{
      $s = $this->db->prepare($q);
      if(!empty($p)){
        foreach ($p as $pm){
          $s->bindParam($pm['key'], $pm['value']);
        }
      }
    }
    catch(PDOException $e){
      echo($e->getMessage());
    }
    return $s;
  }

  public function query($query, $params){
    try{
      $statement = $this->bind($query, $params);
      $statement->execute();
      $res = $statement->fetchAll(\PDO::FETCH_BOTH);

      return $res;
    }
    catch(PDOException $e){
      echo($e->getMessage());
    }
  } 

  public function update($query, $params){
    try{
      $statement = $this->bind($query, $params);
      $statement->execute();
      $res = $statement->rowCount();

      return $res;
    }
    catch(PDOException $e){
      echo($e->getMessage());
    }
  }
}
?>

and here is the code where I am using the sql class...

$sql = new quizazle\sql();

$params = array(
  array(
    'key' => 'd',
    'value' => 'a'
  )
);

$result = $sql->update("INSERT INTO `test` (`data`) VALUES(:d)", $params);

var_dump($result);

I have tried...

  • removing var_dump($result);
  • not binding parameters, although that is a bad way to go for me, it still doesn't work.
  • changing $this->db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); to $this->db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
  • changing $this->db->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); to $this->db->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

yet none of this has worked. Any help will be greatly appreciated and thank you all in advance :)

PS: I discovered this problem while running INSERT statements, if that helps at all.

DibDibs
  • 566
  • 4
  • 17
  • 1
    How do you see that the query gets performed twice and not that the server actually gets two requests? – Charlotte Dunois Sep 16 '16 at 21:52
  • 3
    Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). – Charlotte Dunois Sep 16 '16 at 21:52
  • @CharlotteDunois I've told you my desired behaviour, I only want `execute()` to execute once, and why would the server receive 2 requests consistently if `execute()` is not being run twice? – DibDibs Sep 16 '16 at 21:54
  • 1
    You discovered this with an `INSERT` query, yet you're posting the code that revolves around an `UPDATE`. There's nothing indicating that `execute` gets called twice. Also, the class you created - it's not really doing you any favors, is it? It's more complicated than using `PDO` without "object oriented" code. How come you are not using ORM libraries available to PHP? If you're dabbling with this, I understand intellectual curiosity, but if you're trying to do some actual work - why reinvent the wheel? There's nothing here that we can use to reproduce, so Charlotte is quite correct. – N.B. Sep 16 '16 at 21:55
  • @N.B. I know what you're saying but I'm new to OOP in PHP and I want to fiddle around with it, I use the `update()` function for both `INSERT` and `UPDATE` queries, the queries executed have nothing to do with `UPDATE` – DibDibs Sep 16 '16 at 21:57
  • 1
    You should be using `bindValue`, not `bindParam`, in the `bind()` method, because `bindParam` binds to references. You're binding all the parameters to the last parameter. – Barmar Sep 16 '16 at 22:27
  • 2
    Nothing you've shown would explain why the code is running twice. The most likely reason is that something is calling your script twice. Check your server log to see how many calls there are to the script. – Barmar Sep 16 '16 at 22:32
  • See my answer [Here](http://stackoverflow.com/a/38808417) and look at the screenshot on the top of the Documentation page link. That is what the server is receiving from you. The General Query Log is there for that reason (primarily debugging only) – Drew Sep 17 '16 at 00:39

2 Answers2

1
  1. You wrote a very strange class that made your experience with database much worse than with vanilla PDO.
  2. Most likely your implementation of SEO-friendly URLS is no better.

To solve the first problem, leave PDO alone. Keep only one method in your class - query(), make it return PDOStatement:

public function query($query, $params) {
  $statement = $this->db->prepare($query);
  $statement->execute($params);
  return $statement;
} 

and utilize the method chaining to get different kinds of results from it. You may read detailed explanations in my article Your first database wrapper's childhood diseases. So your application code will become much cleaner:

$sql = new quizazle\sql();
$params = array('d' => 'a');
$result = $sql->query("INSERT INTO `test` (`data`) VALUES(:d)", $params);
var_dump($result->rowCount());

While for the second, just do not make your router script act as 404 handler. Run any controllers only if they are intended to, based on the request parameters. Do not run any SQL for the every request you get, but do it only for the requests you expect.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
0

I'm sorry for wasting all of your time, this was my stupid mistake.

You see, I was using Blisk which is a browser designed for developers. Since it is designed for developers, it has a function built-in that allows you to view your website as if it were on a mobile device, like this... enter image description here

When the page is loaded in this browser, it is loaded twice, once for the PC view and once for the mobile view. This means any PHP functions will be called twice, since the page is effectively being loaded twice, and that was the root of my problem.

There was nothing wrong with the code or the server, it was just me using Blisk that was the problem. Now that I'm back on Chrome, it's all alright!

I have flagged the problem to the Blisk devs, so hopefully something can be done to fix this! :)

DibDibs
  • 566
  • 4
  • 17
  • that's what I told you in my answer exactly. Nowhere it's a Blisk problem, but only your application's design flaw. – Your Common Sense Sep 18 '16 at 15:59
  • @YourCommonSense not really a reason to downvote though. Anyway, how would you even go about doing that, how do you 'expect' a request? – DibDibs Sep 18 '16 at 16:06