Call to a member function prepare() on a non-objec

2019-01-01 13:35发布

问题:

I am trying to write a PHP function. It is very simple. It is just a prepared statement that queries the database, but I can not get this to work. I keep recieving the error Call to a member function prepare() on a non-object. here is the code:

$DBH = new mysqli(\"host\", \"test\", \"123456\", \"dbname\");
function selectInfo($limit, $offset){
    $stmt = $DBH->prepare(\"SELECT * FROM information LIMIT ?,?\");
    $stmt->bind_param(\"ii\", $limit, $offset);
    $stmt->execute();
    }
selectInfo();

Any time I call the function i get that error. Can someone please help?

回答1:

It\'s a scoping error. You\'re making $DBH a global variable. So when you enter the function, the global variable is not available. You have 5 real options.

1. Use the global keyword

function doSomething() {
    global $DBH;
    //...

This is not a good idea, since it makes maintenance and testing a PITA. Imagine trying to debug that function call. You now need to go find out where $DBH is defined to try to figure out what\'s going on...

2. Make $DBH a parameter to the function

function doSomething(MySQLi $DBH) {

It has the advantage of being explicit. But it\'s still not great since the calling code then needs to keep track of the global variable.

3. Create a function to \"get\" the $DBH object

function getDBH() {
    static $DBH = null;
    if (is_null($DBH)) {
        $DBH = new mysqli(...);
    }
    return $DBH;
}

function doSomething() {
    $DBH = getDBH();
}

This has the advantage of getting around the global variable problem completely. But it\'s also hard to have multiple connections or re-use any of the code for other connections.

4. Create a class to wrap database access

class Database {
    public function __construct($host, $user, $pass) {
        $this->DBH = new MySQli($host, $user, $pass);
    }
    public function doSOmething() {
        $this->DBH->foo();
    }
}

This encapsulates everything for you. All database access will go through a single class, so you don\'t need to worry about global variable access or anything else.

5. Use a pre-built class/framework

This is the best option, since you don\'t need to worry about doing it yourself.

Database Access Classes:

  • A quick google search to get you started
  • Doctrine ORM - A complete database access library with full ORM (Object Mapping)
  • ADODB - A database agnostic database access library
  • Pear MDB2 - Another database access library

Full Frameworks:

  • Zend Framework
  • Lithium Framework
  • Code Igniter
  • (really there are a lot more, I\'m not going to bother listing any more since that\'s another question all together...)

Really, the choices are endless. Find something you like, and stick with it. It really will make your life easier...

Good Luck!



回答2:

$DBH is not in scope. You either want to define $DBH as global in the function:

$DBH = new mysqli(\"host\", \"test\", \"123456\", \"dbname\");
function selectInfo($limit, $offset){
    global $DBH;
    $stmt = $DBH->prepare(\"SELECT * FROM information LIMIT ?,?\");
    $stmt->bind_param(\"ii\", $limit, $offset);
    $stmt->execute();
}

or as ircmaxell pointed out in his excellent answer have a function which returns a static instance of $DBH.



回答3:

Try to add global $DBH; in the function, or add it to the function\'s parameters.



回答4:

selectInfo($DBH);

function selectInfo($DBH,$limit, $offset){
    $stmt = $DBH->prepare(\"SELECT * FROM information LIMIT ?,?\");
    $stmt->bind_param(\"ii\", $limit, $offset);
    $stmt->execute();
    }


回答5:

That\'s simply. $DBH doesn\'t exist within selectInfo() function. Variable defined in global scope won\'t be visible within function and vice-versa. Read more about variables scope on manual pages.

How to solve it? Pass that variable as a argument of the function:

$dbh = new MySQLi(...);

function selectInfo(MySQLi $dbh, $limit, $offset) {
    $stmt = $dbh->prepare(...);
    ...
}


回答6:

Make sure the connection is successful.

$DBH = @new mysqli(\"host\", \"test\", \"123456\", \"dbname\");

if ($DBH->connect_errno) {
    die(\'Connect Error: \' . $DBH->connect_errno);
}

or

$DBH = @mysqli_connect(\"host\", \"test\", \"123456\", \"dbname\");

if (!$DBH ) {
    die(\'Connect Error: \' . mysqli_connect_errno());
}


回答7:

Making $DBH global is not healthy... except that you can make your $DBH protected in class and set it to null.. and use it..



回答8:

class PDOconnect extends PDO{

protected $con=null;

    public function __construct(){
              try {      

                     $this->con= new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD ); //our new PDO Object

                      $this->con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );                       
                      $this->con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );                     
                      $this->con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
                      echo \"hi.. you are connected succcessfully...\";
                  }