PHP oop how to call another class method in a easier way? - php

I am new to php OOP. I have a question regarding my situation.
db.php
class db{
protected $db_host;
protected $db_name;
protected $db_user_name;
protected $db_pass;
public function __construct() {
$this->db_host="localhost";
$this->db_name="bs";
$this->db_user_name="root";
$this->db_pass="";
}
public function conn(){
try {
$conn = new PDO("mysql:host=$this->db_host;dbname=$this->db_name", $this->db_user_name="root", $this->db_pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $conn;
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
}
}
item.php
require "../../includes/db.php";
class item{
public $user_uid;
public $last_id;
public $display_item;
public $iid;
protected $item_id;
protected $item_name;
protected $item_price;
protected $item_quantity;
public function add_item($uid,$item_id,$item_n,$item_p,$item_q){
$db = new db();
$conn=$db->conn();
$this->user_uid=$uid;
$this->item_id=$item_id;
$this->item_name=$item_n;
$this->item_price=$item_p;
$this->item_quantity=$item_q;
try {
$sql = "INSERT item(uid,item_id,item_name,item_price,item_quantity)
VALUES('$this->user_uid','$this->item_id','$this->item_name','$this->item_price','$this->item_quantity')";
$conn->exec($sql);
$this->last_id=$conn->lastInsertId();
}
catch(PDOException $e){
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
}
public function display_item($uid){
$db = new db();
$conn=$db->conn();
$this->user_uid=$uid;
try{
$sql="SELECT * FROM item where uid='$this->user_uid'";
$statement=$conn->query($sql);
while($row=$statement->fetch()){
$this->iid[]=$row['iid'];
$this->display_item[]=[$row['item_id'],$row['item_name'],$row['item_price'],$row['item_quantity']];
}
}
catch(PDOException $e){
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
}
}
as you can see from item.php , i have to call
$db = new db();
$conn=$db->conn();
in add_item() and display_item() .
So that means every method that I have to access to database connection, i have to do that. Is there a easier way to do that by not creating $db = new db() in other class by modifying my codes?
OR
Did i miss out some functions that PHP can do that?
My desired way of doing it
require "../../includes/db.php";
$db = new db();
$conn=$db->conn();
class item{
...
...
public function add_item($uid,$item_id,$item_n,$item_p,$item_q){
try {
$sql = "INSERT item(uid,item_id,item_name,item_price,item_quantity)
VALUES('$this->user_uid','$this->item_id','$this->item_name','$this->item_price','$this->item_quantity')";
$conn->exec($sql);
}
public function display_item($uid){
....
try{
$sql="SELECT * FROM item where uid='$this->user_uid'";
$statement=$conn->query($sql);
so that i only declare 1 time()
$db = new db();
$conn=$db->conn();
in class item() and use it for the rest of methods.

Just add the connection in the constructor. Add the necessary property as well:
class db
{
protected $db_host;
protected $db_name;
protected $db_user_name;
protected $db_pass;
protected $db_conn; // add me here
Then inside the constructor, use the credentials there to connect. So that when you create the object, its already connected, you'll just use the property connection for your executing queries and stuff:
public function __construct()
{
$this->db_host = "localhost";
$this->db_name = "bs";
$this->db_user_name = "root";
$this->db_pass = "";
// connect
try {
$this->db_conn = new PDO("mysql:host=$this->db_host;dbname=$this->db_name", $this->db_user_name="root", $this->db_pass);
$this->db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db_conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
exit;
}
}
Then, extend the db class in item. You can now use db's db_conn property inside item class.
class item extends db
{
public $user_uid;
public $last_id;
public $display_item;
public $iid;
protected $item_id;
protected $item_name;
protected $item_price;
protected $item_quantity;
public function display_item($uid)
{
try {
$stmt = $this->db_conn->prepare('SELECT * FROM item WHERE uid = :uid');
$stmt->bindValue(':uid', $uid);
$stmt->execute();
foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$this->iid[] = $row['iid'];
$this->display_item[] = [$row['item_id'], $row['item_name'], $row['item_price'], $row['item_quantity']];
}
} catch(PDOException $e) {
echo $e->getMessage();
exit;
}
}
}
Sidenote: I've added prepared statements on top

Related

PHP A Good way to pass the PDO Object into other Main classes

im new to PHP OOP, now i was woundering if there is a better way to use the Database Class then just extending it over all.
For Example i am having 3 main classes: Employee, Customer, Article. each of this classes have a subclasses which extends form. what i have done until now is extand the Db class on each of these 3 main classes.
My DB class:
class DbController{
private $serverName;
private $userName;
private $userPass;
private $dbName;
private $charSet;
private $pdo;
protected function __construct() {
try {
$this->serverName = "localhost";
$this->userName = "blabla";
$this->userPass = "***";
$this->dbName = "blabla";
$this->charSet = "utf8mb4";
$dsn = "mysql:host=".$this->serverName."; dbname=".$this->dbName."; charset=".$this->charSet;
$pdo = new PDO($dsn, $this->userName, $this->userPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo = $pdo;
return $pdo;
} catch (PDOException $err) {
die($err->getMessage());
}
}
protected function getPdo(){
return $this->pdo;
}
public function __debugInfo(){
$properties = get_object_vars($this);
unset($properties['serverName']);
unset($properties['userName']);
unset($properties['userPass']);
unset($properties['pdo']);
unset($properties['dbName']);
unset($properties['charSet']);
return $properties;
}
}
one Of the Main classes (Employee):
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
include_once "DbController.cls.php";
class Employee{
public $id;
protected $name;
protected $username;
protected $scoore;
protected $dbTable = "employee";
protected PDO $pdo;
public function __construct($info = NULL) {
// pls notice that The DbController() is a protected Constructor.
$this->pdo = new DbController();
if (isset($info)) {
$this->id = $info["id"];
$this->name = $info["name"];
$this->username = $info["username"];
$this->scoore = $info["scoore"];
}
}
// Setters and Getters ......
then there is a sub class of Employee called EmployeeMng. this subclass contains functions such as login or signup. also this subclass handles the POST requests coming froom the client side.
include_once "../classes/Employee.cls.php";
$_POST = json_decode(file_get_contents('php://input'), true);
class EmployeeManagement extends Employee{
public function __construct() {
if (isset($_SESSION['empID'])) {
parent::__construct();
parent::__construct($this->fetchEmpInfo($_SESSION['empID']));
} else {
parent::__construct();
}
}
public function signIn($username, $password){
$retrunArray = array('code' => 0, 'msg' => "No Data Returned");
$checkCredential = $this->checkCredential($username, $password);
if ($checkCredential['code'] == 1) {
try {
$getEmpID = $this->pdo->prepare("SELECT `id` FROM `employee` WHERE `username`=? AND `password`=? LIMIT 1;");
$getEmpID->execute([$username, $password]);
$empId = $getEmpID->fetch(PDO::FETCH_ASSOC)['id'];
$_SESSION['empID'] = $empId;
$retrunArray['code'] = 1;
$retrunArray['msg'] = "Erfolgreich eingeloggt";
return $retrunArray;
} catch (PDOException $err) {
$retrunArray['code'] = 0;
$retrunArray['msg'] = $err->getMessage();
return $retrunArray;
}
} else{
// In case of DB Error
return $checkCredential;
}
}
// Request Handler Begin
$employeeService = new EmployeeManagement();
header('Content-Type: application/json');
// Login:
if (isset($_POST["signIn"])) {
$signIn = $employeeService->signIn($_POST["username"], $_POST["password"]);
echo json_encode($signIn);
}
Now i tried to declare the db class in the Employee constructor. but i keep getting the error Call to protected DbController::__construct() from scope Employee. is there a clean way to do that?
In general, you'd create your database object outside of this class and then inject it as a parameter. This is called Dependency Injection and is a Good Thing™.
Then you'd use that parameter within your class-specific methods. So your employee class would look something like this:
class Employee
{
protected $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function find($id)
{
// or whatever your query looks like
$stmt = $this->db->query('SELECT * FROM EMPLOYEE WHERE id = :id');
// $row = ...
return $row;
}
public function getAll()
{
$stmt = $this->db->query('SELECT * FROM EMPLOYEE');
// whatever
}
}
And then to use that class, you'd instantiate a database object, and then pass that to the Employee:
$db = new PDO();
$employee = new Employee($db);
$steve = $employee->find(1);
You should not do this:
class Employee
{
public $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
}
$db = new PDO();
$employee = new Employee($db);
$steve = $employee->db->query('...');
Or this:
class Employee extends PDO
{
// ...
}
$employee = new Employee($db);
$employee->query('...');
Inheritance is not the way to go here. If you inherit DbController each class will instantiate a new PDO connection.
Instead, instantiate DbController first, then call its getPDO() method to obtain a PDO connection object to pass into your other classes as a parameter to their constructors. You'll need to change the DbController method declaration to public instead of private
Like this:
class DbController{
private $serverName;
private $userName;
private $userPass;
private $dbName;
private $charSet;
private $pdo;
public function __construct() {
try {
$this->serverName = "localhost";
$this->userName = "blabla";
$this->userPass = "***";
$this->dbName = "blabla";
$this->charSet = "utf8mb4";
$dsn = "mysql:host=".$this->serverName."; dbname=".$this->dbName."; charset=".$this->charSet;
$pdo = new PDO($dsn, $this->userName, $this->userPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo = $pdo;
// return $pdo; No need for this. The constructor doesn't use it.
} catch (PDOException $err) {
die($err->getMessage());
}
}
public function getPdo(){
return $this->pdo;
}
}
class Employee {
private $PDO;
public function __construct(PDO $pdo) {
$this->PDO = $pdo
}
public function getEmployee($id) {
// get employee details using $this->PDO as your connection object
}
}
then your main program becomes something like
require_once('DbController.php');
require_once('Employee.php');
$DB = new DbController();
$emp = new Employee($DB->getPDO());
$id = 'some employee reference';
$employeeDetails = $emp->getEmployee($id);

Passing db object to php class oop style does not work

Simple classes using oop php, trying to pass db object (from db class) to another class ( category class ) so i can get the content from db .
db class db.php
class db {
//put your code here
private $hostname = "127.0.0.1";
private $dbname = "php_oop_crud";
private $username = "root";
private $password = "";
public $conn;
public $status = 0;
public function getConnection() {
$this->conn = null;
try {
$this->conn = new PDO("mysql:host:$this->hostname;dbname=$this->dbname", $this->username, $this->password);
// this return null if unsccessfull
$this->status = $this->conn->getAttribute(PDO::ATTR_CONNECTION_STATUS);
if ($this->status) {
echo "connected to db : " . $this->status;
return $this->conn;
}
} catch (PDOException $ex) {
echo "Can't connect to db " . $this->status;
error_log("Ayman :: {{$ex->getMessage()}} - {{$ex->getFile()}} - {{$ex->getLine()}}");
return $this->conn;
}
}
}
pass db object to category class in index.php
// Create db connection pass it to product and category objects
$databaseConn = new db();
$db = $databaseConn->getConnection();
// create object and send database object to class
// now we need to call the function who crearte tha actual connection getConnection();
$category= new category($db);
$category->read();
category class category.php
<?php
class category {
//put your code here
private $databaseConn;
private $tabel_name = 'categories';
public $id;
public $name;
public function __construct($db) {
$this->databaseConn = $db;
}
public function read() {
$sql = 'SELECT * FROM categories';
$query = $this->databaseConn->prepare($sql);
$isok = $query->execute();
$row= $query->rowCount();
echo "row : " . $row;
var_dump($row);
echo "isok : " . $isok;
var_dump($isok);
if ($isok) {
echo "the red process is done and ok <br/> category table";
} else {
echo "Cant get category ";
var_dump($isok);
}
}
}
Now the var_dump($row) and var_dump($isok); are always false , mean while I can connect successfully to db
Credit for #ishegg , be careful when you construct your PDO .
// this will NOT work
$this->conn = new PDO("mysql:host:$this->hostname;dbname=$this->dbname", $this->username, $this->password);
// this will Work
$this->conn = new PDO("mysql:host=".$this->hostname.";dbname=".$this->dbname, $this->username, $this->password);

Call to undefined method in php

Here is my config.php
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'xxxx');
define('DB_USER', 'xxxx');
define('DB_PASS', 'xxxx');
?>
And It is DB.php
<?php
include 'config.php';
class DB {
public static $pdo;
public static function connection(){
if (!isset(self::$pdo)) {
try {
self::$pdo = new PDO('mysql:host='.DB_HOST.'; dbname ='.DB_NAME,DB_USER, DB_PASS);
}catch(PDOException $e){
echo $e->getMessage();
}
}
return self::$pdo;
}
public static function prepareOwn($sql){
return self::connection()->prepare($sql);
}
}
?>
3rd file is Student.php
<?php
include 'DB.php';
class Student {
public $table = 'student_info';
public function readAll(){
$sql = "SELECT * FROM $this->table";
$stmt = DB::prepareOwn($sql);
$stmt->execute();
return $stmt->fetchAll();
}
}
?>
But When I try to access readAll() from index.php using spl_autoload_register() Then I can see Fatal error: Call to undefined method DB::prepareOwn()
Can anyone help me to solve the problem??
Many thanks.
Sahidul
i copied your code into mine and saw your error. but as i guessed, first you will get an error with this line inside db.php:
return self::$pdo->prepare($sql);
Fatal error: Call to a member function prepare() on null
where prepare function came from? $pdo is just a static property in this class and it doesn't have a function called prepare! fix this line
Updated
the problem is you forgot to call connection method inside your prepareOwn. so your new prepareOwn function should be:
public static function prepareOwn($sql) {
self::connection();
return self::$pdo->prepare($sql);
}
i hope this code will work for you
class MySQLDatabase {
// Class attributes
private $host_name = "localhost";
private $database_name = "XXXXXXX";
private $database_username = "XXXXXXX";
private $database_password = "XXXXXXX";
private $is_connected;
private $connection;
private $statement ;
// construct
public function __construct() {
$this->open_connection();
}// End of construct
// connection method
public function open_connection() {
try {
$this->is_connected = TRUE ;
// PDO Connection
$this->connection = new PDO("mysql:host=".$this->host_name.";dbname=".$this->database_name.";charset=utf8",$this->database_username,$this->database_password);
// Error reporting
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES,FALSE);
} catch(PDOException $errors) {
$this->is_connected = FALSE ;
self::catch_errors($errors);
}
}// End of open connection method
// Get connection method
public function connection(){
return $this->connection ;
}
// Close connection method
public function close_connection() {
$this->connection = null;
}// End of close connection method
private static function catch_errors($errors) {
echo("<h4><p>" . $errors -> getMessage() . "</p></h4>");
die();
}
// query method
public function query($sql){
return $this->statement = $this->connection->prepare($sql);
}
}// End of database class
$database = new MySQLDatabase();
class Student {
protected static $table = 'My_table';
public function readAll(){
global $database;
try{
$sql = "SELECT * FROM ". self::$table;
$stmt = $database->query($sql);
$stmt->execute();
return $stmt;
}catch(PDOException $error){
echo("<h4><p>" . $errors -> getMessage() . "</p></h4>");
die();
}
}
}
$c = new Student();
$s = $c->readAll();
$stmt = $s->fetchAll(PDO::FETCH_ASSOC);
foreach($s as $v){
var_dump($v);
}

this PDO OOP Method is Correct?

dbConnect.php dbConnect Class page
class dbConnect {
/*
* initiate mysql database host,username,password,database name
*/
private $host;
private $dbName;
private $uname;
private $upass;
protected $con;
public function __construct($host, $database, $userName, $password) {
$this->host = $host;
$this->dbName = $database;
$this->uname = $userName;
$this->upass = $password;
$this->connectDB();
}
public function connectDB() {
/*
* #var $dsn mean data source name for pdo connection
*/
$dsn = "mysql:host=" . $this->host . ";port=3306;charset=utf8;dbname=" . $this->dbName;
try {
$this->con = new PDO($dsn, $this->uname, $this->upass);
$this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $this->con;
} catch (Exception $e) {
echo $e->getMessage();
}
}
}
sampleView.php sampleViews class page
/*
* include dbConnect class for this SampleView Class Page
*/
require_once 'class/dbConnect.php';
class sampleViews extends dbConnect {
public function __construct() {
parent::__construct('localhost', 'test2', 'root', '');
}
function chkConnection() {
/*
* dbConncect Class Connection variable access
*/
$dbcon = $this->con;
if ($dbcon) {
echo "successfully Connect database";
} else {
echo "sorry Could not be connect databsae";
}
}
/*
* In CRUD method implementation
* READ Method Sample
*/
function getData() {
$sql = "SELECT "
. "users.uid, "
. "users.uname, "
. "users.upass "
. "FROM "
. "users";
try {
$stmt = $this->con->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$array[] = $row;
}
return $array;
} catch (Exception $exc) {
echo $exc->getMessage();
}
}
/*
* CREATE Method
*/
function createSample() {
/*
* ini variable for insert
*/
$uname = "රුවන්";
$upass = "123";
//Sql insert query
$sql = "INSERT INTO `test2`.`users` (`uname`, `upass`) VALUES (:uname, :upass);";
try {
/*
* prepare Insert Query
*/
$createStmt = $this->con->prepare($sql);
/*
* bindParam method use for inset user data preventing sql injection
*/
$createStmt->bindParam(":uname", $uname, PDO::PARAM_STR, 150);
$createStmt->bindParam(":upass", $upass, PDO::PARAM_STR, 150);
/*
* execute insert query
*/
if ($createStmt->execute()) {
echo "successfully Inserted";
} else {
echo "sorry could not be inserted";
}
} catch (Exception $exc) {
echo $exc->getMessages();
}
}
}
My Problem was in the Second class which was sample Views. Parent Class $con variable can access but Net Beans IDE not Display any suggestions. prepare, execute, bind Param or any thing related to PDO db Connection. So i think my OOP method was Something Wrong or incorrect. Can anyone confirm if I am correct or not?
PHP is not strong typed - Method signature does not provide information about returned type. Variables do not have information about type. To help your IDE you have to use PHPDoc comments describing types.
Add a comment to $con property:
class dbConnect {
private $host;
private $dbName;
private $uname;
private $upass;
/**
* #var PDO
*/
protected $con;

PDO wont connect to the database

I've made a simple Database class to handle my database connections. But it's somehow not working? At first it wasn't working with MySQLi, so i tried PDO – which ain't working either.
I am however eager to make PDO work. I've already googled and searched here at StackOverflow, but without luck.
Here's my class:
class Database
{
// Local
protected $_host = "localhost";
protected $_user = "root";
protected $_pass = "root";
protected $_database = "hs";
protected $_connection;
// Construct
private function __construct()
{
try
{
$this->_connection = new PDO('mysql:host=localhost;dbname=hs', $this->_user, $this->_pass);
$this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo 'ERROR: ' . $e->getMessage();
}
}
public function login($usr, $pwd)
{
echo "hi";
}
}
And here's the execution:
if(isset($_POST['hs_login']))
{
$db = new Database;
$db->login($_POST['hs_username'], $_POST['hs_password']);
}
Thanks in advance! :)
Constructors are always public so change that like so:
class Database
{
// Local
protected $_host = "localhost";
protected $_user = "root";
protected $_pass = "root";
protected $_database = "hs";
protected $_connection;
// Construct
public function __construct()
{
try
{
$this->_connection = new PDO('mysql:host=localhost;dbname=hs', $this->_user, $this->_pass);
$this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo 'ERROR: ' . $e->getMessage();
}
}
public function login($usr, $pwd)
{
echo "hi";
}
}
Also, new Database is a method call so change that like so:
if(isset($_POST['hs_login']))
{
$db = new Database;
$db->login($_POST['hs_username'], $_POST['hs_password']);
}
Just wanted to point out, that there are some cases, when you can use private constructors. One of the practical use of them is with Databases, so it's relevant in your case as well. This design pattern is called Singleton pattern, and it relies on static method calls. You don't have to instantiate the class, as instantiation is handled by the class itself. I've put together an example:
<?php
class Database {
private static $instance = null;
private $db;
private static $last_result;
private function __construct() {
try {
$pdo_param = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$this->db = new PDO("mysql:host=YOUR_HOSTNAME;dbname=YOUR_DBNAME", "YOUR_USERNAME", "YOUR_PASSWORD", $pdo_param);
}
catch (PDOException $e) {
die($e->getMessage());
}
}
private static function getInstance() {
if (self::$instance == null) {
self::$instance = new self();
}
return self::$instance;
}
public static function query($sql) {
try {
$instance = self::getInstance();
$stmt = $instance->db->prepare($sql);
$stmt->execute();
self::$last_result = $stmt->fetchAll();
return self::$last_result;
}
catch (PDOException $e) {
die($e->getMessage());
}
}
public static function prepare($sql, $params) {
try {
$instance = self::getInstance();
$stmt = $instance->db->prepare($sql);
$stmt->execute($params);
self::$last_result = $stmt->fetchAll();
return self::$last_result;
}
catch (PDOException $e) {
die($e->getMessage());
}
}
}
$users = Database::query("SELECT * FROM users");
$filtered_users = Database::prepare("SELECT * FROM users WHERE username = :username", array(":username" => "john_doe"));
?>
<pre><?php
print_r($users);
print_r($filtered_users);
?></pre>
Singleton design pattern is really useful when you want to make sure, that there's ONLY ONE instance of a class in any given time.

Categories