I know this probably has been asked before, but the answers in other topics I found didn't seem to help for me :/. I'm not sure what I'm doing wrong when I follow the answers but its bugging me out.
The error: Call to undefined method DB_Class::prepare() on line 15. I've put a comment line to mark it.
The code is in Dutch, I hope that ain't a problem.
Reg_Functies.php (or the relevant part atleast):
<?php
require_once("Reg_Config.php");
class Gebruiker
{
private $db;
public function Gebruiker()
{
$this->db = new DB_Class();
}
public function check_login($email, $wachtwoord)
{
$wachtwoord = md5($wachtwoord);
$resultaat = $this->db->prepare("SELECT Log_ID, Log_Bevoegdheid from login WHERE Log_Email = ? and Log_Wachtwoord = ?"); //this line gives the error
$resultaat->bind_param("ss", $email, $wachtwoord);
$resultaat->execute();
Reg_Config.php:
<?php
define('DB_Server', 'localhost');
define('DB_Gebruikersnaam', 'root');
define('DB_Wachtwoord', 'password');
define('DB_Database', 'database');
class DB_Class
{
function __construct()
{
$connection = mysqli_connect(DB_Server, DB_Gebruikersnaam, DB_Wachtwoord, DB_Database);
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
}
}
?>
It's probably something very simple I'm looking over, but help is really appreciated.
Your code is trying to call DB_Class::prepare(), because $this->db has been assigned new DB_Class().
First, your constructor should keep a copy of the mysqli connection object, so add a field
private $connection;
to the DB_Class class, and update the constructor so that it calls
$this->connection = $connection;
at the end.
Then, you either need to define a prepare method that calls mysqli_prepare($this->connection) in DB_Class(), or call $this->db->connection->prepare(). If you choose the last option, you need to make it a public field, instead!
Another, much better option, is to avoid creating this redundant DB_Class and use PDO instead.
Related
I really hope someone can help me figure out what I am missing. I have upgraded my installation from PHP 5.6 to 7.0 and this has forced me to update from Mysql to Mysqli which for some reason has broken my setup.
I researched and followed this guide "Using MySQLi in other classes": Using MySQLi in other classes
I am writing as a last resort and have looked at other sites as well but it seems like the problem comes some where else from.
First I have a database class:
private $serverName = "localhost";
private $userName = "DBUserName";
private $pass = "UserPassword";
private $database = "SelectedDB";
public $conn;
public function __construct(){
$this->conn = new mysqli($this->serverName, $this->userName,$this->pass,$this->database);
}
Then I have an API class where I want to access this connection which looks like
require_once 'Database.php';
class MyAPI{
private $db;
public function __construct($request_uri, $postData, $origin) {
$this->db = new Database();
}
and lastly i try to call it from a function:
$getUserResult = mysqli_query( $this->db->conn, $getUserQry);
When ever I call $this->db->conn I get an internal server error 500
If I create the database connection in the MyAPI class there is no issues which seems odd to me.
I hope someone can point me in a direction.
UPDATE:
I corrected a spelling error in the script and now I get 200 but the value still continues to be null from the query mysqli_query.
If i create the $dbtest = new database(); and use that instead it works fine. Is there someway to get it to work inside the constructor with the reference to $db?
There are several bad practices that led you to this error.
Clearly, extending User from a Database is a wrong move. Also, the whole Database class is rather useless as it doesn't do anything useful.
Hence I would suggest to
get rid of the useless Database class.
create a single $db instance from vanilla mysqli.
pass it as a constructor parameter into every class that needs a database connection
database.php:
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$db = new mysqli("localhost", "DBUserName", "UserPassword", "SelectedDB");
$db->set_charset('utf8mb4');
myapi.php
<?php
class MyAPI
{
protected $db;
public function __construct($db, $request_uri, $postData, $origin)
{
$this->db = $db;
}
public function getUser($id)
{
$sql = "SELECT * FROM users where id=?";
$stmt = $this->db->prepate($sql);
$stmt->bind_param("s", $id);
$stmt->execute();
$result = $stmt->get_result();
return $result->fetch_assoc();
}
}
app.php
<?php
# require_once 'Database.php';
# require_once 'myapi.php';
require 'vendor/autoload.php'; // autoloading is a must
$api = new MyAPI($db, $request_uri, $postData, $origin);
$user = $api->getUser($_POST['id']);
I am trying to find a way to get the variable called $connect to run but don't know how.
Filename: /engine/init.php
class Engine {
function MySQL() {
$connect = new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char", $db_user, $db_pass);
}
}
Filename: /inc/database.php
require 'engine/init.php;
$engine = new Engine;
$conn = $engine->MySQL;
// Activate $connect variable
If it's not clear, please request for more info.
Thanks,
CrAzYz_
You will have to update the class to access members outside.
You have several options to do it.
1: store the connection in a public property
class Engine {
public $connection;
public function MySQL() {
$this->connection = new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char",$db_user, $db_pass);
}
}
This way you can retrieve it by
$engine = new Engine();
$engine->MySQL();
$conn = $engine->connection;
2: Make the function return the connection
class Engine {
public function MySQL() {
return new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char",$db_user, $db_pass);
}
}
This way your example will work (if you use Mysql as a function):
$engine = new Engine();
$conn = $engine->MySQL();
3: A more complicated but generally better aproach:
class Engine {
protected $connection;
public function __construct($db_host, $db_name, $db_user, $db_pass $db_char = "utf-8") {
$this->connection = new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char",$db_user, $db_pass);
}
public function MySQL() {
if ( !$this->connection instanceof PDO ) {
throw new Exception("Connection is not set up");
}
return $this->connection;
}
}
This would work almost as you wanted, except you cant access the connection directly (its protected), but only through the MySql function. This way if you forgot to init the connection an exception is thrown.
$engine = new Engine("localhost", "db_name", "user", "pass");
$conn = $engine->MySQL(); // you don't even need to save the connection to a local variable, because the function only references the connection and won't start a new one
Footnote:
If you had to as this kind of question you should probably look up and learn more about OOP. For php this is a start: http://php.net/manual/en/language.oop5.php
About to run off so this is a little quickly done.
class Engine
{
public $db;
public function connect($host, $database, $charset, $user, $pass)
{
$this->db = new PDO("mysql:host=$host;dbname=$database;charset=$charset", $user, $pass);
}
}
First of we have your Engine class that you want to create, we've created a property named db on the class that we can access with ->db. We also have a method called connect which we pass our database variables into so that PDO can connect to our database.
Now we pass in our database credentials to our connect method, in a production environment I really would advise against hard coding these and instead use something like environment variables.
$engine = new Engine();
$engine->connect('127.0.0.1', 'example_database', 'UTF-8', 'root', 'root');
We can then use our newly initiated PDO connection like so:
$statement = $engine->db->query('SELECT * FROM some_table');
$result = $statement->execute();
That should at least give you a starting point, there are other ways to go about this but I didn't want to stray too far from your original code.
Also if anyone spots anything wrong, let me know and i'll update it when I'm back in, need to run off in a sec.
I'm newbie here. I tried to solve this for a day and searching all the way but I still couldn't.
The error shown up
Notice: Undefined variable: db (in dbFunction)
Fatal error: Call to a member function query() on a non-object (in dbFunction)
and code is
dbConnect.php
class dbConnect{
public $db;
public function __construct(){
$db = new mysqli("localhost", "root", "", "onlineshopping");
$db->set_charset("charset");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
}
}
dbFunction
class dbFunction extends dbConnect {
function __construct() {
}
public $db;
public function UserRegister($fname, $lname, $tel, $email, $pass){
$pass = md5($pass);
$db->query("INSERT INTO member(fname, lname, tel, email, password) values('".$fname."','".$lname."','".$tel."','".$email."','".$pass."')") or die(mysqli_error());
return $db;
}
}
First of all, your $db is a local variable in the __construct() method and not a class property and second, as pointed by #wogsland it gets overwritten by the child.
You might want to review a bit the OO basics
dbConnect.php
class dbConnect{
public $db;
public function __construct(){
$this->db = new mysqli("localhost", "root", "", "onlineshopping");
$this->db->set_charset("charset");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
}
}
dbFunction
class dbFunction extends dbConnect {
public function UserRegister($fname, $lname, $tel, $email, $pass){
$pass = md5($pass);
$this->db->query("INSERT INTO member(fname, lname, tel, email, password) values('".$fname."','".$lname."','".$tel."','".$email."','".$pass."')") or die(mysqli_error());
}
}
Notice the replacement of $db with $this->db in both methods.
edit:
My post was an exact answer to your question but, as others have pointed in comments, there are quite a few things you need to improve and my hope was that this code is for your own personal play not something for 'production'.
So, directly related to the code example, two obvious things you might want to expand:
at least escape all your input to avoid sql injection
don't use MD5 for hashing passwords as it is very weak, check a more secure way to hash passwords
Your dbFunction class redefines __construct() to do nothing, so the $db property remains undefined. If you don't want to change the constructor in dbFunction, just omit it and the parent constructor will be used. If, on the other hand, you want to add to the functionality of the constructor then make sure to call the parent constructor:
function __construct() {
parent::__construct();
// additional dbFunction construction here
}
First of all, there's no need to make dbFunction a child class of dbConnect. They aren't related at all. In fact, I couldnt find any need to make dbConnect a class at all. All you need is the module __construct(). I would propose that you read up on OOP concepts :)
Still, answering your question - your __construct() function in dbConnect should return the db variable! You can assign this return value to your db variable in dbFunction.
Add the following line to your dbConnect's __construct() outside the if clause:
return $db;
And then instantiate an object of your class dbConnect in your dbFunction and assign db to that return value. (I'm assuming that dbFunction is not a child of dbConnect now...)
dbConn = new dbConnect()
db = dbConn.__construct()
First learn some basics of OO programming it seems like you should first read about objects and instances before using them in any fashion. Try this http://litove.com/object-oriented-programming-2/ you will find all your answers.
I'm trying to connect to 2 databases. One of them is a remote database. Once i connected to the remote database i had trouble with the one that existed, it gave me 'supplied argument is not valid ' on mysql_fetch_array() . So i changed my database class a bit and tried to make it work. But i still get errors :(. Its not grabbing $connection variable.
i get "undefined variable connection".
this is my connection class. Please help me out. Appreciate your help.
global $connection;
class Database{
function __construct()
{
$this->open_connection();
}
public function open_connection()
{
$connection = $this->connection= mysql_connect(SERVER,UNAME,PASSWORD);
if(!$this->connection)
{
return false;
}
if(!mysql_select_db(DB_NAME,$this->connection))
{
return false;
}
return true;
}
public function close_connection()
{
mysql_close($this->connection);
}
//open_connection();
}
$database = new Database();
and in another page:
$result=mysql_query($query,$connection);
while ($rec = mysql_fetch_array($result)) ... etc
p.s all constants and other variables are correct.
Using a global variable in a class is like death.
You could provide a class field for the connection link
$this->connection = mysql_connect(...);
And outside your class
$result = mysql_query($sql, $object->connection);
I'd also suggest you to use the existing mysqli class.
Hmm... Well, it looks like you are getting an undefined error thrown because you are calling global $connection at the top of the class file, and it hasn't been assigned a value.
It looks like you are establishing $connection inside of the open_connection() method... Are you establishing $connection in some included file that you haven't mentioned?
Try removing the first line of code, perhaps?
the "global $connection;" MUST be inside "open_connection" method or use #peipst9lker method
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...";
}