If i made my database class a singleton would I call it in the constructors of the classes it is required in?
Database class so far
[code=php]
<?php
class database
private $query;
private $results;
private static $database;
//connect to the database
private function __construct()
{
$this->link = mysql_connect($constants::DBHOST, $constants::DBUSER, $constants::DBPASS) or die(mysql_error());
mysql_select_db($constants::DBNAME) or die(mysql_error());
}
public static function singleton()
{
if (!isset(self::$database)) {
self::$database = new database();
}
return self::$database;
}
public function query($query)
{
$this->query = $query;
$this->execute();
}
//execute the mysql query
private function execute()
{
$this->results = mysql_query($this->query, $this->link) or die(mysql_error());
}
//protect against SQL injection attacks
public function antisql($data)
{
if (is_array($data))
{
foreach ($data as $name=>$value)
{
$data[$name] = mysql_real_escape_string($value);
}
}
else
{
$data = mysql_real_escape_string($data);
}
return $data;
}
//retrive the insert id
public function insertid()
{
return mysql_insert_id();
}
//return an array of results
public function returnArray()
{
return mysql_fetch_array($this->results);
}
}
a quick knockup example of registration class
[code=php]
class registration
{
public function __construct()
{
$database = database::singleton();
}
public function checkunique($email)
{
$this->query(“SELECT * FROM `members` WHERE email=’$email'”);
}
public function add()
{
$this->query(“INSERT INTO `members` (`name`, `address`) VALUES (‘$name’, ‘$address’)”);
}
[code=php]
require_once 'database.class.php';
class example
{
private $db;
public function __construct()
{
$this->db = database::singleton();
}
public function example()
{
$result = $this->db->query('SELECT * FROM table');
}
}
[/code]
[code=php]
<?php
/**
* Database class to implement singleton pattern on top of mysqli
*/
class Database extends mysqli
{
/**
* @var object Singleton instance
*/
private static $instance = null;
// DB connection parameters:
private $dbHost = 'localhost';
private $dbUser = 'xxxxxx';
private $dbPwd = 'yyyyyy';
private $dbName = 'zzzzzzzz';
/**
* Constructor
* @return void
*/
private function __construct()
{
@parent::__construct(
$this->dbHost,
$this->dbUser,
$this->dbPwd,
$this->dbName
);
if(mysqli_connect_errno())
{
throw new Exception(
mysqli_connect_error(),
mysqli_connect_errno()
);
}
}
/**
* Do the singleton thing
* @return object Database
*/
public function getInstance() {
if(self::$instance === null)
{
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public function __clone()
{
throw new Exception("Cannot clone ".__CLASS__." class");
}
}
[/code]
If a second call is made to mysql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned. The new_link parameter modifies this behavior and makes mysql_connect() always open a new link, even if mysql_connect() was called before with the same parameters. In SQL safe mode, this parameter is ignored.
[/quote]
[code=php]
require_once 'database.class.php';
class example
{
private $db;
public function __construct()
{
$this->db = database::singleton();
}
public function example()
{
$result = $this->db->query('SELECT * FROM table');
}
}
[/code]
[/QUOTE]
I assign results to an object within the database class via the $this->database->query("query"); function.
results become $this->database->results; (it is private and can only be accessed via methods within the database class.)
Could this become a problem?[/QUOTE]
Why would you want to make your class a singleton anyway? It's just another global variable. Anyway mysql_connect is a singleton anyway so it doesn't matter how many times your script calls it you will only ever have one connection to any given DB.[/QUOTE]
I use your database class and I really like it
But I have one question
Is there a possibility to log all statements that are made with this class?
If so how could this look like? I hope you can help me![/QUOTE]
[code=php]
public function query($query, $resultmode = null)
{
parent::query($query, $resultmode);
// do whatever sort of logging you want to do hear
}
[/code]
[code=php]$db = Database::getInstance();
$sql = "SELECT id, LogOnUser FROM personaldaten WHERE LogOnUser = '$user' ";
$ergebnis = $db->query( $sql );
$zeile = $ergebnis->fetch_row();
return $zeile[0];[/code]
[code=php]
public function query($query, $resultmode = null)
{
$result = parent::query($query, $resultmode);
// do whatever sort of logging you want to do here, then...
return $result;
}
[/code]
Singletons suck [/quote]
@NogDog
thanks it works!
does this problem (described in #10) exist for your class of post #4?
if so how could I avoid it?
[/quote]
@bokeh
in your opinion what exactely is wrong in using singletons?
how is your db class arranged?[/QUOTE]
Is this singleton class slower as other db connections particularly in situations with many db queries?[/QUOTE]Using a class to access a function (mysql_connect for example) is always going to be slower than calling the function directly, singleton or otherwise. Comparing singleton access of the object compared to conventional access singleton would theoretically be slower because it involves an additional layer but you have to offset this against sending your connection to other objects by reference. In practice though I think you would see little or no difference even in a microsecond bench test. And don't forget, the lion-share of the time wasted is communicating with or waiting for the database server, not some nanosecond saved accessing a variable by an alternative method.
by the way is my english understandable? ;-)[/QUOTE]About as understandable as my Spanish. ?
[code=php]public function query($query, $resultmode = null)
{
$result = parent::query($query, $resultmode);
$db = self::getInstance();
$query_bereinigt = mysql_escape_string($query);
$sql = 'INSERT INTO logging (UserID, SQLStatement) VALUES ("'.$_SESSION['UserID'].'", "'.$query_bereinigt.'" );';
$ergebnis = $db->prepare( $sql );
$ergebnis->execute();
return $result;
}[/code]
[code=php]
if(preg_match('/^s*(insert|delete|update)/i', $query))
{
// log it
}
[/code]
[code=php]
if(is_bool($result))
{
// log it
}
[/code]
I set up my application to create a MySQLi object, and then pass it to each class that needs to use it as part of its contructor. [/QUOTE]
Can you explain this more detailed?
A code example would be great ?[/QUOTE]
[code=php]
class Example
{
private $db;
public function __construct(mysqli $db)
{
$this->db = $db;
}
public function doSomething()
{
$result = $this->db->query('SELECT * FROM table');
}
}
// USAGE:
$dbObj = new mysqli('localhost', 'foo', 'bar', 'database');
$test = new Example($dbObj);
$test->doSomething();
[/code]
0.1.9 — BETA 5.20