Is this right way to use php oop and mysqli? - php

I am not very experienced in php oop. Moreover, when mysqli comes with php oop, it make me more confused about using it in best efficient way. Anyway, first look at my connection class:
<?php
//connectionclass.php
class connection{
public $conn;
public $warn;
public $err;
function __construct(){
$this->connect();
}
private function connect(){
$this->conn = # new mysqli('localhost', 'sever_user', 'user_password');
if ($this->conn->connect_error) {
$this->conn = FALSE;
$this->warn = '<br />Failed to connect database! Please try again later';
}
}
public function get_data($qry){
$result = $this->conn->query($qry);
if($result->num_rows>=1){
return $result;
}else{
$this->err = $this->conn->error;
return FALSE;
}
$result->free();
}
public function post_data($qry){
$this->conn->query($qry);
if($this->conn->affected_rows>=1){
return TRUE;
}else{
$this->err = $this->conn->error;
return FALSE;
}
}
}
?>
Now please structure of a php page which uses mysql database to store and get data:
<?php
//login.php
include('/include/connectionclass.php');
$db = new connection();
$query = "SELECT * FROM USERS WHERE user_country='India'";
$data = $db->get_data($query);
if($data){
while($row=$data->fetch_assoc()){
echo 'User Name: ':.$row["user_name"].' Age: '.$row["age"];
}
}
?>
So my login.php uses connection class to get data about users. All the things are running well. But one things made me confused. In connectionclass.php $this->conn is itself an object as it calls new mysqli. So this is an object inside another object $db. Moreover, When I am using $data = $db->get_data($query);, a result set is created inside object $db by method get_data, then this result set is copied into a variable $data inside login.php page.
So according to me, actually two result sets/data sets are creating here, one inside db object and one inside login page. Is it right way to use mysqli and php to get dataset from mysql database? Will it use more memory and server resources when the dataset is larger (when have to get large amount of data for many users)?
If it is not right way, please explain your points and please give me code which can be used efficiently for php oop and mysqli.

Related

How to debug my PDO database class? [duplicate]

This question already has answers here:
How do I parse object data from MySQL database using PHP PDO?
(1 answer)
PHP/PDO - use variable assignment as fetch-statement
(4 answers)
Closed 5 years ago.
After 10 years away from PHP coding, am getting back in the swing of things going through tutorials. I discovered things have changed, and PDO is the new standard to connect to MySQL.
I set up small projects. I am trying to build my own Class database, and things get all sideways, and I don't figure out why.
So here is my database class:
<?PHP
$Db = new database;
class database
{
/////////////
//Attributs//
/////////////
private $db_host;
private $db_user;
private $db_pass;
private $db_name;
private $bdd;
/////////////////////
// internal process//
/////////////////////
private function activateDB()
{
$this->checkList();
$this->dbInitilisation();
$this->dbConnection();
}
////////////////////////
//Check Websiteconfig//
////////////////////////
private function checkList()
{
if(!file_exists('website-config.ini')){
die('missing configuration file.');
}
}
///////////
//Db init//
///////////
private function dbInitilisation()
{
// Load config file for database connection info
$config = parse_ini_file("website-config.ini");
$this->db_host=$config['db_host'];
$this->db_user=$config['db_login'];
$this->db_pass=$config['db_password'];
$this->db_name=$config['db_name'];
}
/////////////////
//Db connection//
/////////////////
private function dbConnection()
{
try
{
$this->bdd = new PDO('mysql:host='.$this->db_host.';dbname='.$this->db_name.';charset=utf8', 'root', '');
$this->bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
die('error '.$e);
}
}
public function dbQuery($user_query, $parameters)
{
$this->activateDB();
$query = $this->bdd->prepare($user_query);
$query->execute($parameters);
$query->fetch();
return $query;
}
}
?>
and, here is how I am calling it:
$values[':user_id']='1';
$result=($Db->dbQuery('SELECT user_username FROM user WHERE user_id = :user_id',$values));
print_r($result);
When I was not using pdo, and writing my function like normal, I had what I wanted. Now, not any more.
Does anyone has a clue on what I am doing wrong? Do you have any kind of comment on how to improve my overall stuff?
PS: I did read around before coming here (like here: http://php.net/manual/fr/pdostatement.fetch.php (I thought my issue were maybe with the type of fetch, but again, when not in OOP, my code runs ok as it is.) Or here PHP: Database Connection Class Constructor Method but the solution give here is to go on someone else code library, and not allowing to understand what I am actually doing wrong.

Smartest way to access database with sql via functions in php

I'm making a small CMS for some fun and practice. And I've come across this problem where I have to access a database multiple times in different functions. And the way I do it now by making a new prepared statement with the code and all to access the database in the function doesn't seem very convenient since the code is very repetitive and I'm using mostly the same code for each function. So how would I go about creating a class maybe or some functions that reduce the amount of code used in the functions that gather the information from that database? I currently use the following queries in SQL
SELECT
UPDATE
INSERT
DELETE
So mostly the basic ones. The code I'm using is basic PHP code where I'm using prepared statements to access my database like this:
// Create database connection
$con = db_connect();
// Initialize $error variable for errors
$error = "";
if ($stmt = $con->prepare("SELECT * FROM profiles WHERE username = ?")) {
// Bind the $username variable to the parameter in the query
$stmt->bind_param('s', $username);
// Execute the prepared query
$stmt->execute();
$stmt->store_result();
// Assign the data recieved from the database (if any)
$stmt->bind_result($data);
$stmt->fetch();
if ($stmt->num_rows == 1) {
if (!empty($stmt->error)) {
printf("Error: %s.\n", $stmt->error);
return false;
}
// Query successful
} else {
$error .= "User doesn't exist";
return false;
}
} else {
$error .= 'Could not connect to database';
return false;
}
To me this seems like pretty easy to use code, but when you have to paste it again and again in different functions, then it gets a bit frustrating.
You should use Dependency Injection.
By injecting the Database connection into a Profile's class, you have much more maneuverability to do what you please.
You can change that database to whatever you want (MongoDB, Cassandra, MySQL).
You are only declaring the connection once; which performs better and faster
Makes it easier to test and develop (echo & print_r & unit testing)
Handel exceptions in 1 place
Database is loosely couple with rest of code.
ex:
class Profile {
private $db = null;
public function __construct($db Database) {
$this->db = $db;
}
public function getProfile() {
//ish....
$this->db->query("SELECT * FROM profiles WHERE username = ?");
}
public function insert() {
...
}
public function update() {
...
}
public function delete() {
...
}
}
To access the database, I would do something like this and also implement what you have (prepared statements are great!):
class Database {
private $conn = null;
public function __construct($db Database) {
$this->conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->conn;
}
public function query($sql) {
try {
return $conn->query($sql);
} catch (Exception $e) {
echo $e->getMessage();
}
}
}
A very good explaination and tutorial can be found here: http://code.tutsplus.com/tutorials/dependency-injection-huh--net-26903

can't connect to db through another class

I have an issue that I can't figure out. I have a class Database which if I use it directly I connect to db regularly. I have another class Categories and I want to call a Database object. The problem is that if I call $db->connect in categories does not work. I tried call mysql_connect directly in Categories and it works fine!
Why can't I use $db->connect (the error is Access denied for user 'user'#'0.0.0.0' (using password: YES).
My code in class Database is:
public function connect($new_link=false){
$this->link_id = #mysql_connect($this->server,$this->user,$this->pass,$new_link);
echo "<br/>link_id = ".$this->link_id;
if (!$this->link_id){//open failed
$this->oops("Could not connect to server: <b>$this->server</b>.");
}
else{
echo "Connected to server <br/>";
}
if(!#mysql_select_db($this->database, $this->link_id)){//no database
$this->oops("Could not open database: <b>$this->database</b>.");
}
else{
echo "Database opened <br/>";
}
// unset the data so it can't be dumped
$this->server='';
$this->user='';
$this->pass='';
$this->database='';
}#-#connect()
My code in class Category is:
public static function selectAll() { // SELECT All Function
$db = Database::obtain();
// connect to the server
$db->connect();
$sql = "SELECT * FROM productCategory";
$rows = $db->fetch_array($sql);
return $rows;
}
Database::obtain code
public static function obtain($server=null, $user=null, $pass=null, $database=null){
if (!self::$instance){
self::$instance = new Database($server, $user, $pass, $database);
}
return self::$instance;
}#-#obtain()
Am I doing sth wrong, that I can't see?
Well, the error message is "Access denied for user 'user'#'0.0.0.0'"
That means when you instantiate your class with $db = Database::obtain(); You don't set the values for server, user, pass, database. Probably the class Database implements a singleton pattern, and the method obtain() just returns the instance without any properties set.

OOP - Connecting to database via __construct [duplicate]

This question already has an answer here:
PHP: mysql_connect not returning FALSE
(1 answer)
Closed 8 years ago.
I'm very new to OOP and am trying to learn it. So please excuse my noobness. I'm trying to connect to mysql and to test whether the connection is successful or not, I'm using if-else conditions.
Surprisingly, the mysql_connect is always returning true even on passing wrong login credentials. Now I'm trying to figure out why it does and after spending about 20 minutes, I gave up. Hence, I came here to seek the help of the community. Here is my code:
class test
{
private $host = 'localhost';
private $username = 'root2'; // using wrong username on purpose
private $password = '';
private $db = 'dummy';
private $myConn;
public function __construct()
{
$conn = mysql_connect($this->host, $this->username, $this->password);
if(!$conn)
{
die('Connection failed'); // this doesn't execute
}
else
{
$this->myConn = $conn;
$dbhandle = mysql_select_db($this->db, $this->myConn);
if(! $dbhandle)
{
die('Connection successful, but database not found'); // but this gets printed instead
}
}
}
}
$test = new test();
Please don't use the mysql_* functions, there are many, many reasons why - which are well documented online. They are also deprecated and due to be removed.
You'd be much better off using PDO!
Also I'd strongly advise abstracting this database code into a dedicated database class, which can be injected where necessary.
On-topic:
That code snippet seems to work for me, have you tried var_dumping $conn? Does that user have correct rights?
I also hope that you don't have a production server which allows root login without a password!
Ignoring the fact that you're using mysql_* functions rather than mysqli or pdo functions, you should utilise exceptions in OOP code rather than die(). Other than that, I can't replicate your problem - it may be that your mysql server is set up to accept passwordless logins.
class test
{
private $host = 'localhost';
private $username = 'root2'; // using wrong username on purpose
private $password = '';
private $db = 'dummy';
private $myConn;
public function __construct()
{
// returns false on failure
$conn = mysql_connect($this->host, $this->username, $this->password);
if(!$conn)
{
throw new RuntimeException('Connection failed'); // this doesn't execute
}
else
{
$this->myConn = $conn;
$dbhandle = mysql_select_db($this->db, $this->myConn);
if (!$dbhandle)
{
throw new RuntimeException('Connection successful, but database not found'); // but this gets printed instead
}
}
}
}
try {
$test = new test();
} catch (RuntimeException $ex) {
die($ex->getMessage());
}

mysqli_real_escape_string: Non-Object in HelperFunction

I have a question regarding the following Code. It's a PHP-Class which I plan to use as a DB-Handler. For the INSERT I'm using a little helper function, mainly because I'm too lazy to sanitize the strings from hand. Here is the Code:
<?php
class Db{
/*
* Configure DB settings here, make sure php is in good health. Check phpinfo();
*/
private $MYSQL_HOST = 'localhost';
private $MYSQL_USER = 'root';
private $MYSQL_PASS = '******';
private $db;
function select($selected_db, $sql){
//Create new object out of connection to db
$this->db = #new mysqli($this->MYSQL_HOST, $this->MYSQL_USER, $this->MYSQL_PASS, $selected_db);
//If there aren't any errors
if(mysqli_connect_errno() == 0){
$result = $this->db->query($sql);
if($result){
$result = $result->fetch_array(MYSQLI_ASSOC);
}else{
echo "There is a problem with the query";
}
} else { //If you couldn't connect to DB at all
die("No connection possible: " . mysqli_connect_error());
}
//Close connection
$this->db->close();
return $result;
}
function dirtyLittleHelper($string){
//Change each character into its HTML equivalent
$string = htmlentities($string);
//Create a legal SQL string from input
$string = $this->db->mysqli_real_escape_string($string);
return $string;
}
}
?>
Now for the error I get:
Fatal error: Call to a member function mysqli_real_escape_string() on a non-object in /path/to/file/db_class.php on line 35
The Question is simply why? I don't want to use the strings unsanitized and I don't want to use mysql_real_escape_string since it's deprecated.
Since this is my first time working with SQL, I'm taking the risk to post a duplicate of a question. It is important for me to learn it proper and not just use a version that works, leaving ways in to the database open.
Thanks in advance,
stiller_leser
EDIT
Thanks, I guess I'm going with elusive's hint. I did not know, that it prepare does that. Anyway just to check, a proper insert-function could look like that right?
function insert($selected_db, $sql){
//Create new object out of connection to db
$this->db = #new mysqli($this->MYSQL_HOST, $this->MYSQL_USER, $this->MYSQL_PASS, $selected_db);
//If there aren't any errors
if(mysqli_connect_errno() == 0){
//If you could prepare query
if($result = $db->prepare( $sql )){
//Execute query
$result->execute();
} else { //If you couldn't prepare query
echo "There is a problem with the query";
}
} else { //If you couldn't connect to DB at all
die("No connection possible: " . mysqli_connect_error());
}
//Close connection
$this->db->close();
The call should instead be like this
$string = $this->db->real_escape_string($string);
Please check the documentation.
Alternative solution would be:
$string = mysqli_real_escape_string($this->db, $string);
Your class seems inconsistent and unusable to me.
You are passing $selected_db to your functions, but never use it
instead of that you are creating a new connection for the every query you run(!)
there is no use for that little helper function can be seen.
and I suspect it's still unusable and unsafe anyway
calling prepare/execute doesn't protect your queries by itself. it have to be fed with variables to be bound to do any good
binding variables in mysqli is A PAIN
that's why you've been told to use PDO
Also, with adequately implemented placeholders, you won't need no special functions like delete(). update() and such, using conventional query() method to run them all queries:
$data = array('name' => 'John','surname'=>'doe', ...);
$db->query("INSERT INTO ?n SET ?u", $table, $data);
So, if you need PHP-Class to use as a DB-Handler, here is a SafeMysql which is written with some knowledge and experience

Categories