So, I'm in the middle of writing a web application for one of my clients, and I've decided to keep the database connection in a class. The following code is what I have:
class databaseConnection {
private $hostname = 'hn.app.dev';
private $username = 'root';
private $password = '';
private $database = 'hn_app_dev';
public function connect() {
$host = mysqli_connect($this->hostname, $this->username, $this->password);
if ($host) {
$connection = mysqli_select_db($host, $this->database);
if (!$connection) {
die('An error occured while trying to connect to the database.');
}
return $connection;
}
}
}
I am using the standard PHP function of mysqli_query to send queries to the database. I am using the following to send queries to the database:
function fetch_from_db($query) {
$connection = new databaseConnection();
$query = mysqli_query($connection->$connection, 'QUERY');
}
I'm new to using classes in my code. I'm still learning, as we all are. I've checked about but cannot find a fix for my issue. I know what the issue is: it's an issue with the class being an object, and something to do with fetching the returned $connection variable from it.
How can I fix this issue so that I can connect correctly to my database? Also, could anyone point me in the direction of some documentation that I could learn the fix so I can tackle this in future.
Thank you!
There are a lot of different ways you could write a object to handle connections and queries to the database.
What matters most is what your trying to achieve.
I would think these would be a few features you would like to have.
Single Connection
Runs SQL and returns mysqli results.
Access to the connection for escaping values.
It looks like you want to store your credentials within the object it self. ( I would suggest passing these in as a value in __construct()
These are a few basic features, that could easily be expanded apon.
class databaseConnection {
//private $hostname = 'hn.app.dev';
//private $username = 'root';
//private $password = '';
//private $database = 'hn_app_dev';
private $connection; // this is where the object will store the connection for other methods to access it
public function __construct($host, $username, $password, $database)
//public function connect() {
$this->connection = mysqli_connect($host, $username, $password);
if ($host) {
$this->connection->select_db($database);
if (!$this->connection) {
die('An error occured while trying to connect to the database.');
}
return $connection;
}
}
// this is so databaseConnection $db can access the connection for escaping MySQLi SQL
public function connection(){
return $this->connection;
}
function fetch_from_db($query) {
//$connection = new databaseConnection(); // I don't believe you really want to create a instance of this object inside of itself
//$query = mysqli_query($connection->$connection, 'QUERY');
$query = $this->connection->query($query); // we will use the object oriented style instead of the above procedural line
return $query; // return the results to the $results var in the bottom example
}
// this is a magic function that is called when the object is destroyed, so we will close the connection to avoid to many connections
function __destruct(){
$this->connection()->close();
}
}
// make a new datbaseConnection class with specific credentials
$db = new databaseConnection('localhost', 'someuser', 'somepass', 'somedb');
$sql = 'SELECT * FROM tableName LIMIT 100';
// call the fetch_from_db function from the new databaseConnection $db
$results = $db->fetch_from_db($sql);
// print the results
while($result = $results->fetch_assoc()){
print_r($result); // print_r on each row selected from db
}
You can learn more about OOP and PHP Objects in the Manual and there are many tutorials available online about specifically classes to manage database connections and queries.
http://php.net/manual/en/language.oop5.php
Hope this helps!
If you're going to keep it in a class, you never call the connect() function. But if you want it connected when you initiate the class, change the connect() function to __construct() and remove the return and assign it to a public variable.
class databaseConnection {
private $hostname = 'hn.app.dev';
private $username = 'root';
private $password = '';
private $database = 'hn_app_dev';
public $connection;
public function __construct() {
$host = mysqli_connect($this->hostname, $this->username, $this->password);
if ($host) {
$connection = mysqli_select_db($host, $this->database);
if (!$connection) {
die('An error occured while trying to connect to the database.');
}
$this->connection = $host;
}
}
}
After that, you can get the database connection in your function like:
function fetch_from_db($query) {
$connection = new databaseConnection();
$query = mysqli_query($connection->connection, 'QUERY');
}
Now, after having said all that, you don't want to create a new instance in every function to access the database. So possibly making it static and create an init() function of sorts so it takes less memory in the overall application.
For class documentation PHP's Classes/Objects page will help. Specifically the 'Examples' link.
<?php
class databaseConnection {
private $hostname = 'localhost';
private $username = 'root';
private $password = '';
private $database = 'onlinylh_sggsfaculty';
public function connect() {
$host = mysqli_connect($this->hostname, $this->username, $this->password,$this->database);
if ($host) {
return $host;
}
else{
echo "Error";
}
}
}
function fetch_from_db($query) {
$conn = new databaseConnection();
$r = mysqli_query($conn->connect(), $query);
}
fetch_from_db()
?>
This Worked For me.
Related
i'm updating from PHP5.6 to PHP7.0 and this doesn't work anymore:
$con=mysqli_connect(DATABASE_SERVER,DATABASE_USER,DATABASE_PASSWORD) or die(DATABASE_ERROR);
mysqli_select_db($con, DATABASE_NAME) or die(DATABASE_ERROR);
class DoSomeStuff()
{
function GetSomeDate()
{
$result=mysqli_query($con, "SELECT * FROM my_table");
}
}
Looks like the $con variable is not available inside the class.
Do i have to to something like this?
global $con=mysqli_connect()
Thanks!
The main pattern used is something like, pass database connection into constructor (dependency injection) and then store it in an instance variable ($this->con in this case). Then later database calls just use $this->con for the database connection...
$con=mysqli_connect(DATABASE_SERVER,DATABASE_USER,DATABASE_PASSWORD) or die(DATABASE_ERROR);
mysqli_select_db($con, DATABASE_NAME) or die(DATABASE_ERROR);
class DoSomeStuff
{
private $con;
// Create instance with connection
public function __construct( $con ) {
// Store connection in instance for later use
$this->con = $con;
}
public function doSomething() {
// Run query using stored database connection
$result=mysqli_query($this->con, "SELECT * FROM my_table");
}
}
// Create instance, passing in connection
$some = new DoSomeStuff ($con);
$some->doSomething();
heres something I've worked with recently
class Database {
private $_conn = null;
public function getConnection($password) {
if (!is_null($this->_conn)) {
return $this->_conn;
}
$this->_conn = false;
try {
$this->_conn = new PDO("mysql:host=localhost;dbname=databasename", 'root',
$password);
$this->_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
return $this->_conn;
}
}
function conOpen() {
$servername = "localhost";
$username = "root";
$password = "password";
$db = new Database();
$conn = $db->getConnection($password);
return $conn;
}
Then use it like this
$con = conOpen();
You can check out PDO connection here
I'm trying to use db connection parameter inside function, i tried to global it but it does not working.
$host = 'localhost';
$username = 'b**s';
$password = '1******m';
$dbname = 'b*********e';
$connection = new mysqli($host, $username, $password, $dbname);
if ($connection->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
When i'm executing the query it returning error, becuase i didn't pass $connection parameter inside function.
function insertData(){
{......}
if($connection->query($sql)){
$response['success'] = 'User record successfully added!';
}
}
Can anyone guide me what is best to use without passing parameter inside function. I would like to appreciate if someone guide me.
In your function you should do something like
global $connection;
then use it below like
if($connection->query($sql)){
$response['success'] = 'User record successfully added!';
}
This is well documented in manual, i suggest you go have a look.
Create a database class and access it by object
<?php
class Database {
private static $db;
private $connection;
private function __construct() {
$this->connection = new MySQLi(/* credentials */);
}
function __destruct() {
$this->connection->close();
}
public static function getConnection() {
if (self::$db == null) {
self::$db = new Database();
}
return self::$db->connection;
}
}
?>
Then just use $db = Database::getConnection(); wherever I need it.
Having trouble understanding classes and inheritance:
core.php:
$servername = "****";
$database = "****";
$username = "****";
$password = "****";
try {
$pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
class Database {
protected $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
}
class User extends Database {
private $ip;
private $sessionId;
public function __construct($ip, $sessionId) {
$this->ip = $ip;
$this->sessionId = $sessionId;
}
public function getSessionInfo () {
$stmt = $this->pdo->prepare(".."); <-- error here
....
}
}
When calling:
require_once 'api/core.php';
$database = new Database($pdo);
$user = new User($_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);
In this contest $database, and $user variables are not related to each other:
require_once 'api/core.php';
$database = new Database($pdo);
$user = new User($_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);
Thus, calling prepare() on $user won't work.
You need a mechanism, at least like this , although not a good practice to assign Database to a User:
$user->setDatabase($database);
Instead create a static Database object, initiate it before User initiation, and call it statically within User object, or any other object, make it available for all objects.
A quick fix would look like this, where User doesn't extend Database, because it's wrong. User is not a Database.
$database = new Database();
$user = new User();
$user->setDatabase($database); //sets $db variable inside User
//User.php
namespace MyApp;
class User{
private Database $db;
public function setDatabase($db){
$this->db = $db;
}
public function doSomething(){
$this->db->getPdo()->prepare('..');
}
}
//Database.php
namespace MyApp;
class Database{
private $pdo; //returns PDO object
function __construct(){
//create pdo connection
$this->pdo = ..
}
function getPdo(){
return $this->pdo;
}
}
Database should be injected to objects or used by objects, you shouldn't be extending Database just to have it. If you want to do it properly, in an object-oriented way.
Remember PHP doesn't allow multiple inheritances by extend. Tomorrow, you might want to have a Person class that every User will extend, but since you did it wrong in the beginning, and wasting precious extend on Database, it won't be possible. And by not having a control of how many database instances you have created, you will run into issues. You need to know for sure that you have only a single connection object for one database, if of course the opposite is a must - which in your case I doubt.
Of course this will change if you have multiple database requirements, and more sophisticated app structure.
You are receiving this error because User Instance has pdo empty. try this code
$servername = "****";
$database = "****";
$username = "****";
$password = "****";
try {
$pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
class Database {
protected $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
}
class User extends Database {
private $ip;
private $sessionId;
public function __construct($pdo, $ip, $sessionId) {\
parent::__construct($pdo)
$this->ip = $ip;
$this->sessionId = $sessionId;
}
public function getSessionInfo () {
$stmt = $this->pdo->prepare("..");
....
}
}
then
require_once 'api/core.php';
$user = new User($pdo, $_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);
hope it helps.
I'm currently writing my first PHP application using OOP and PDO. In doing so I'm working on a connection class so that I can initiate a database connection when needed. I believe the terms for the way I am doing it is dependency injection.
I currently have an error when trying to access the connection.
This is my connection class:
class db{
private $host = '';
private $dbname = '';
private $username = '';
private $password ='';
public $con = '';
function __construct(){
$this->connect();
}
function connect(){
try{
$this->con = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username, $this->password);
$this->con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'We have a problem!';
}
}
}
And this is how I am trying to call it inside of other classes.
private $con;
public function __construct(db $con) {
$this->con = $con;
}
However this is the error I receive when trying to run it.
Catchable fatal error: Argument 1 passed to users::__construct() must be an instance of db, none given.
Any advice on what I am doing incorrectly would be much appreciated.
You will need to first create your DB instance and pass it to the constructor of your 'Other' class
$db = new DB();
$class = new OtherClass($db);
Apart from that, there are other issues:
The DB class constructor did not assign values to the database name, user and password etc. One way of doing it is to pass those settings to the constructor of DB and assign the values to the private properties.
class DB{
private $host = '';
private $dbname = '';
private $username = '';
private $password ='';
public $con = '';
function __construct($host, $dbname, $username, $password){
$this->host = $host;
$this->dbname = $dbname;
$this->username = $username;
$this->password = $password;
$this->connect();
}
function connect(){
try{
$this->con = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username, $this->password);
$this->con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'We have a problem!';
}
}
}
When building dynamic websites I use a php include to make my connections to the database. The included file is very basic:
mysql_connect($hostname = 'host', $username = 'user', $password = 'password');
mysql_select_db('database');
This works fine.
In some places I use an AJAX system to create drag-and-drop reordering of database records which updates the database at the same time, it is adapted from something I found on the internet. This uses its own connection code:
class SortableExample {
protected $conn;
protected $user = 'user';
protected $pass = 'password';
protected $dbname = 'database';
protected $host = 'host';
public function __construct() {
$this->conn = mysql_connect($this->host, $this->user, $this->pass);
mysql_select_db($this->dbname,$this->conn);
}
This also woks fine.
What it means, however, is that I have to add the username, password, host and database to two separate files. Sometimes the second one is forgotten and causes the website to fail.
My question is, how can I either combine both connection files into one, OR how can I get the second block of code to accept external variables so that I only have to enter the actual values in one place?
Your last question is easy.
db.config.php
$host = '';
$user = '';
$pass = '';
$db = '';
db.plain.php
include 'db.config.php';
$conn = mysql_connect($host, $user, $pass);
mysql_select_db($db,$conn);
db.class.php
include 'db.config.php';
class SortableExample
{
protected $conn;
public function __construct()
{
global $host, $user, $pass, $db;
$this->conn = mysql_connect($host, $user, $pass);
mysql_select_db($db,$this->conn);
}
}
You can simply put the database connection code in another file and included that everywhere you need it.
Create a single entry point for your database connection.
Use a Singleton with lazy instantiation for that:
class ConnectionProvider {
protected $conn;
protected $user = 'user';
protected $pass = 'password';
protected $dbname = 'database';
protected $host = 'host';
private static $__instance;
private function __construct() {
$this->conn = mysql_connect($this->host, $this->user, $this->pass);
mysql_select_db($this->dbname,$this->conn);
}
public static function getInstance() {
if ( self::$__instance == null) {
self::$__instance = new ConnectionProvider();
}
return self::$__instance;
}
public function getConnection() {
return $this->conn;
}
}
And then, from your code
ConnectionProvider::getInstance()->getConnection();
to use the connection wherever you need it.
SortableExample would thus become:
class SortableExample {
protected $conn;
public function __construct() {
$this->conn = ConnectionProvider::getInstance()->getConnection();
}
...
}