This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to access mysqli connection in another class on another page?
I have a PHP class for connecting to a MYSQLi database and I want to use this class within another class to create a prepared statement and display some info from a database.
Is this possible at all?
<?php
class database {
public $host = "localhost";
public $user = "root";
public $password = "root";
public $name = "store";
public function connect() {
$connect = new mysqli($this->host, $this->user, $this->password, $this->name);
if($connect->connect_errno > 0){
die('Unable to connect to database [' . $connect->connect_error . ']');
}
}
}
class products {
// In here I want to use a MYSQLi prepared statment to show some information
// from the database details in the class above
}
$database = new database();
$database->connect();
?>
Thanks in advance!
Instead of connecting in the other class, you have to connect somewhere in bootstrap, getting class instance into variable. Then you'll be able to either pass this variable into constructor parameters or simple use
global $db;
$this->db = $db;
in constructor
By the way, I see no use for separate connect() method. Why not to connect right in the constructor?
Also let me suggest you not to use die() but trigger_error() (or exception) 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 work now on a project for learning i'm a beginner, i use singelton pattern to make sure, that there is just one PDO connection to the Data Base.
I made var_dump() for all possible connections to the Mysql and I founded that there were 10 objects of pdo.
how can i found, from where come all this objects?
Are 10 objects of PDO normal?
I wanted to use just one for all the project.
my singelton
<?php
namespace App\Database;
use PDO;
use PDOException;
class DataBase
{
private static $instance;
private PDO $pdo;
private function __construct()
{
try {
$db= parse_ini_file("..//..//..//config.ini");
#$db= parse_ini_file("..//..//config.ini");
$type = $db['type'];
$host = $db['host'];
$name = $db['name'];
$user = $db['user'];
$password = $db['password'];
$this->pdo = new PDO($type . ':host=' . $host . ';dbname=' . $name, $user, $password);
}
catch (PDOException $e) {
echo "there is an error";
die();
}
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $this->pdo;
}
private function __clone() {}
public static function getInstance()
{
if (!static::$instance) {
static::$instance = new DataBase();
}
return static::$instance;
}
public function getPdo(): PDO
{
return $this->pdo;
}
}
?>
then I made a connection of the pdo like this in another place, where I need to use pdo init.
function makePdo(){
$db= DataBase::getInstance();
$pdo= $db->getPdo();
var_dump($pdo);
return $pdo;
}
Thank you
10 connections are not normal, you should have only one to one DB. Use singleton pattern for database connection:
https://gist.github.com/jonashansen229/4534794
https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
In this case, you will have one connection and always will get it instead of creating duplicates.
No it should be only one object, the best way to implment it, is to create a separate config file to store your DBMS credentials as associative array, like mysql db_name, host .. etc.
Then create a config class to get those values by creating a static get method.
and finally use this get method inside your db constructor to get the credentials.
I'm pretty sure If you do that you'll get only one instance of PDO object.
I wanted to insert a row and at the same time get the id generated by that query.
I'm just testing it first and so far here is what I got.
I created a class which has a database configuration like this
class Database{
private $host;
...
...
protected function connect(){
$this->host = 'localhost';
...
...
$conn = new mysqli($this->host, ...,);
if ($conn->connect_errno){
echo 'error';
};
return $conn;
}
}
A User class for the actual query and where I extend my Database class.
class User extends Database{
function createUser(...,){
$sql = "INSERT INTO t (field) VALUES ('value');";
$this->connect()->query($sql);
return $this->connect()->insert_id;
}
}
I already have data inserted in my table but the function returns 0.
Note:
I have my column ID on user table of AUTO_INCREMENT attribute.
The query is successful but not returning the correct ID.
I tried doing this without the Database class and it works fine, returning the ID generated by the query.
$mysqli = new mysqli('host', ...,);
if(result = $mysqli->query("INSERT INTO t (field) VALUES ('value');")){
return $mysqli->insert_id;
}
Problem is inside your Database class.
you need a $conn field.
calling connect() causes to create new connection every time.
class Database{
private $host;
private $conn;
...
...
protected function connect(){
$this->host = 'localhost';
...
...
$this->conn = new mysqli($this->host, ...,);
if ($this->conn->connect_errno){
echo 'error';
};
}
}
class User extends Database{
function createUser(...,){
$sql = "INSERT INTO t (field) VALUES ('value');";
$this->conn->query($sql);
return $this->conn->insert_id;
}
}
Don't do it this way! Your Datebase class is useless and it doesn't follow the best practices of OOP.
Your problem is that each time you call $this->connect() you create a new connection. The connections do not share state between themselves so you can't access the last inserted ID using a different connection. It has to be the same connection!
Don't write such classes like Database class unless you are actually going to write abstraction library, and never inherit from a Database class.
mysqli is a class in itself. To open a database connection using mysqli you only need 3 lines of code.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4'); // always set the charset
You can then pass the instance to any class that needs it.
class User {
private mysqli $db;
public function __construct(mysqli $mysqli) {
$this->db = $mysqli;
}
function createUser(/* ... */) {
$stmt = $this->db->prepare("INSERT INTO t (field) VALUES (?)");
$stmt->bind_param('s', $value);
$stmt->execute();
return $this->db->insert_id;
}
}
$user = new User($mysqli);
You must always use prepared statements because it allows you to parameterize your queries. Never concatenate data directly into SQL.
Lastly, do not use mysqli on its own. It is not suitable for beginners nor to be used on its own. If you are only starting to learn PHP then you should learn PDO instead of mysqli. PDO is much easier and more suitable for beginners. Start here https://phpdelusions.net/pdo
This question already has an answer here:
Cannot redeclare class - php [closed]
(1 answer)
Closed 6 years ago.
i recently started learning PDO and OOP to make my websites safer and faster. i am having some issues with OOP in PHP.
i have a folder named res (short for resources) and a folder named classes and an index.php file, in the res folder i have a menu.php file that needs two classes named class.ManageUsers.php and class.ManageNews.php. in both of these files i am including class.database.php, here is the code for that file:
<?php
class dbConnection {
protected $db_conn;
public $db_name = 'red_sec_net';
public $db_user = 'root';
public $db_pass = '';
public $db_host = 'localhost';
function connect(){
try{
$this->db_conn = new PDO("mysql:host=$this->db_host;dbname=$this->db_name;",$this->db_user,$this->db_pass);
$this->db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->db_conn;
$this->conn = null;
}catch(PDOException $e){
die('failed to connect to database');
}
}
}
?>
now in the index.php file i need class.ManageUsers.php so i include it just before i include menu.php but when i go to that page i get this error:
Cannot redeclare class dbConnection in C:\wamp64\www\redsec\classes\class.database.php on line 3
the people i consulted said i should close the connections so i did that using
$this->link = null; and all the other variables that contained anything related to the connection after i do return what i need.
this is my constructor method:
class ManageUsers {
public $link;
function __construct(){
$db_connection = new dbConnection();
$this->link = $db_connection->connect();
return $this->link;
$this->link = null;
}
}
all my attempts have failed and i am starting to pull my hair out any help appreciated
i believe the error is happening in the constructor method when i do $db_connection = new dbConnection();
When your PHP app loads, the interpreter comes across the same class declaration more than once.
Try this:
include_once or require_once (if multiple inclusions of the same file happen)
Probably this could be a duplicated:
Cannot redeclare class - php
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.