Call to a member function prepare() on a non-object PHP [duplicate] - php

This question already has answers here:
Call to a member function prepare() on a non-object PHP Help [duplicate]
(8 answers)
Closed 9 years ago.
Heres my code to connect to the database
function createConnection($DB_USER, $DB_PASSWORD){
$dbc = new PDO('mysql:host=****', $DB_USER, $DB_PASSWORD);
}
and below and is the code for a function being called
function checkIfUserExists($dbc, $username, $table){
global $dbc;
$stmt = $dbc->prepare("SELECT * FROM ? WHERE username = ?");
$stmt = bindParam(1, $table);
$stmt = bindParam(2, $username);
$stmt->execute();
}
below is the code i use to call them
$connect = new databaseOperations;
$connect->createConnection($DB_USER, $DB_PASSWORD);
$connect->checkIfUserExists($dbc, login, Username);
my question is why am i getting the call to a member function prepare() on a non-object error when the page loads?

You get that because the $dbc you pass to the checkIfUserExists method is not available in the global scope, only in the scope where it is created (in this case, the scope of createConnection).
The solution is simple: Never ever use globals in your code and the last code where you should use globals is in OOP code.
Use something like this:
class DatabaseOperations
{
private $dbc;
public function createConnection(...)
{
$this->dbc = new PDO(...);
}
public function checkIfUserExists(...)
{
$this->dbc->prepare(...);
// ...
}
}
$db = new DatabaseOperations();
$db->createConnection(...);
$db->checkIfUserExists(...);
Or return the $dbc variabele in the createConnection function and pass that to the other functions.
Important side note: This is surely not the way you should use classes. Read something about OOP and program like that. In that case, you usually have a method on the User (Active Record) or UserMapper (DataMapper) object to check if it exists.

function createConnection($DB_USER, $DB_PASSWORD){
$dbc = new PDO('mysql:host=****', $DB_USER, $DB_PASSWORD);
return $dbc; // <---- add this...
}
function checkIfUserExists($dbc, $username, $table){
// ---> no need to use global, because you pass $dbc as an argument
calling...
$dbc = $connect->createConnection($DB_USER, $DB_PASSWORD);

Related

Unable to use PDO inside class

I've a simple class, User which requires database access. I also require database access in several other classes, so my class.user.php looks like this:
include "config.php"
class User {
public $db;
public function __construct(PDO $db){
$this->db = $db;
global $db;
}
function LastLogin(){
// global $db; // if I uncomment this, it works for this function.
$pdo = $db->prepare("SELECT last_login FROM users WHERE username = ?");
$pdo->execute(array($username));
while($r = $pdo->fetchObject()){
echo $r->last_login;
}
}
}
Config.php looks like this:
$dsn = "mysql:host=localhost;dbname=db;charset=utf8";
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$db = new PDO($dsn,'user','pass', $opt);
So let's say I have page called userdetails.php, and I want to know when the user has last logged in.
$user = new User($db);
$user->LastLogin();
This results in a error message like this:
Notice: Undefined variable: db in /home/www/class.user.php on line 12
Fatal error: Call to a member function prepare() on a non-object in/home/www/class.user.php on line 12
So I'm having problems with using pdo inside the class. It makes no sense to type "global $db" to every function, so what am I doing wrong?
As stated in the comments, remove the line:
global $db;
Also, you don't need to pass the PDO either.
And instead of trying to reference it as
$db->prepare(....)
You want to reference it as:
$this->db->prepare(....)
since you're instantiating it as a variable accessible within the class.
try this
include "config.php"
class User {
public $db;
public function __construct($db){
$this->db = $db;
}
function LastLogin(){
$pdo = $this->db->prepare("SELECT last_login FROM users WHERE username = ?");
$pdo->execute(array($username));
while($r = $pdo->fetchObject()){
echo $r->last_login;
}
}
}
The global $db is definitely not required and is bad practice as it destroys the encapsulation of a class.
The type hint PDO in __construct(PDO $db) is also not actually legal as far as I know.
And while you have a property of $db and loaded it with the correct handle, to use it chnage this
$pdo = $db->prepare("SELECT last_login FROM users WHERE username = ?");
To
$pdo = $this->db->prepare("SELECT last_login FROM users WHERE username = ?");
So you are using/addressing it correctly.
global $db is the problem. Loose it and it all should work.
Remove global $db from your constructor.
Use $this->db instead of $db in function LastLogin

Fatal error: Using $this when not in object context in [duplicate]

This question already has answers here:
Fatal error: Using $this when not in object context
(4 answers)
Closed 9 years ago.
i have this class for connect to mysql database using php/mysqli:
class AuthDB {
private $_db;
public function __construct() {
$this->_db = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME)
or die("Problem connect to db. Error: ". mysqli_error());
}
public function __destruct() {
$this->_db->close();
unset($this->_db);
}
}
now, i have any page for list user :
require_once 'classes/AuthDB.class.php';
session_start();
$this->_db = new AuthDB(); // error For This LINE
$query = "SELECT Id, user_salt, password, is_active, is_verified FROM Users where email = ?";
$stmt = $this->_db->prepare($query);
//bind parameters
$stmt->bind_param("s", $email);
//execute statements
if ($stmt->execute()) {
//bind result columnts
$stmt->bind_result($id, $salt, $pass, $active, $ver);
//fetch first row of results
$stmt->fetch();
echo $id;
}
now, i see this error:
Fatal error: Using $this when not in object context in LINE 6
How to fix this error?!
Like the error says, you can't use $this outside of the class definition. To use $_db outside the class definition, first make it public instead of private:
public $_db
Then, use this code:
$authDb = new AuthDb();
$authDb->_db->prepare($query); // rest of code is the same
--
You have to understand what $this actually means. When used inside a class definition, $this is used to refer to an object of that class. So if you had a function foo inside AuthDB, and you needed to access $_db from within foo, you would use $this to tell PHP that you want the $_db from the same object that foo belongs to.
You might want to read this StackOverflow question: PHP: self vs $this

PHP mysqli connection class - can't access the connection variable outside. Scope issue [duplicate]

This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I am new to using PHP in an OOP way but have found an issue with my database connection class.
I have a file with this mysqli connection class here
$db_name = 'dbname';
$db_user = 'dbuser';
$db_password = 'dbpassword';
$db_host = 'localhost';
class database {
public $mysqli;
public function connect($db_host, $db_user, $db_password, $db_name){
$this->mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);
if ($mysqli->connect_errno) {
return "Sorry Andre, but you seem to have messed up the DB connection :(";
}
}
}
$newConnection = new database;
$newConnection->connect($db_host, $db_user, $db_password, $db_name);
I then want to use the variable $mysqli in a db connection in another file - this is a simple insert to a database using $mysqli variable to connect. I included the above in the connection file but it seems the $mysqli variable is not being returned when I call the method within the database class. I get the PHP error saying...
Fatal error: Call to a member function prepare() on a non-object in...
I have seen that using
global $mysqli;
works however I want to do it the proper way as I have heard that is not good practice.
I understand that I am potentially doing things a bit wrong here as I'm new to using OOP but I assumed that by returning that variable in the connect function I can then access it from creating the class outside.
Help is appreciated,
thanks.
When using it outside , you access a class variable via the instance...
$newConnection = new database;
$newConnection->connect($db_host, $db_user, $db_password, $db_name);
$newConnection->mysqli /* here you have access from outside */
from inside you use the keyword $this...
// like this from inside
if ($this->mysqli->connect_errno) {
return "Sorry Andre, but you seem to have messed up the DB connection :(";
}
In case you want to protect your variable from outside access use:
private $mysqli;
// instead of
public $mysqli;
You need to change:
$mysqli->connect_errno
To:
$this->mysqli->connect_errno
Fatal error: Call to a member function prepare() on a non-object in...
this always means, the the thing you called the method on, is not an object.
In your case: mysqli is not initialized.
a general tip:
connect looks like something, that should be within the constructor.
class d {
public function __construct($db_host, $db_user, $db_password, $db_name){
$this->mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);
if ($this->mysqli->connect_errno) {
return "Sorry Andre, but you seem to have messed up the DB connection :(";
}
}
public $mysqli;
}
$foo = new d('host', 'user', 'pass', 'dbname');
$foo->mysqli->prepare("something");
So when you aquire an instance of this class, it's automatically initialized.
Also this way you save a line, each time you want to initialize it.

PHP Problem accessing the global variable

I'm having problem with global variable in PHP. I have mysqli config file which contains only following data:
$mysqli = new mysqli("localhost", "user", "pass", "db");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
I have the following class on another file:
class user{
function username_exists($username){
global $mysqli;
if ($stmt = $mysqli->prepare("SELECT username FROM users WHERE username=?")) {
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->store_result();
$count=$stmt->num_rows;
$stmt->close();
}
return ($count > 0 ? true : false);
}
...
some more functions
...
}
Now this works fine, but in my previous question on SO, i was told that it is a bad practice to access global variable like I'm doing in above class. So, I'm trying to pass the global variable in the constructor, in following way:
private $mysqli;
function __construct()
{
global $mysqli;
$this->mysqli = $mysqli;
}
function username_exists($username){
//global $mysqli;
if ($stmt = $this->mysqli->prepare("SELECT username FROM users WHERE username=?")) {
And I get the following error:
Fatal error: Call to a member function prepare() on a non-object in...(line number)
Can you please tell me whats problem with it and how this can be fixed? Thanks.
Edit: Sorry for the spelling mistake of __construct. It was only mistake typing here, and the error isnt because of that.
Well... having global in your constructor kindof beats the point. Consider passing it in as a parameter __construct($mysqli).
public function __construct($mysqli)
{
$this->mysqli = $mysqli;
}
What you're trying to do here is called dependency injection.
I think the problem is you misstyped __construct try changing your __cuntruct to the right name for the constructor.
The global in username_exists is also useless.
You should also write a constructor which takes the variable as argument and avoid using global completly :
class User {
var $mysqli;
function __construct($mysqli) {
$this->mysqli = $mysqli;
}
[ ... some functions ... ]
}
You must create your object like this :
$myuser = new User($mysqli);
$myUser->prepare();
Your constructor is not getting called because it is not the constructor at all
__cuntruct
should be
__construct
Couple of things. I think it would work OK if you changed __cuntruct to __construct.
You're still using the global declaration inside the username_exists function. Why not just pass the $mysqli variable in the constructor?
function _construct($mysqli) {
$this->mysqli = $mysqli;
}
then you have no globals in the class.
The code as written was not really what the others on SO were attempting to encourage you to do.
function __construct($mysql_handler){
$this->mysql = $mysql_handler;
}
This is passing in the parameter into the object scope at construction. When you create an instance of your object, you would pass in the MySQL handle.
$mysqli = new mysqli("localhost", "user", "pass", "db");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$u = new User($mysqlli);
Then you should be able to call mysqli member functions on the property itself.
Your constructor is also misspelled. It will only work properly with the magic method name __construct().
Remove global $mysqli; in the function username_exists(), it does not makes sense.
The global $mysqli; is not required/does not makes sense since you want this variable to store the reference the connection IN THE CONTEXT of your object.
change __cuntruct() to __construct()

Call to a member function prepare() on a non-object PHP Help [duplicate]

This question already has answers here:
Executing mysqli_query inside a function
(2 answers)
Closed 7 months ago.
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?
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...
$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.
Try to add global $DBH; in the function, or add it to the function's parameters.
selectInfo($DBH);
function selectInfo($DBH,$limit, $offset){
$stmt = $DBH->prepare("SELECT * FROM information LIMIT ?,?");
$stmt->bind_param("ii", $limit, $offset);
$stmt->execute();
}
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(...);
...
}
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());
}
Making $DBH global is not healthy...
except that you can make your $DBH protected in class and set it to null..
and use it..
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...";
}

Categories