Extend prepare() to Database class - php

I'm using:
> $db = new Database(); // my own Database class
> $result = $db -> query(sql);
> $row = $result -> fetch_array(MYSQLI_BOTH);
... and it does so fine and without any issues. But often times the sql is changed a bit based on user input (or can be altered by user input), which I've learned is extremely susceptible to sql injection. Yikes.
So I've been reading up on prepared statements, and I'm ready to switch to something more like this:
> $db = new Database();
> $stmt = $db -> prepare(sql);
> if ($stmt->execute(array($_GET['name'])) {
> > while ($row = $stmt->fetch()) {
> > > print_r($row);
> > }
> }
... which I've grabbed from example #3. I've altered my code to fit what I want but I'm getting Call to undefined method Database::prepare(), which I realize means I don't have the prepare() method available in the class. How can I extend this functionality? And if you don't mind, a little explanation might be helpful. :)
Edit: Here are the contents of my current Database class.
class Database {
private $link;
private $host = "#####";
private $username = "#####";
private $password = "####";
private $db = "####";
public function __construct(){
$this->link = new mysqli($this->host, $this->username, $this->password, $this->db)
OR die("There was a problem connecting to the database.");
return true;
}
public function query($query) {
$result = mysqli_query($this->link, $query);
if (!$result) die('Invalid query: ' . mysql_error());
return $result;
}
public function __destruct() {
mysqli_close($this->link)
OR die("There was a problem disconnecting from the database.");
}
}

Make Database extend mysqli
class Database extends mysqli
{
private $link;
private $host = "#####";
private $username = "#####";
private $password = "####";
private $db = "####";
public function __construct()
{
parent::__construct($this->host, $this->username, $this->password, $this->db)
OR die("There was a problem connecting to the database.");
}
public function __destruct()
{
mysqli_close($this->link)
OR die("There was a problem disconnecting from the database.");
}
}
Then you can call $db as if it's a mysqli object
$db = new Database();
$db->query($sql);
BUT you should just use the mysqli object directly if you're not really adding any functionality to the class...

Return the mysqli link from your construct or you could write a get method for returning the link.
public function __construct(){
$this->link = new mysqli($this->host, $this->username, $this->password, $this->db)
OR die("There was a problem connecting to the database.");
return $this->link;
}
And try this:
$db = new Database();
$name = $_GET['name']; // try validating the user input here
if( $stmt = $db->prepare($sql) ){
$stmt->bind_param("s", $name);
$stmt->execute();
while ($row = $stmt->fetch()) {
print_r($row);
}
}

Related

Passing a db connection in function

I have a database function and I am trying to figure out if passing the db info can be done in the same format as a new function
I was using a global db connect function but was told that is a bad practice so I wrote one of my functions as follows
function mysystem(mysqli $db){
//mystuff here
}
and it connects to the database with no issue.
my 2nd function is a little different I created a function to check if anything duplicate exists
function check_duplicate_entries($table, $column_name, $value){
$db = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
$stmt = $db->prepare("SELECT * FROM $table WHERE $column_name = ?");
$stmt->bind_param('s', $value);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
if (mysqli_num_rows($result) == 1) {
return true;
} else {
return false;
}
}
is there a way that I can pass my db info like the rest of my functions instead of calling a new db connection.
like this
function check_duplicate_entries(mysqli $db, $table, $column_name, $value){
Yes. It's common practice to use singleton pattern to handle this. This is code example for PDO, you can refactor it to mysqli
class MysqlConnector
{
private static $connection;
private function __construct()
{
}
public static function getConnection(): PDO
{
$username = "root";
$password = "";
$database = "blog";
$servername = "localhost";
if (!empty(self::$connection)) {
return self::$connection;
}
self::$connection = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
self::$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return self::$connection;
}
}
// now you can get your connection anywhere
// just make sure this class is available in your current namespace
$connection = MysqlConnector::getConnection();
$connection->query('SELECT COUNT(*) FROM articles');

Implementing mysqli procedural with a class

so recently I've been trying to use more procedural mysqli for practise, and have been looking at http://www.phpknowhow.com/mysql/mysqli-procedural-functions/, and also w3schools as reference, but i'm still having trouble so I thought I'd ask.
I have this database.php file where I have alot of stuff but the important stuff is
class Database{
public $host = DB_HOST;
public $username = DB_USER;
public $password = DB_PASS;
public $db_name = DB_NAME;
public $link;
public $error;
public function __construct(){
$this -> connect();
}
private function connect(){
$link = mysqli_connect($this->host,$this->username,$this->password,$this->db_name);
if(!$link){
echo "Failed".mysqli_error($link);
}
}
// create select method
public function select($query){
$result = mysqli_query($link,$query) or die("didnt work".mysqli_error($link));
if(mysqli_num_rows($result) > 0){
return $result;
}
else{
return false;
}
}
Now the way it currently works fine in my index.php file is simply by doing something like
$db = new Database();
//CREATe query
$query = "SELECT * FROM posts";
$posts = $db->select($query);
Is there any way to implement $posts = $db->select($query) with procedural functions? Before I have done stuff like mysqli_query($link,$query), but link is public here and inside a class so I can't do that, plus I want to access the function select . Thanks!
$link is not defined in your function select.
Modify your connect function:
private function connect() {
$this->link = mysqli_connect($this->host, $this->username, $this->password, $this->db_name);
if(!$this->link) {
echo "Failed: " . mysqli_error($this->link);
}
}
Now $this->link may be used in your select function:
public function select($query){
$result = mysqli_query($this->link, $query) or die("didn't work: " .mysqli_error($this->link));
if(mysqli_num_rows($result) > 0) {
return $result;
}
else{
return false;
}
}
I suggest you read the PHP OOP documenentation (at least the first chapters) to get a better understanding.

Querying JSON from PHP Function

I have a sequence order of PHP programming that i need to query from a table and insert it in a JSON array. I dont know where my mistake is but it just doesnt go through. please help me,
in dbinfo.inc.php,
define("ORA_CON_UN", "ADMIN");
define("ORA_CON_PW", "pass");
define("ORA_CON_DB", "192.168.100.195/finance");
class db {
private $conn;
private $lastId;
private static $instance;
private function _construct(){
$this->connect();
}
public static function create(){
if (!isset(self::$instance)) {
self::$instance = new db();
}
return self::$instance;
}
public function connect($dbconn = ORA_CON_DB, $dbuser = ORA_CON_UN, $dbpass = ORA_CON_PW){
$this->conn = oci_connect($dbuser, $dbpass, $dbconn);
}
}
and in DBFunction.php
include 'dbinfo.inc.php';
class Connection{
private $dbConnection;
public function _construct($dbConnection){
$this->dbConnection = $dbConnection;
}
function initConnection(){
$db = new db();
$dbConnection = $db->connect();
}
}
class PurchaseOrder {
private $job = '%';
private $subjob = '%';
public function _construct($job, $subjob){
$this->job = $job;
$this->subjob = $subjob;
}
function listPO($job, $subjob){
$conn = new Connection();
$conn->initConnection();
$sql = oci_parse($conn, 'SELECT VPI.PO_NO FROM VW_PO_INFO#WENFINANCE_WENLOGINV_LINK WHERE VPI.PROJECT_NO = ' .$job. ' AND VPI.PROJECT_NAME = ' .$subjob);
if (!$conn) {
$oerr = OCIError($conn);
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
exit();
} else {
echo 'CONNECTION SUCCEDED';
}
$rows = array();
while ($r = oci_fetch_assoc($sql)){
$rows[] = $r;
}
$listPO = json_encode($rows);
oci_execute($sql);
oci_close($conn);
}
}
and lastly, testDBFunction.php
include('DBFunction.php');
$queryOracle = new PurchaseOrder();
$queryOracle->listPO('W-IGG','');
var_dump($queryOracle);
and this is my error message,
Warning: oci_parse() expects parameter 1 to be resource, object given
in C:\xampp\htdocs\WeltesFinance\pages\lib\DBFunction.php on line 36
CONNECTION SUCCEDED Warning: oci_fetch_assoc() expects parameter 1 to
be resource, null given in
C:\xampp\htdocs\WeltesFinance\pages\lib\DBFunction.php on line 47
Warning: oci_execute() expects parameter 1 to be resource, null given
in C:\xampp\htdocs\WeltesFinance\pages\lib\DBFunction.php on line 52
object(PurchaseOrder)#1 (2) { ["job":"PurchaseOrder":private]=>
string(1) "%" ["subjob":"PurchaseOrder":private]=> string(1) "%" }
I dont know exactly where my error is, Please help me
UPDATE:
I made some more updates to your code and classes, here's relevant changes for each file.
dbinfo.inc.php
<?php
define("ORA_CON_UN", "ADMIN");
define("ORA_CON_PW", "pass");
define("ORA_CON_DB", "192.168.100.195/finance");
Class DbConnect{
private $user = null;
private $password = null;
private $db_string = null;
public function __construct(){
$this->user = ORA_CON_UN;
$this->password = ORA_CON_PW;
$this->db_string = ORA_CON_DB;
}
public function connect() {
$connection = oci_pconnect($this->user, $this->password, $this->db_string);
return $connection;
}
}
?>
DBfunction.php
<?php
include 'dbinfo.inc.php';
// there is no need for a Connection class unless you want further wrapping or something :-/
Class PurchaseOrder {
// ....
public function listPO($job,$subjob){
$db = new DbConnect();
$conn = $DbConnect->connect();
if (!$conn) {
// keep your code, throw error, exit
}
else{
// move all your database processing here
$sql = oci_parse($conn, 'SELECT VPI.PO_NO FROM VW_PO_INFO...');
// also note that you are passing an empty value for the $subjob parameter, thus making the query likely to fail
oci_execute($sql);
$rows = array();
while($r = oci_fetch_assoc($sql)){
$rows[] = $r;
}
$listPO = json_encode($rows);
oci_close($conn);
}
return $listPO; // you need to return $listPO in order to be able to dump it
}
// ....
}
testDBFunction.php
<?php
include('DBFunction.php');
$queryOracle = new PurchaseOrder();
// either pass what listPO() returns to a variable and dump it
$jsonResults = $queryOracle->listPO('W-IGG','');
var_dump($jsonResults);
// or dump the return directly
// var_dump($queryOracle->listPO('W-IGG',''));
You need to return the actual connection resource in the initConnection function
See the following inline comments
function initConnection(){
$db = new db();
// $dbConnection = $db->connect(); // this is not needed since you call connect from the
// constructor, but you need to return the connection
// see below the EDIT
// return the actual connection resource
// return $dbConnection;
return $db;
}
$sql = oci_parse($conn->initConnection(), 'SELECT VPI.PO_NO FROM VW_ ...')`
EDIT:
public function connect($dbconn = ORA_CON_DB, $dbuser = ORA_CON_UN, $dbpass = ORA_CON_PW){
$this->conn = oci_connect($dbuser, $dbpass, $dbconn);
return $this->conn;
}

Reusing a mysql connection in oop php [duplicate]

This question already has answers here:
Use global variables in a class
(4 answers)
Closed 7 years ago.
Solution taken from comment so I can't accept an answer for this to be closed. But I did post the actual solution that works for me below
I'm new to OOP and I just can't figure out, even after reading through quite few examples, how use the same mysql connection without using $GLOBALS.
If someone can explain it like I'm a two year old that would be super helpful.
This is my connection file.
$hostname = 'hostname';
$username = 'db';
$password = 'password';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=db", $username, $password);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
but then to use this in a class or a function I do this:
class basic {
function simple($id) {
$query = $GLOBALS['dbh']->query("SELECT * FROM table WHERE id = $id");
$row = $query->fetch(PDO::FETCH_OBJ);
$thing = $row->partoftable;
echo $thing;
}
}
$first = new basic();
$first->simple(12);
This of course will return what I'm looking for the $thing with the id of 12. But how do I do this without the GLOBALS['dbh'] to connect to the db?
Also feel free to rip anything else apart but just keep in mind this was the easiest example of what I'm talking about.
Thanks in advance.
This is the solution that works for me based on the comment below.
class basic {
function __construct($dbh)
{
$this->dbh = $dbh;
}
function simple($id) {
$query = $this->dbh->query("SELECT * FROM table WHERE id = $id");
$row = $query->fetch(PDO::FETCH_OBJ);
$thing = $row->partoftable;
echo $thing;
}
}
$first = new basic($dbh);
$first->simple(12);
Thanks. hope this helps someone else.
class basic {
var $CONNECTION;
function __construct($dbh) {
$this->CONNECTION = $dbh;
}
function simple($id) {
$conn = $this->CONNECTION;
$query = $conn->prepare("SELECT * FROM table WHERE id = $id");
$query->execute();
$row = $query->fetch(PDO::FETCH_OBJ);
$thing = $row->partoftable;
echo $thing;
}
}
//class ends you can use thae class like this
$hostname = 'hostname';
$username = 'db';
$password = 'password';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=db", $username, $password);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
$first = new basic($dbh);
$first->simple(12);
You can create a class for database connection :
class MysqlDB
{
private $conn;
public function __construct($hostName, $userName, $passWord, $databaseName)
{
$this->conn = new PDO("mysql:host=$hostName;dbname=$databaseName", $userName, $passWord);
}
public function query($id)
{
//This is just a sample query
$this->conn->query("SELECT * FROM table WHERE id = $id");
return $query->fetch(PDO::FETCH_OBJ);
}
}
And then you can use in another class like:
class basic {
private $dbConn;
function __construct(){
$dbConn = new MysqlDB('hostName', 'username', 'password', 'database')
}
function simple($id) {
$row = $dbConn->query($id);
$thing = $row->partoftable;
echo $thing;
}
}
You can also create a database connection in common class and extend it with you class
I like this solution:
class db_connection
{
public static $sql_object = NULL;
public function __construct()
{
if ($sql_object === NULL)
{
// Initialize self::$sql_object
}
}
}
Then you can use it with:
$db = new db_connection();
// Do something with $db->sql_object
Since $sql_object is static, it will be initialized only once, no matter how many times you use new db_connection().
<?php
define('DB_SERVER','localhost');
define('DB_USER','root');
define('DB_PASS' ,'');
define('DB_NAME', 'db');
class DB_con {
function __construct()
{
$conn = mysql_connect(DB_SERVER,DB_USER,DB_PASS) or die('localhost connection problem'.mysql_error());
mysql_select_db(DB_NAME, $conn);
}
public function insert($fname,$lname,)
{
$res = mysql_query("INSERT users(first_name,last_name,) VALUES('$fname','$lname')");
return $res;
}
public function select($id)
{
$res=mysql_query("SELECT * FROM users WHERE id = $id");
return $res;
}
} ?>

how to change mysql_connect() to PDO

This is my db connect class which is working with php5.3 but it not working after i updated the php5.4 and show error that it's expired.
class DB {
function DB() {
$this->host = "localhost";
$this->db = "dbtest";
$this->user = "root" ;
$this->pass = "password";
$this->link = mysql_connect($this->host, $this->user, $this->pass) or die("<br>Could not connect 1: " . mysql_error());
mysql_select_db($this->db);
}
function query($query) {
$result = mysql_query($query, $this->link) or die ("<br>Could not execute command 1: ".mysql_error());
return $result;
}
function thislink() {
return $this->link;
}
function close() {
mysql_close($this->link);
}
}
How to change it into PDO or mysqli so the wamp could use it
You can't.
Your class is not a black box, you have for example a public method that returns the MySQL link identifier:
function thislink() {
return $this->link;
}
If you change that to another database interface, you will run into problems when you call this method as it will not contain what the calling end is expecting.
The same applies to your public query() method:
function query($query) {
$result = mysql_query($query, $this->link) or die ("<br>Could not execute command 1: ".mysql_error());
return $result;
}
That returns a mysql resource in case of for example a SELECT statement so if you change that to msyqli or PDO, the calling side will not be able to handle it.
class DB {
function DB() {
$this->host = "localhost";
$this->db = "dbtest";
$this->user = "root" ;
$this->pass = "password";
$this->link = new PDO("mysql:host=$this->host;dbname=$this->db", $this->user, $this->pass);
}
function query($query) {
$result = $this->link->query($query);
return $result;
}
function thislink() {
return $this->link;
}
function close() {
$this->link = NULL;
}
}
Your class should look something like this:
Note that I change the constructor to __construct(), since in PHP 7 the other way what you used will be deprecated. Also I put the variables as arguments in the constructor with default values. I also enabled error mode for your PDO connection, only have it on in testing!, never in production.
<?php
class DB {
public $host;
public $db;
public $user;
public $pass;
private $link;
public function __construct($host = "localhost", $db = "dbtest", $user = "root", $pass = "password") {
$this->host = $host;
$this->db = $db;
$this->user = $user;
$this->pass = $pass;
try {
$this->link = new PDO("mysql:host={$this->host};dbname={$this->db}", $this->user, $this->pass);
$this->link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOExcpetion $e) {
echo $e->getMessage();
}
}
function query($query) {
$stmt = $this->link->prepare($query);
$stmt->execute();
return $stmt;
}
function thislink() {
return $this->link;
}
function close() {
$this->link = null;
}
}
?>
For more information about PDO see the manual: http://php.net/manual/en/book.pdo.php
You may also want to take a look into prepared statements.

Categories