Simple PHP OOP and MySQLI - php

I am trying to learn some more PHP, OOP and MySQLI, but I am stuck. Google didn't help me and searching on this website didn't give me any results either. I have a config class to connect to the database, and in another class I want to run some queries, but I am getting this error with whatever I am trying:
Fatal error: Call to a member function query() on a non-object in
test.php on line 9
Can someone please help me?
config.php:
<?php
class Database
{
private $host;
private $user;
private $password;
private $db;
private $mysqli;
function __construct() {
$this->host = "private";
$this->user = "private";
$this->pass = "private";
$this->data = "private";
$this->mysqli = new mysqli($this->host, $this->user, $this->pass, $this->data);
}
public function query($query)
{
return $this->mysqli->query($query);
}
}
?>
test.php:
<?php
class Dummy
{
private $Database;
function __construct()
{
$this->Database = new Database();
$this->Database->test = $this->mysqli->query("SELECT test FROM test")->fetch_object()->test;
}
}
?>
index.php:
<?php
require 'config.php';
require 'test.php';
$test = new Database();
$test = new Dummy();
echo $this->Database->test;
?>

How about using Dependency injection, create the Database object then pass that as a parameter to the class through the construct.
<?php
class Database
{
private $host;
private $user;
private $password;
private $db;
private $mysqli;
function __construct($host,$user,$pass,$data) {
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->data = $data;
$this->mysqli = new mysqli($this->host, $this->user, $this->pass, $this->data);
}
public function query($query)
{
return $this->mysqli->query($query);
}
}
?>
...
<?php
class Dummy
{
function __construct(Database $db)
{
$this->db = $db;
}
function get_test_yada(){
return $this->db->mysqli->query("SELECT test FROM test")->fetch_object()->test;
}
}
?>
...
<?php
$db = new Database('127.0.0.1','root','pass','database');
$dummy = new Dummy($db);
$dummy->get_test_yada();
?>
Untested, hope it helps

For the goodness sake, DON'T learn them all at once. You won't get any sensible result.
Each is a hard and complex topic alone, of which OOP is hardest.
For the database interacton use PDO prepared statements.
As the OOP practice, never extend class from a service, but use it as a class variable.
class Dummy
{
protected $db;
function __construct($pdo)
{
$this->db = $pdo;
}
}

$this->mysqli = new mysqli($this->host, $this->user, $this->pass, $this->data);
If connecting fails, you can't call anything on that member variable. Check if your connection is established first.
And, if you want to have access to that variable, you should make it public.

Related

How to create 2 PDO database connection instances PHP

I currently have a class which creates one database connection, however I would like to create another connection too. I have tried copying the class structure but just renaming the variables and functions however that doesn't work and it seems like it doesn't detect where my new PDO connection is as I get error Uncaught Error: Call to a member function prepare() on null in. What is the best approach to take in my case when creating 2 database connections?
config.php:
<?php
class Database
{
private $host = "localhost";
private $db_name = "database1";
private $username = "root";
private $password = "";
public $conn;
public function dbConnection()
{
$this->conn = null;
try
{
$this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $exception)
{
echo "Connection error: " . $exception->getMessage();
}
return $this->conn;
}
}
?>
class.user.php:
class USER
{
private $conn;
public function __construct()
{
$database = new Database();
$db = $database->dbConnection();
$this->conn = $db;
}
public function runQuery($sql)
{
$stmt = $this->conn->prepare($sql);
return $stmt;
}
}
You could create your User class and pass the connection to the constructor. This will give you flexibility to swap out the connection.
Regarding your database class, it seems to be a wrapper, to create a PDO connection. You could do away with it, or extend the class with different params.
Perhaps look at dependency injection, and containers. They might help you here.
<?php
class User
{
private $conn;
public function __construct(PDO $conn)
{
$this->conn = $conn;
}
public function runQuery($sql)
{
$stmt = $this->conn->prepare($sql);
return $stmt;
}
}

Getting query error in OOP php

I'm just new using OOP php and I'm having a hard time to figure out how to query in database using class method. Here's my code and I've got an error which I dont know how to solve.
I declared the connection variable but I don't know why it's undefined
Notice: Undefined variable: connection
Fatal error: Call to a member function query() on a non-object in
db.php
class DbConnector {
private $serverName;
private $userName;
private $password;
private $dbName;
private $connection;
public function __construct(){
$this->serverName = "localhost";
$this->userName = "root";
$this->password = "attl";
$this->dbName = "oop";
$this->connection = new mysqli($this->serverName, $this->userName, $this->password, $this->dbName);
if ($this->connection->connect_error) {
$this->connection = die("Connection failed: " . $this->connection->connect_error);
}
}
public function getConnection(){
return $this->connection;
}
}
index.php
include('../queries/db.php');
class Users{
private $connection;
public function __construct(){
$con = new DbConnector();
$connection = $con->getConnection();
}
public function getUsers(){
$sql = $connection->query("SELECT * FROM login");
while($getUsers = $sql->fetch_array()){
echo $getUsers['username'];
}
}
}
$user = new Users();
return $user->getUsers();
Your problem is you're trying to access a locally scoped variable rather than a class property
public function getUsers(){
$sql = $connection->query("SELECT * FROM login"); // HERE
while($getUsers = $sql->fetch_array()){
echo $getUsers['username'];
}
}
this can't find a variable called $connection in that scope, you need to access the object property using $this.
class Users {
private $connection;
public function __construct()
{
$con = new DbConnector();
// Assign this to object propety declared above
$this->connection = $con->getConnection();
}
public function getUsers()
{
// now access the object property set in constructor.
$sql = $this->connection->query("SELECT * FROM login");
while($getUsers = $sql->fetch_array()){
echo $getUsers['username'];
}
}
}
Since you're declaring the following as private:
private $connection;
and including it in your construct:
public function __construct(){
$con = new DbConnector();
$connection = $con->getConnection();
You need to use $this for its property:
$this->connection = $con->getConnection();
Then changing:
$sql = $connection->query
to
$sql = $this->connection->query
in order to use the connection property.
Now, I have to admit that I am not an OOP expert and there may be another way to have solved this, yet this is what I took from it, which worked for me.

Data Base Connection Class with PDO statement

I've just started to learn OOP PHP and i'm trying create class that will do connection to my data base.
The code:
class DB_CONNECT
{
private $host ;
private $dbName ;
private $userName ;
private $password;
private $db;
public function __construct($host,$dbName,$userName,$password){
$this->host = $host;
$this->dbName = $dbName;
$this->userName = $userName;
$this->password = $password;
try {
$this->db = new PDO('mysql:host='.$this->host.';dbname='.$this->dbName.';charset=utf8',$this->userName,$this->password);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->db;
} catch (Exception $e) {
ECHO $e->getMessage();
}
}
}
$db = new DB_CONNECT("localhost", "oopcms","viktor","viktor");
function select($db){
$query = $db->prepare("SELECT * FROM `test`");
$query->execute();
$row = $query->fetchAll(PDO::FETCH_ASSOC);
return $row;
}
$x = select($db);
var_dump($x);
But I am getting this error:
Fatal error: Call to undefined method DB_CONNECT::prepare();
What I understand is that the PDO object couldn't be created. Can you give some guidance please?
Learning OOP is not the reason for creating pointless classes.
Unfortunately, you created one. PDO don't need a class to be built on top of it. Just leave it as is.
So, instead of
$db = new DB_CONNECT("localhost", "oopcms","viktor","viktor");
make it
$db = new PDO("localhost", "oopcms","viktor","viktor");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
that would be way clearer and useful
who interested here is the solution of this and Pekka and Your Common Sense thank you for a tip:)
class Select
{
private $query;
private $dbh;
private $row;
public function __construct(){
$this->dbh = new DB_CONNECT("localhost", "oopcms","viktor","viktor");
}
public function select(){
$this->query = $this->dbh->db->prepare("SELECT * FROM `test`");
$this->query->execute();
$this->row = $this->query->fetchAll(PDO::FETCH_ASSOC);
return $this->row;
}
}
$sel = new Select();
$s = $sel->select();
var_dump($s);

Class is not inheriting DB correctly

So I have a DB class that looks like this
class db{
private $hostname = 'localhost';
private $username = 'root';
private $password = 'root';
private $con;
public function db(){
try {
$dbh = new PDO("mysql:host=$this->hostname;dbname=myDB", $this->username, $this->password);
}catch(PDOException $e){
echo $e->getMessage();
exit();
}
$this->con = $dbh;
echo 'Connected to database<br />';
}
And my index.php
include('db.class.php');
include('todo.class.php');
include('dressTemplate.inc.php');
$db = new db;
$todo = new todo($db);
And my todo.class.php start like this
class todo{
function todo(db $db){
$this->db = $db;
}
public function render($post) {
$db &= $this->db;
But then I get this notice
Notice: Undefined variable: db in todo.class.php on line 11
Notice: Object of class db could not be converted to int in todo.class.php on line 11
How do I get db to be defined correctly in todo.class.php?
You are using &=. That is equal to $db = $db & $this->db. And first notice is there because PHP knows nothing of $db (it's undeclared yet). Second notice is because you're trying to do (null) & (object). First will be converted to int first and then 'object could not be converted' will appear, obviously (since PHP will try to treat whole expression as int)
That's it: your object variable is set correctly, but your $db variable is local and has nothing to do with it. And you're doing something strange with object via & (bitwise AND)
Tip: do not use old PHP4 way to define class constructors - unless you're using PHP4. In PHP5 there's __construct() magic method for that.
Try this:
class todo {
var $db;
__construct(&$db) {
$this->db = $db;
}
public function render($post) {
$db = &$this->db;
}
}
Your todo class should either use the __construct or a public function with the class name, e.g.
class todo {
var $db;
__construct (db $db) {
$this->db = $db;
}
// OR
public function todo(db $db){
$this->db = $db;
}
...
}
You should use a public constructor: __construct()
This works fine for me:
class db{
private $hostname = 'localhost';
private $username = 'root';
private $password = 'root';
private $con;
public function __construct(){
try {
$dbh = new PDO("mysql:host=$this->hostname;dbname=myDB", $this->username, $this->password);
}catch(PDOException $e){
echo $e->getMessage();
exit();
}
$this->con = $dbh;
echo 'Connected to database<br />';
}
}
class todo{
public function __construct(db $db){
$this->db = $db;
}
}

PHP __construct()

I have the following, however I'm unable to access the database functions outside of the initial db class?
Thanks!
database.php
class db
{
private $connection;
public function __construct()
{
$this->connection = new PDO();
}
}
admin.php
class admin
{
private $connection
public function __construct(db $connection)
{
$this->connection = $connection;
}
function myFunc()
{
// How do I access the connection here?
}
}
main.php
//include db.php
//include admin.php
$connection = new db();
$admin = new admin($connection);
// How do I access the DB here?
First of all, why are you encapsulating PDO just to class containing that one object? Cannot you use PDO directly?
One of the common practices would be to implement getter in db class, like:
class db {
...
public function getPDO(){
return $this->connection;
}
}
Another way is to re-implement every function (why would you do that?!), or use __call magic function...
Or just make $connection public ;)
Or you could extend PDO class (I'm not sure whether it'll work):
class DB extends PDO {
public function __construct ( $dsn, $username = null, $password = null, $driver_options = array()){
parent::__construct( $dsn, $username, $password, $driver_options);
... more of your stuff
}
public function myFunc(){
$this->...
}
}
ok, you really need to go and read up on object-oriented design, and access modifiers. I'll explain what you need to do here, but this is a band-aid solution, and you need to deeply understand how things are working here.
In your admin class, you defined the connection as a private attribute of the class. So in the myFunc function, you simply do $this->connection to access the connection that you created in the constructor.
In your main.php file, the object you are getting rom initializing a DB object is not the connection. It is the db object as a whole, so you can not pass the connection by itself to the admin class (it is defined as private, so nobody outside the class can view it). However, why do you need to pass it to the admin class? Managing the DB connection should be the responsibility of the DB class.
In other words, what are you trying to achieve by exposing the DB connection to the admin class?
Upate: based on the reply here is a suggested answer:
class Database {
private $connection;
public function __construct() {
$this->connection = new PDO();
}
}
class Admin {
private $db;
public function __construct() {
$this->db = new Database();
}
public function myFunc() {
$this->db->query('...');
}
}
In your main.php file:
$admin = new Admin();
$admin->myFunc();
Keep in mind, every admin object is going to create a new connection to the DB, so if you create many admin objects you might face some issues. You can get around this by declaring the DB to be a singleton.
How about this:Updated
<pre>
<?php
class DB {
private $host;
private $user;
private $pass;
private $dbase;
private $connection;
public function __construct($host,$user,$pass,$dbase)
{
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->dbase = $dbase;
$this->connection = new PDO("mysql:host=$this->host;dbname=$this->dbase", $this->user, $this->pass);
}
public function connect()
{
return $this->connection;
}
public function close()
{
unset($this->connection);
return true;
}
}
$dbh = new DB('localhost','root','','inventory');
$result = $dbh->connect()->query("SELECT * FROM products")->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
?>
</pre>
Updated with files separation
database.php
class db
{
private $connection;
public function __construct()
{
$this->connection = new PDO();
}
}
admin.php
class admin
{
private $connection
public function __construct(db $connection)
{
$this->connection = $connection;
}
function myFunc()
{
return $this->connection->prepare('SQL');
}
function getConnection()
{
return $this->connection;
}
}
main.php
require_once 'database.php';
require_once 'admin.php';
$connection = new db();
$admin = new admin($connection);
$admin->myFunc()->execute();

Categories