I tried to create a connection class in PHP to connect with the DB data, but one error appears on the lines:
const USER = "{$value['user_DB']}";
const PASS = "{$value['password_DB']}";
Fatal error: Constant expression contains invalid operations in
C:\xampp\htdocs\dev\davinci\classes\Conexao_Teste.class.php on line 21
<?php
require_once"../classes/configDB.class.php";
abstract class conection extends configDB{
private $valor;
private $instanceConfigDB;
public function listDB(){
$valor = $instanceConfigDB->listconfigDB();
foreach($valor as $value){
echo "Banco: ID:{$value['id_db']} - Hostname:{$value['hostname']} - DBNAME:{$value['dbname']} - User:{$value['user_DB']} - PASS:{$value['password_DB']}<br>";
}
}
const USER = "{$value['user_DB']}";
const PASS = "{$value['password_DB']}";
private static $instance = null;
private static function conect(){
try {
if(self:: $instance==null):
$dsn = "mysql:host={$value['hostname']};dbname={$value['dbname']};charset=utf8";
self::$instance = new PDO($dsn, self::USER, self::PASS);
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
endif;
} catch (PDOException $e) {
echo "Erro: " . $e->getMessage();
}
return self::$instance;
}
protected static function getDB() {
return self::conect();
}
}
?>
You should use
define('USER', "{$value['user_DB']}");
As const would be evaluated at compile time where as define would be evaluated at run time.
You are trying to use $value[] outside it's defined scope, and that is why you are getting those errors.
$value[] is declared in method listDB(). If you want to use that value outside of the method you'd have to declare variables outside the method.
//Declaring variables and constants
private $valor;
private $instanceConfigDB;
private $username;
private $pass;
private $hostname;
private $dbname;
public function listDB(){
$valor = $instanceConfigDB->listconfigDB();
foreach($valor as $value){
echo "Banco: ID:{$value['id_db']} - Hostname:{$value['hostname']} - DBNAME: {$value['dbname']} - User:{$value['user_DB']} - PASS:{$value['password_DB']}<br>";
//Initialize your data
$username = $value[user_DB];
$pass = $value[password_DB];
....
}
}
At least this way, your data is then accessible outside your method
Your connect method would then look like this:
private static function conect(){
try {
if(self:: $instance==null):
$dsn = "mysql:host={$hostname};dbname={$dbname};charset=utf8";
self::$instance = new PDO($dsn, self::$username, self::$pass);
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
endif;
} catch (PDOException $e) {
echo "Erro: " . $e->getMessage();
}
Related
I'm attempting to create a mysql query using OOP in PHP. In the code below the class "database_disconnection" does not toss any errors or notices, however the last class "database_query" gives me a notice that $database_handle is undefined. I have no idea what's causing this as I created the database_query class as a derivative class of database_connection, which include the $database_handle variable as private. Any help would be greatly appreciated!
Instantiating the objects:
include("includes/database_classes.php");
new database_connection;
new database_query('SELECT * FROM users');
and the classes:
<?php
/*----------------------------------------------------------------------------------------------------*/
class database_connection
{
private $username = 'root';
private $password = '';
private $hostname = 'localhost';
private $database = 'assistant';
private $database_handle;
function connect()
{
try
{
$database_handle = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
}
catch (PDOException $e)
{
print "Error!: " . $e ->getMessage() . "<br/>";
die();
}
}
}
/*----------------------------------------------------------------------------------------------------*/
class database_disconnection extends database_connection
{
function disconnect()
{
$database_handle = null;
}
}
/*----------------------------------------------------------------------------------------------------*/
class database_query extends database_connection
{
private $mysql_statement;
function __construct( $mysql_statement )
{
$this->mysql_statement = $mysql_statement;
foreach($database_handle->query("$mysql_statement") as $row) {
print_r($row);
}
}
}
/*----------------------------------------------------------------------------------------------------*/
?>
In your database_query constructor, you're attempting to use $database_handle before initializing it. If you notice, you only initialize in the connect function of your parent class (database_connection).
Either call connect before trying to refer to it, or initialize it in the parent's constructor, and call it (parent::__construct();).
I have been trying to get better at OOP. I am writing a database class, which will handle simply connecting to a database via PDO. Now, I want to make it so that it uses different variables if it is being served from my localhost server.
Consider the following code:
<?php
class Database {
private $host;
private $name;
private $username;
private $password;
public $conn;
if ($_SERVER['SERVER_NAME'] == "localhost") {
$host = "change_to_your_db_host";
$name = "change_to_your_db_name";
$username = "change_to_your_db_username";
$password = "change_to_your_db_password";
}
else {
$host = "change_to_your_db_host";
$name = "change_to_your_db_name";
$username = "change_to_your_db_username";
$password = "change_to_your_db_password";
}
public function connect () {
$this->conn = null;
try {
$this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
}
catch (PDOException $exception) {
echo "Connection error: " . $exception->getMessage();
}
return $this->conn;
}
}
?>
I am very new to classes in general - I have been writing pure prodecural function-based PHP for wayyyy too long.
My questions are:
Is it cool to use $_SERVER variables within a class like that?
Is using that conditional statement within the class to determine the private variables OK? This class will be included in all of my other scripts which access the database via my object classes.
Is there a more efficient way to write this rather that have it echo an exception if one is caught?
I just want to make sure that I am doing things properly going forward. I have been writing PHP for a long time and I want to get out of the my outdated and archaic methods entirely.
You should do your conditional declaration in the __construct() method of your class like so:
<?php
class Database {
private $host;
private $name;
private $username;
private $password;
public $conn;
public function __construct()
{
if ($_SERVER['SERVER_NAME'] == "localhost")
{
$this->host = "change_to_your_db_host";
$this->name = "change_to_your_db_name";
$this->username = "change_to_your_db_username";
$this->password = "change_to_your_db_password";
}
else
{
$this->host = "change_to_your_db_host";
$this->name = "change_to_your_db_name";
$this->username = "change_to_your_db_username";
$this->password = "change_to_your_db_password";
}
}
public function connect () {
$this->conn = null;
try {
$conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
}
catch (PDOException $exception) {
throw $exception // you can throw again this \Exception to handle it in your code using the object
}
$this->conn = $conn;
return $this; // you should return $this so you can chain the object methods. Since $con is public, you can still access it
}
}
Is it cool to use $_SERVER variables within a class like that?
I cannot see why not.
Is using that conditional statement within the class to determine the private variables OK? This class will be included in all of my other scripts which access the database via my object classes.
As per #MarcB's comment, no you cannot run code at the top-level of a class, only in methods.
Is there a more efficient way to write this rather that have it echo an exception if one is caught?
Yes, throw it again so you can handle it in the final code using the Database class.
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 have a try catch block that connects via PDO to a database. I would like to be able to reference it in all my functions without having to pass it as a parameter. How would I do this? The mentioned code is:
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e) {
echo $e->getmessage();
die();
}
EDIT:
I created a singleton class (attempt below) that executes the try catch block upon _construct
final class database {
private static $instance = NULL;
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
}
Declare it as a static attribute of a singleten class. Than you can access it with
$pdo = Singleton::instance()->getConnection();
Alternatively I can suggest taking a look at MArtin Fowler's relational database mapping pattern. It goes a step further, than centralizing ony the connection itself.
Alternatively Doctirne project has a complete implementation of that: www.doctrine-project.org
final class database {
private static $instance = NULL;
private $pdo; //added private variable for pdo
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
$this->pdo = $database; //saved the connection into the new variable
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
//added a function to get the connection itself
function getConnection(){
return $this->pdo;
}
}
So now you use it:
$pdo = database::getInstance()->getConnection();
Can anybody please guide me with a sample code to establish a database connection in php using singleton class.
class DatabaseSingleton
{
// [Singleton]
private static $instance = null;
public static function getInstance()
{
if (!self::$instance)
{
self::$instance = new self();
}
return self::$instance;
}
private function __clone(){}
// [/Singleton]
private $connection = null;
private function __construct()
{
$this->connection = mysql_connect('localhost','root','admin');
if ($this->connection)
{
mysql_select_db('my_database');
}
}
//
// crud operations go here.
//
}
$db = DatabaseSingleton::getInstance();
$db->SomeCRUDOperation();
Something like that perhaps? Very basic, but should give you a starting point.
That's how a singleton-pattern looks like:
<?php
class SingletonClass
{
static private $instance = null;
static public function getInstance()
{
if (null === self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
private function __construct(){}
private function __clone(){}
}
$singletonClass = SingletonClass::getInstance();
Now you can put random functions and parameters in there that handle your DB-stuff. I hope that answers your question.
See the manual for an example on how to implement the Singleton pattern: http://www.php.net/manual/en/language.oop5.patterns.php
Then just establish the database connection in your class constructor.
I use something like this:
class DBConn
{
static private $_db = null; // The same PDO will persist from one call to the next
private function __construct() {} // disallow calling the class via new DBConn
private function __clone() {} // disallow cloning the class
/**
* Establishes a PDO connection if one doesn't exist,
* or simply returns the already existing connection.
* #return PDO A working PDO connection
*/
static public function getConnection()
{
if (self::$_db == null) { // No PDO exists yet, so make one and send it back.
try {
self::$_db = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASS);
} catch (PDOException $e) {
// Use next line for debugging only, remove or comment out before going live.
// echo 'PDO says: ' . $e->getMessage() . '<br />';
// This is all the end user should see if the connection fails.
die('<h1>Sorry. The Database connection is temporarily unavailable.</h1>');
} // end PDO connection try/catch
return self::$_db;
} else { // There is already a PDO, so just send it back.
return self::$_db;
} // end PDO exists if/else
} // end function getConnection
} // end class DBConn
/**
* And you can use it as such in a class
* */
class Post {
public function __construct(){
$this->db = DBConn::getConnection();
}
public function getPosts()
{
try {
/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM posts";
foreach ($this->_dbh->query($sql) as $row) {
var_dump($row);
}
/*** close the database connection ***/
$this->_dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
}
}
}
I am using something like below
class Database
{
private $_connection;
private static $_instance; //The single instance
private $_host = "HOST";
private $_username = "USERNAME";
private $_password = "PASSWORd";
private $_database = "DATABASE";
public static function getInstance() {
if(!self::$_instance) { // If no instance then make one
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() {
$this->_connection = new mysqli($this->_host, $this->_username,
$this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()) {
trigger_error("Failed to conencto to MySQL: " . mysqli_connect_error(),
E_USER_ERROR);
}
}
// Magic method clone is for prevent duplication of connection
private function __clone() { }
public function getConnection() {
return $this->_connection;
}
}
$db = Database::getInstance();
$mysqli = $db->getConnection();
$sql_query = "SELECT foo FROM etc";
$result = $mysqli->query($sql_query);