Using MySQLi from Another Class in PHP

Using MySQLi from another class in PHP

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']);

How to access mysqli connection in another class on another page?

Your DBConnection class would need an additional method:

public function getLink()
{
return $this->mysqli;
}

It seems that your original User class was a subclass of DBConnection, because mysqli property on DBConnection is protected and User class has a parent::__construct() call.

It's better to use dependency injection, so your User class will receive its database connection via the constructor:

public function __construct(DBConnection $db)
{
$this->mysqli = $db->getLink();
}

Then from your code you can run:

$db = new DBConnection;
$uObj = new User($db);

Using MySQLi in other classes

I think you have at least 3 ways to do this... (Maybe there are more ways)

databasde.php (with class) needs to be included first for following steps

1: The first one is to extend the dbclass to your class like

class myclass extends database {

public function myclass(){

parent::__construct();
//....
}
}

than you have all functions and vars in your myclass

2: The second way is

require_once(database.php);

class myclass {

private $db;

public function myclass(){ /* the constructor */

$this->db = new database();
}

public function grabResult($table, $where, $field)
{
$result = "SELECT * FROM {$table} WHERE {$where}={$field}";

return $db->mysqli->query($result);
}
}

3: The third way is

class myclass{

private $db;

public function myclass(){
$this->db = false;
}

public function setupDBHandler($dbHwNd){
$this->db = $dbHwNd;
}

public function grabResult($table, $where, $field)
{
if($this->db){
$result = "SELECT * FROM {$table} WHERE {$where}={$field}";
return $db->mysqli->query($result);
}
else{
return "Setup DBHandler first.";
}
}
}

How to use MySQLi in a class

As mentioned in comment, you should include connection object file to another file.

Another alternative is:-

1) Make connection class static to handle mysqli object.

class DBConnection {
public static $con;
}
DBConnection::$con = new mysqli(YOUR_HOST, YOUR_USER, YOUR_PASS, YOUR_DB);

and in other file, call it statically as below:-

DBConnection::$con->query(...); // execute your query

2) You can also do it by creating class and object.

class Connection{
public $conn;

function __construct($host='YOUR_HOST',$user='YOUR_USER',$pass='YOUR_PASS',$db='YOUR_DB'){
$this->conn = new mysqli($host, $user, $pass, $db);
}
}

then create object of Connection class

$object = new Connection(); // pass connection params if you want to overwrite default connection params

$object->conn->query(..); // execute your query

Using PHP's mysqli connection as an object for other classes

It sounds like you're looking for Dependency Injection. There are other ways, but this is the best practice.

//create an object of the DB class
$DB = new DB();

//create a PageFunctions object and pass the DB object into it as a dependency
$PF = new PageFunctions($DB);

//call your function from PageFunctions
$PF->myFunction();

//follow these concepts and do whatever you want!

You can make this work by setting a constructor for PageFunctions:

class PageFunctions() {

//we don't want to accidentally change DB, so lets make it private;
private $DB;

//this is the class constructor
//the constructor is called when instantiating the class - new PageFunctions()
public function __construct(DB $DB) {
//now the DB object is available anywhere in this class!
$this->DB = $DB;
}
//sample function
public function myFunction() {
$this->DB->connect();
}
}

So, anytime you need to use a class within another class, make an instance (object) of it (or use an existing one) and pass it into the new class that needs it when creating an instance of it.

You might see this behavior accomplished using a Dependency Injection container, but it is still the same concept, system, and result. It's just a bit more abstracted. As you might have noticed from my explanation there, if you have a lot of classes that depend on other classes, that depend on other classes, etc, it can get quite overwhelming manually creating the instances and passing them in. A dependency injection container is nice because it lets you tell it how to make each class, and then it will take care of putting them altogether.

accessing database class from another class

When you extend a class, and both the parent and child class have a constructor, you must call the parent constructor from the child. If the parent constructor has arguments, you must then either a) get those arguments in the child constructor (best practice), or b) use hard-coded values (generally bad practice).

I assume that either a) your parent class establishes the database connection in its constructor, or b) you pass a database connection to the parent class. If the latter (b), then you have to take that db connection as an argument to the child class and manually evoke the parent constructor, OR, re-implement the tasks from the parent constructor in the child class. If the former, (a), the above is true BUT you are engaged in a bad practice. A class constructor should not do work, it should not know about other classes except its ancestors and typehinted constructor arguments. The new keyword in a constructor body is usually a sign of a "code smell' -- you create a hidden dependency.

Instead of this for a class that uses the database:

public function __construct ($username, $password) {
// establish database connection using username and password
}

....

$myObject = new SomeClass('ausername', 'apassword');

... do this:

$dbConnection = establishDbConnection($username, $password); // establish connection outside of the class
$myObject = new SomeClass($dbConnection); // pass in the connection into the object

^ that is called "Dependency Injection", and is a worthwhile topic to learn!

Here is an example of calling a parent constructor:

class A {
private $a1 = null;
public function __construct($arg1) {
// do something with the args
$this->a1 = $arg1;
}
}

class B extends A {
private $a2 = null;
public function __construct($arg1, $arg2) {
parent::__construct($arg1);
$this->a2 = $arg2;
}
}

Documentation

  • Constructors/Destructors - http://php.net/manual/en/language.oop5.decon.php

OOP PHP Can't get new mysqli from other class

Your code is a bit messy, so it's hard to tell where exactly the problem lies:

  • Why do you require config?
  • Why do you create a Database (which is more like a DbConfig) in the constructor instead of passing it?
  • What is the Scandiweb-class?
  • Why do you call mysqli->query on that class instead of $this

The last one is your immediate mistake. You extend myClass which creates the mysqli-connection and stores it as class variable $this->mysqli. That means that the child class Cd will have access to it. When you extend a class you can call all it's public and protected properties and methods. Only those marked as private can't be accessed.

That means instead of accessing $get->mysqli->query(...) you can do $this->mysqli->query(...). What would make sense in OOP is to create a connection once (like you do in the constructor) and pass it around to the services requiring a database connection. This is called Dependency Inversion Principle and using a Dependency Container makes it easier (but is not mandatory).

There are so called design patterns that will make it easier to deal with performing sql queries like in your code above. The most common ones are the Active Record-pattern as used in Laravel's Eloquent and the Propel library, the Table Data Gateway-pattern as used in Zend Framework's DB-component and the Data Mapper-pattern as employed by Doctrine ORM. If you want to write OOP code you should look at their documentation and maybe use one of those instead of dealing with everything yourself.

How to use $db from another .php to another .php's class using OOP?

You'd be best to create a DB class or harnessing an already created one to achieve what you're trying to do.

The usual flow for things like this is call Lazy Loading/Dependency Injection. Where you're passing the required objects into the class.

If you choose this path, I suggest that you read up on Dependency Injection, as many things do, it has pros AND cons but is essential in OOP.

As Ben Stated in the comments:


Dependency injection is a key principle in OOP. I'd like to add that
if you are serious about OOP you should also look into autoloaders in
general, PSR-4 and Composer.

A side not on the above mentioned, you'd be best to look at PHPTheRightWay, they list a lot of stuff, including Dependency Injection.

You'll end up creating something like. It'd be better if you followed this example to understand how it works:

Class DB {

function __construct($host, $user, $pass, $db) {
return $this->connect($host, $user, $pass, $db);
}

function connect($host, $user, $pass, $db) {
//..connect and all.
}

//...the rest of your functions/class...
}

You can construct this anyway you please. Or just make the mysqli object accessible, allowing you to call it.

Now we get to the fun stuff. Actually injecting it into your class;

Class Foo {

$private $db;

// your construct method here will ONLY except a `DB` class instance/object as $db.
// Try it with anything else and learn from the errors to understand what I mean.
function __construct(DB $db){
$this->db = $db;
}

}

$db = new DB($host, $user, $pass, $db);
// you can error check it here

$foo = new Foo($db);// inject the $db object.

If you just want to share the resource, you could harness global, but it is strongly discouraged.

include('connection.db.php');

class MySQLqueries {
public function samplefunction($queryString) {
global $db;
$sqlQry = mysqli->query($queryString);

return ($sqlQry) ? "<pre>Query Executed Successfully</pre>" : die("<pre>An error occured -> $db->error</pre>");
}
}

If you chose this path, you'd be best to assign the global instance of $db to an internal class variable, like $this->db.

PHP - Calling database class from another class

above the private declaration is just the class creation class
createSession

In which case your $conn = new databaseConnection; either needs visibility, or should be in a method. Hard to tell which without seeing all the class and the odd indentation you have.

So put that in the method it belongs in (perhaps the constructor?) or set it to private, protected, or public - whichever it was intended for.



Related Topics



Leave a reply



Submit