I get the following error on my php pages that use database functions:
Warning: mysql_real_escape_string()
[function.mysql-real-escape-string]: Access denied for user
'apache'#'localhost'
I know I have to have a working connection to my database, but here is the 'problem'. The class that connects to my database looks like this:
class Database
{
private static $instance = null;
private static $conn;
private function __construct()
{
try {
self::$conn = new mysqli('localhost', 'root', 'user', 'database');
} catch (Exception $ex) {
$errorpager = new CustomPageGenerator();
$errorpager->generateErrorPage("Connection to database failed. Please try again later.");
}
}
public static function getInstance()
{
try {
if (self::$instance == null) {
self::$instance = new Database();
}
return self::$instance;
} catch (Exception $ex) {
$errorpager = new CustomPageGenerator();
$errorpager->generateErrorPage("Connection to database failed. Please try again later.");
return false;
}
}
public function query($sql)
{
try {
return self::$conn->query($sql);
} catch (Exception $ex) {
$errorpager = new CustomPageGenerator();
$errorpager->generateErrorPage("Connection to database failed. Please try again later.");
return false;
}
}
}
As you can see, I use the Singleton pattern for this. But even though I put a
Database::getInstance();
at the very beginning of my code to open up the connection I keep getting this error. How do I correctly open up the connection so that I can use the mysql_real_escape_string() function?
Thanks.
And here is le fix
Added this function to the Database class:
public static function getConnection()
{
self::getInstance();
return self::$conn;
}
Replaced every single mysql_real_escape_string( with mysqli_real_escape_string(Database::getConnection(),
I think the problem is that you are using mysql_real_escape_string().
That is from a different library than mysqli, maybe that's why there is no connection?
From the mysql_real_escape_string page in the PHP manual:
string mysql_real_escape_string ( string $unescaped_string [, resource
$link_identifier = NULL ] )
This is the definition for the second parameter, $link_identifier.
The MySQL connection. If the link identifier is not specified, the
last link opened by mysql_connect() is assumed. If no such link is
found, it will try to create one as if mysql_connect() was called with
no arguments. If no connection is found or established, an E_WARNING
level error is generated.
A possible, but kind of ugly solution, is to just add a wrapper to the real_escape_string method on your mysqli instance in your db singleton.
public function escapeString($value){
return $this->conn->real_escape_string($value);
}
Another alternative may be to use the procedural version for mysqli library (although, I haven't actually tried to see if you can mix both, but I think you can): mysqli_real_escape_string
Related
I work now on a project for learning i'm a beginner, i use singelton pattern to make sure, that there is just one PDO connection to the Data Base.
I made var_dump() for all possible connections to the Mysql and I founded that there were 10 objects of pdo.
how can i found, from where come all this objects?
Are 10 objects of PDO normal?
I wanted to use just one for all the project.
my singelton
<?php
namespace App\Database;
use PDO;
use PDOException;
class DataBase
{
private static $instance;
private PDO $pdo;
private function __construct()
{
try {
$db= parse_ini_file("..//..//..//config.ini");
#$db= parse_ini_file("..//..//config.ini");
$type = $db['type'];
$host = $db['host'];
$name = $db['name'];
$user = $db['user'];
$password = $db['password'];
$this->pdo = new PDO($type . ':host=' . $host . ';dbname=' . $name, $user, $password);
}
catch (PDOException $e) {
echo "there is an error";
die();
}
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $this->pdo;
}
private function __clone() {}
public static function getInstance()
{
if (!static::$instance) {
static::$instance = new DataBase();
}
return static::$instance;
}
public function getPdo(): PDO
{
return $this->pdo;
}
}
?>
then I made a connection of the pdo like this in another place, where I need to use pdo init.
function makePdo(){
$db= DataBase::getInstance();
$pdo= $db->getPdo();
var_dump($pdo);
return $pdo;
}
Thank you
10 connections are not normal, you should have only one to one DB. Use singleton pattern for database connection:
https://gist.github.com/jonashansen229/4534794
https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
In this case, you will have one connection and always will get it instead of creating duplicates.
No it should be only one object, the best way to implment it, is to create a separate config file to store your DBMS credentials as associative array, like mysql db_name, host .. etc.
Then create a config class to get those values by creating a static get method.
and finally use this get method inside your db constructor to get the credentials.
I'm pretty sure If you do that you'll get only one instance of PDO object.
Greetings good people,
I am running with some issue with OOP recently. First, I am looking to create CRUD Db class from scratch. This is a code:
class Database{
public static $link;
public $message;
public function __construct () {
try {
self::$link = mysqli_connect(HOST, USER, PASS, DB);
if (!self::$link) {
echo self::$link->error;
}
} catch (Exception $e) {
die(" Failed connecting to DB") ;
}
}
public static function query($SQL){
return self::$link->query($SQL);
}
public static function select($table, array $columns){
$columns=implode(",",$columns);
$result=self::query("SELECT $columns FROM $table");
return self::$link->fetch($result);
}
}
So the problem is this:
If I call my static select function like this:
Database::select('users', array('username'=>'user'));
It returns: Fatal error: Call to a member function query() on a non-object in ..
And if I debug connection like this: var_dump(Database::$link) it returns NULL
But if I place "$db = new Database();" above that line, it works?
Can anyone instruct me what I am doing wrong?
Thanks!
You are calling a static method. So, the object WILL NOT be instantiated. So, __construct() method WILL NOT be called. Which means $link property will not be populated.
Whatever you do, you need to connect to your DB. You can either call a static method connect() which will connect to database and populate $link, or make sure in every method that require the connection, that the connection is established:
public static function connect()
{
try {
self::$link = mysqli_connect(HOST, USER, PASS, DB);
if (!self::$link) {
echo self::$link->error;
}
} catch (Exception $e) {
die(" Failed connecting to DB") ;
}
}
public function select(SQL)
{
if (!static::$link) {
static::connect();
}
// your stuff
}
It's a good thing you want to learn. Before dealing with specific projects like that, you need to be comfortable with OOP: constructors/destructors, accessors, mutators, static methods, etc. It's important since it's the basis of all what you will want to do next.
This question already has answers here:
Can't connect to MySQL with PDO
(2 answers)
Closed 26 days ago.
I have to create getConnection function inside of Database class. The function should connect to a database using PDO object and returning it.
I have something like this:
class Database {
public function getConnection() {
$result = new PDO('mysql:host=localhost;dbname=demo', 'root', '');
return $result;
}
}
Is it correct? How can i know if i'm connected to database?
PDO will throw an exception if the connection attempt fails, so you can normalize that like this:
class Database {
private $_conn = null;
public function getConnection() {
if (!is_null($this->_conn)) {
return $this->_conn
}
$this->_conn = false;
try {
$this->_conn = new PDO('mysql:host=localhost;dbname=demo', 'root', '');
} catch(PDOException $e) { }
return $this->_conn;
}
}
$db = new Database();
$conn = $db->getConnection();
if (!$conn) {
die("Error connecting to the database");
}
$conn->whatever();
How can i know if i'm connected to database?
PDO will throw an exception in case of connection error.
Is it correct?
Nope, it's not a good idea, because the method is called getConnection while in reality it creates a connection. And a public property asks to call it in the application code, resulting multiple connections from the same script.
Besides, you should always set PDO in exception mode. And you should set charset in DSN as well.
Depends on the proposed use of this function the code could be
protected function connect()
{
$pdo = new PDO('mysql:host=localhost;dbname=demo;charset=utf8', 'root', '');
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
return $pdo;
}
if it's intended to be used only once in the constructor.
While for the getConnection() function you are bound to use a static variable ho hold the single instance of PDO.
Recently I took time to compile all the common mistakes for the database wrappers in the article Your first DB wrapper's childhood diseases. You may find this reading extremely useful.
I am using abstract class with PDO. I want to know if it is necessary to null the $conn variable every time, or if it does so itself when the scripts ends?
Can you also tell me, with this type of structure, what would be the best way to nullify $conn?
abstract class DB_Connection
{
protected static $tbl_admin = "prof_admin";
//protected static $tbl_admin = "prof_admin";
protected static function obj_db()
{
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "salmanshahid";
$conn = null;
try
{
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $conn;
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
}
protected static function select($query)
{
try
{
$conn = self::obj_db();
$stmt = $conn->prepare($query);
$stmt->execute();
// set the resulting array to associative
$stmt->setFetchMode(PDO::FETCH_ASSOC);
return $stmt->fetchAll();
}
catch(PDOException $e)
{
throw new Exception("Error In SELECT STATMENT: " . $e->getMessage());
}
}
protected static function insert($query)
{
try
{
$conn = self::obj_db();
$stmt = $conn->prepare($query);
$stmt->execute();
}
catch(PDOException $e)
{
throw new Exception("Error In INSERT STATMENT: " . $e->getMessage());
}
}
}
or if it does so itself when the scripts ends?
Yes, sure, PHP automatically close and clean up all the resources that has been opened during script execution, so, don't worry to close it manually.
Anyway, to nullify conn, just nullify it: $this->conn = NULL;
But all that stuff is utterly negligible compared to the other problems of your class, which is insecure, inefficient and unusable.
First of all, I have no idea why would you want to make this class abstract. Abstract classes are prototype classes, used to be source of other classes. But a database wrapper is rather a ready to use final class. I see no point in making it abstract.
Error reporting is also superfluous and inconsistent. Adding "Error In SELECT STATMENT" to the error message is quite useless. While connection error handling is plainly wrong. Instead, let PDO to throw an exception and just let it go. It will be handled the same way as any other error in your site.
Next problem is security. For some reason neither select() not insert() function supports prepared statements, which renders them quite useless: you can use PDO::query() instead, with exactly the same outcome. But what you really have to is to use prepare/execute properly, by using placeholders in the query while sending actual variables to execute();
Another problem is duplicated code: both functions are pretty much the same.
And at the same time both function are quite unreliable: select() function is limited to only one type of result set, while insert() doesn't return anything at all. Instead, you can use just single function to run all your queries, and make it return the statement, which will be extremely useful. It will let you to get the returned data in dozens different formats supported by PDO, and even let you to get the number of affected rows from DML queries.
Let me suggest you another approach, a simple PDO wrapper that can let you to use PDO most simple and secure way:
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_CHAR', 'utf8');
class DB
{
protected static $instance = null;
public function __construct() {}
public function __clone() {}
public static function instance()
{
if (self::$instance === null)
{
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => TRUE,
);
$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR;
self::$instance = new PDO($dsn, DB_USER, DB_PASS, $opt);
}
return self::$instance;
}
public static function __callStatic($method, $args)
{
return call_user_func_array(array(self::instance(), $method), $args);
}
public static function run($sql, $args = [])
{
$stmt = self::instance()->prepare($sql);
$stmt->execute($args);
return $stmt;
}
}
It's extremely powerful, secure, and easy to use.
You can use any PDO function by simply adding it's call after DB:: prefix:
$stmt = DB::query("SELECT * FROM table WHERE foo='bar'");
So, in the first place, it's a PDO wrapper, which is able to run any PDO method by means of using magic __call() method. The only function I added is run().
Instead of your own insecure and unreliable select() and insert() methods let me suggest you to use one universal run() method, which is nothing more than a shorthand to these three lines:
$stmt = DB::prepare($query);
$stmt->execute($params);
$data = $stmt->fetch();
So, instead you can write it as a neat one-liner:
$data = DB::run($query, $params)->fetch();
Note that it can run a query of any kind and return the result in any format that PDO supports.
I wrote an article about this simple wrapper, where you can find some usage examples. All the example code can be run as is, just copy and paste it in your script and set up credentials: http://phpdelusions.net/pdo/pdo_wrapper#samples
I'm new. Below is the beginning of an attempt to interface with a database. Please let me know if the syntax is not correct, it seems to work on my localhost.
I think I could have typed class Database extends Mysqli, right? which would then have made the methods of Mysqli directly accessible to Database rather than through an instance created in the class itself. Would that have been preferable to what I have done?
class Database {
#The variable that stores the database handle
public $db;
#The Database objects's datbase parameters
public $host;
public $user;
public $password;
public $database;
#creates a Database object with the required databases details
public function __construct($host, $user, $password, $database) {
$this->host = $host;
$this->user = $user;
$this->password = $password;
$this->database = $database;
}
#Stores the database handle as a var $db of the Database instance
public function connect() {
if ($this->db = new Mysqli($this->host, $this->user, $this->password, $this->database)) {
if ($this->db->connect_errno) {
echo "No connection could be made <br/>";
} else {
echo "database succesfully connected <br/>";
}
}
}
}
If your class Database represents the database handle, then it should not have it public:
#The variable that stores the database handle
public $db;
Otherwise you would not encapsulate that detail and therefore you wouldn't need your class at all.
Next to that, when you start to write classes, echo does not belong in there:
if ($this->db = new Mysqli($this->host, $this->user, $this->password, $this->database)) {
if ($this->db->connect_errno) {
echo "No connection could be made <br/>";
} else {
echo "database succesfully connected <br/>";
}
}
Because classes consists of methods returning via their return value and not via standard output. Instead you want to throw an exception here. Which is also a feature of Mysqli already, therefore, you don't need to write that error handling code your own to get started:
Turning query errors to Exceptions in MySQLi
After getting these more or less obvious ones out of the way, you're asking yourself whether or not you should inherit mysqli instead of aggregating it.
I actually can not tell you. So far the code you've shared just shows standard functionality of a mysqli therefore I would suggest to drop that class completely as the code looks superfluous. So I would say: neither. I see no reason for your Database class as you just could use mysqli instead.