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);
Related
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);
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();
?>
I wanna get data on table and write a class. But this class doesn't work because pdo doesn't access. How can I get table data with this class?
$db = new PDO("mysql:host=localhost;dbname=xxx;charset=utf8", "xxx", "xxx");
class uye extends PDO{
var $id;
var $kadi;
function cek($id){
$query = $db->query("SELECT * FROM btc WHERE id='{$id}'", PDO::FETCH_ASSOC);
if ( $query->rowCount() ) {
foreach( $query as $row ){
$this->id=$row["id"];
$this->kadi=$row["kadi"];
}
}
}
}
$bilgiler=new uye;
$bilgiler->cek(1);
echo $bilgiler->kadi;
So I'm running this off of fetching all data as I dont know where you're getting $id from.
I generally break my code up into files and folders as I found this easier to work with and others to work on.
// database connection file (dbc.php)
class Database
{
private $host = "127.0.0.1";
private $db = "";
private $user = "";
private $password = "";
public $conn;
public function dbConnect()
{
$this->conn = null;
try
{
$this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db, $this->user, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $exception)
{
echo "Connection error: " . $exception->getMessage();
}
return $this->conn;
}
}
I then make a common file, this is where you can store all of your frequently used functions or your static functions
// Common file (common.php)
require_once('dbc.php');
class DBCommon
{
private $conn;
public function __construct()
{
$database = new Database();
$db = $database->dbConnect();
$this->conn = $db;
}
public function run($sql)
{
$stmt = $this->conn->prepare($sql);
return $stmt;
}
}
So to explain this a little more, you will see a function of run() this is just to save the tedious $this->conn->prepare on every query.. Now you can run $this->run()
The next would be your class file.. this is where your logic goes:
// your class file... (class.btc.php)
require_once "common.php";
class BTC extends DBCommon
{
public function getQuery()
{
$stmt = $this->run("SELECT * FROM `btc`");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_OBJ))
{
$rows[] = $row;
}
return $rows;
}
}
Self explanatory..
And then your calling method.. Lets say index.php
// File you're calling your class from (index.php)
require_once "class.btc.php";
$fetch = new BTC();
$returnData = $fetch->getQuery();
foreach ($returnData as $data)
{
echo
"<p>$data->something</p>
<p>$data->somethingElse</p>";
}
It seems a little long winded I know, but the time you'll save overall will help!
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.
I'm very new to php constructors I know of from java. But for some reason, this one is not running. I am following a tutorial and I can't seem to get a 1 only a 0. Here are the two scripts involved:
<?php
class dbConnection{
protected $db_conn;
public $db_name = 'todo';
public $db_user = 'root';
public $db_pass = '';
public $db_host = 'localhost';
function connect(){
try{
$this->db_conn = new PDO("mysql:host=$this->db_host;db_name=$this->db_name",$this->db_user,$this->db_pass);
return $this->db_conn;
}
catch(PDOException $e)
{
return $e->getMessage();
}
}
}
?>
<?php
include_once( 'class.database.php' );
class ManageUsers {
public $link;
public $constructed;
function ManageUsers(){
$db_connection = new dbConnection();
$this->link = $db_connection->connect();
return $this->link;
}
function registerUser($username,$password,$ip_address,$time,$date){
$query = $this->link->prepare("INSERT INTO users (username,password,ip_address,time,date) VALUES (?,?,?,?,?)");
$values = array($username,$password,$ip_address,$time,$date);
$query->execute($values);
$counts = $query->rowCount();
return $counts;
}
}
$users = new ManageUsers();
echo $users->registerUser('bob','bob','127.0.0.1','10:00','29-02-2012');
?>
You should try to use __construct() instead for ManageUsers().
Also, I'm not quite sure what you're trying to achieve in your constructor (see my markings below):
function ManageUsers(){
$db_connection = new dbConnection();
$this->link = $db_connection->connect();
return $this->link; //<--?
$constructed = 'Construct'; //<--?
}
Agreed - the method you are using is the old school PHP4 method - you should use the __construct() method as explained above.
http://www.php.net/manual/en/language.oop5.decon.php
This page explains construct() & destruct() in PHP 5
// constructor
function __construct() {
ManageUsers();
}
function ManageUsers(){
$db_connection = new dbConnection();
$this->link = $db_connection->connect();
$constructed = 'Construct';
}
You cannot return from a constructor tho, maybe you can want to make link a public property and access it directly like this
$user = new ManageUsers();
$link = $user->$link;