Getting query error in OOP php - 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.

Related

How to call a local property using OOP?

I'm a beginner looking to learn more about PHP OOP, so there are things I don't know, in the ShowUsers() method, I would like to display all users in the database, but I'm not getting it, because I don't know how to call the connection property. If I've been using encapsulation, it would be easy, but I'm using the connection property as local, and I really don't know how to call this property, how can I call it without using encapsulation?
db.php
<?php
class DbConnect {
private $host = 'localhost';
private $dbname = 'database';
private $username = 'root';
private $password = '';
public function __construct() {
try {
$conn = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $exception) {
throw new Exception($exception->getMessage());
}
}
}
main.php
<?php
require_once 'db.php';
class Main extends DbConnect {
public function __construct() {
parent::__construct();
}
public function ShowUsers() {
$sql = "SELECT * FROM users";
$result = parent::__construct()->prepare($sql); //Problem here
$result->execute();
}
}
$object = new Main();
$object->ShowUsers();
Note: I don't want to use encapsulation to make it work, I want to learn how to call the variable without using encapsulation, if possible.
Based on the code above and the comments, I recommend that you declare $conn as protected in your DbConnect class:
<?php
// db.php
class DbConnect {
private $host = 'localhost';
private $dbname = 'database';
private $username = 'root';
private $password = '';
protected $conn;
public function __construct() {
try {
$this->conn = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $exception) {
throw new Exception($exception->getMessage());
}
}
}
Then in main.php, you can do:
<?php
// main.php
require_once 'db.php';
class Main extends DbConnect {
public function __construct() {
parent::__construct();
}
public function ShowUsers() {
$sql = "SELECT * FROM users";
$result = $this->conn->prepare($sql);
$result->execute();
}
}
$object = new Main();
$object->ShowUsers();
?>

Using class database connection in other class

I have a class with a connection to a database
$db = new db();
class db {
public $server = 'localhost';
public $user = '';
public $passwd = '******';
public $db = '';
public $dbCon;
function __construct() {
$this->dbCon = mysqli_connect($this->server, $this->user, $this->passwd, $this->db);
}
function __destruct() {
mysqli_close($this->dbCon);
}
}
Now i want to make an other class and using the connection like this:
class Categories (
function GetCategory($cat) {
$myQuery = "SELECT * FROM test GROUP BY $cat";
$results = mysqli_query($this->dbCon, $myQuery);
return $results;
}
)
How can i use the connection in a other class?
Can somebody help me out whit this?
Make the $dbCon in your db class a static variable, so you can access it from category's using db::$dbcon as the connection variable. You could also make a static function returning the static dbcon variable, usefull tot check if it is actually a link and not null.
This is just one solution of many possibilities, but probably the easiest to implement because it isn't likely you need more connections to a db, so a static is perfect for it.
A static is nothing more then a variable living in the namespace it is defined in, you don't need to initialize the class in order to access it. It's value is shared across all instances of the object, so creating multiple DB class instances allows you tot just return a static if it was set in a previous DB class instance.
class db{
static $link;
static function connect(){
if(self::$link = mysqli_connect(....)){
return self::$link;
} else {
die('could not connect to db');
}
}
static function getcon(){
return isset(self::$link) ? self::$link : self::connect();
}
}
class Categories{
function GetCategory($cat){
$myQuery = "SELECT * FROM test GROUP BY $cat";
return mysqli_query(db::getcon(), $myQuery);
}
}
Create an object of the db class in the categories class. Then use that object to query the db accordingly. Also make sure you use a static variable in the db class. SO that the connection variable is created once and will be used all along the application.
Your db class may look like this
class db {
public $server = 'localhost';
public $user = '';
public $passwd = '******';
public $db = '';
public static $dbCon;
function __construct() {
$this->dbCon = mysqli_connect($this->server, $this->user, $this->passwd, $this->db);
}
function __destruct() {
mysqli_close($this->dbCon);
}
}
Your categories class may look like this
class Categories {
$connection=db::$dbCon;
if(!$connection){
$db=new db();
$connection=db::$dbCon;
}
function GetCategory($cat) {
$myQuery = "SELECT * FROM test GROUP BY $cat";
$results = mysqli_query($this->connection, $myQuery);
return $results;
}
}

How to properly use dependency injection with PHP?

I'm very new at PHP. I have two classes: Database and RetrieveItem. Because RetrieveItem needs a connection, I've just been extending the Database class to use its constructor. Apparently this is wrong, because RetrieveItem is not a database?
Here is my current code:
class Database {
public $host = '127.0.0.1';
public $username = 'root';
public $password = '';
public $dbname = 'example';
function __construct(){
$this->connect = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
}
}
class RetrieveItem extends Database {
function retrieve_item(){
$query = $this->connect->prepare("SELECT * FROM posts");
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
}
And on a separate page, to use this, I have:
include 'db.php';
$retrieve = new RetrieveItem();
print_r($retrieve->retrieve_item());
Rather than extend the class, how can I access the Database constructor in the cleanest possible way?
Any help or guidance would be much appreciated.
This amended code is still not working:
Argument 1 passed to RetrieveItem::__construct() must be an instance of Database, none given:
class Database {
public $host = '127.0.0.1';
public $username = 'root';
public $password = '';
public $dbname = 'example';
function __construct(){
$this->connect = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
}
}
class RetrieveItem {
private $_db;
public function __construct(Database $database){
$this->_db = $database;
}
public function retrieve_item(){
$query = $this->connect->prepare("SELECT * FROM posts");
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
}
In use:
include 'db.php';
$database = new Database();
$retrieve = new RetrieveItem($database);
print_r($retrieve->retrieve_item());
As you said, with plain dependency injection
class RetrieveItem {
private $_db;
public function __construct(Database $db) {
$this->_db = $db;
}
}
For easier use, you can abstract the injection in container, or, at least, has one super class that recieves the injection.
A dependency injection is so easy but it sounds complicated.
$class1 = new firstclass();
$class2 = new secondclass($class1); //This is a dependency injection.
class firstclass{
private $var1;
private $var2;
public function __construct(){
$this->var1 = "hello";
$this->var2 = "world";
}
public function getvar1(){
return $this->var1;
} //imagine a second one like this for var2;
}
class secondclass{
private $fc; //will hold first class object or the dependency.
public function __construct($firstclassobject){
$this->fc = $firstclassobject;
echo $this->fc->getvar1(); //call dependency methods like this.
echo $this->fc->getvar2();
} //echoes helloworld
}
So you pretty much put an object of one class and asign it to a field in your other class.
for your edit
set this line in your database class at the top.
public connect; //add to dbclass
Then do this in your function
public function retrieve_item(){
$connect = $this->db->connect; //added this
$query = $connect->prepare("SELECT * FROM posts"); //changed this
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
class Database {
public $host = '127.0.0.1';
public $username = 'root';
public $password = '';
public $dbname = 'example';
public $connect;
function __construct(){
$this->connect = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
}
}
class RetrieveItem {
private $connect;
public function __construct(&$db){
$this -> connect = $db -> connect;
}
function retrieve_item(){
$query = $this->connect->prepare("SELECT * FROM posts");
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
}
// Usage
$db = new Database();
$retrieve_item = new RetrieveItem($db);
Here in Retrieve Item we tried to send the database object as a refereneced variable rather sending a copy of its, which happens to be a good way of passing connection to your operable classes

Simple PHP OOP and MySQLI

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.

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;
}
}

Categories