I read many posts and blogs about Singleton and database connection. What I understand from the singleton definition is that you can use it on any class object that is instantiated many times while staying intact.
I have a web application, and I was wondering if I could implement Singleton for database connection
Here is what I have under the DatabaseGateway class:
class DatabaseGateway
{
private $DBConnection;
private $serverName;
private $userName;
private $password;
private $databaseName;
public function __construct() {
//not done
}
public function getDBConnection() {
return $this->DBConnection;
}
public function openDBConnection() {
$this->DBConnection = new mysqli($this->serverName, $this->userName, $this->password, $this->databaseName);
}
public function closeDBConnection() {
mysqli_close($this->DBConnection);
}
The method OpenDBConnection is used when users log in in the UserGateway class. I was wondering if it is a good idea, and if it possible, to make openDBconnection into a singleton, while everyone has their own account and password.
Related
I have a "static" class which connects to database and has various functions. The current base layout is as follows:
class DB {
private static $con;
private function __construct() {};
private static function init() {
if(is_null(self::$con) {
// Initialize database connection
}
}
public static someMethod1() {
self::init();
// Do stuff
}
public static someMethod2() {
self::init();
// Do stuff
}
public static someMethod2() {
self::init();
// Do stuff
}
}
My intention is to be easily be able to call these methods as: DB::someMethod1(). However, as you can see, I am having to cehck for initialization at every method beginning. Is this a good coding practice? Is there a better design pattern available? Initially I thought of builder pattern but that doesn't really fit here in my opinion.
It looks like you are trying to ensure that there is a single instance of your DB class AND also that the instance is available as a single, globally available constant.
I'd recommend separating those two concerns in order to simplify the implementation.
First, I'd focus on getting the database access object right. Plain objects are simpler to test and inject as dependencies than static functions. For example,
class DBThing
{
private $con;
public static function build()
{
return new static('theconnection');
}
function __construct($con)
{
$this->con = $con;
}
public function someMethod1()
{
echo "someMethod1: $this->con\n";
}
public function someMethod2()
{
echo "someMethod2: $this->con\n";
}
public function someMethod3()
{
echo "someMethod3: $this->con\n";
}
}
Gives you an object you can easily test and replace with alternate implementations if needed.
Second, I'd focus on the object lifecycle and making it discoverable in the application.
If you're really OK with a single instance and the global state that implies, then something like this gets you close to the interface you asked for in your original post.
$DB = DBThing::build();
$DB->someMethod1();
$DB->someMethod2();
$DB->someMethod3();
In general, I discourage global state but I'd have to know more about your application to know if it's appropriate in your case.
I just wrote a simple db class for a coding test. Take a look at how I used here: https://github.com/TheRealJAG/Valuation-Vision-Full-Stack-Test/blob/master/classes/db.php
class DB
{
private static $instance = null;
private $db;
private $host = '';
private $username = '';
private $password = '';
private $database = '';
private function __construct()
{
$this->db = new mysqli($this->host, $this->username, $this->password, $this->database);
if ($this->db->connect_error) {
throw new Exception("Connection to the mysql database failed: " . $this->db->connect_error);
}
}
public static function connection()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance->db;
}
}
I'm 100% sold on the approach, but with the time I had for the test this is what I wrote. My biggest concern was that I only had 1 db connection open.
I have a PHP web service that uses a singleton API class to call my web service methods. I have specific classes for each module in my application: Posts, Users, Login, etc. My API class is something like:
class API{
private static $api;
private $database;
private $post;
private $user;
public function __construct(){
$this->database = new DataBase();
$this->post = new Post();
$this->user = new User();
}
public static function getInstance(){
if(empty(self::$api)){
self::$api = new API();
}
return self::$api;
}
}
So, to get my user posts, I'd call $api->post->getPosts() inside the API class, or API::getPosts() outside the API class. The API class is a facade. Each child class has its own DataBase instance. For example, Post and User has the following:
class User{
private $database;
public function __construct(){
$this->database = new DataBase();
}
}
My DataBase constructor is something like:
public function __construct() {
try{
$this->db = new \PDO(
"mysql:host=$this->host;dbname=$this->base;",
$this->user, $this->pass,
array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'")
);
}catch(\PDOException $e){
echo "<b>Error:</b> {$e->getMessage()} in <b>{$e->getFile()}</b> on line <b>{$e->getLine()}</b>";
die();
}
}
The problem is: each request uses up to five MySQL connections to generate the response. For example: a regular request includes login validation, get user info, get posts info, etc. I was wondering if I can pass the DataBase instance from the API facade to the children classes. I tried something like:
public static function getDatabase(){
$api = self::getInstance();
return $api->database;
}
But every time I call API::getDatabase() from the children classes, I get a MySQL TOO MANY CONNECTIONS error, because this method calls the API __construct() and creates a new DataBase instance.
Any idea how can I recycle my DataBase instance, or connections, to avoid connections wasting?
UPDATE
As suggested bellow, I used the dependency injection pattern to pass my DataBase object from the API facade to its children:
public function __construct(){
$this->database = new DataBase();
$this->post = new Post($this->database);
$this->user = new User($this->database);
}
(To take this out of "Unanswered".)
The commenters suggested and the OP verified:
Use the dependency injection pattern to pass the DataBase object from the API facade to its children:
private function __construct(){
$this->database = new DataBase();
$this->post = new Post($this->database);
$this->user = new User($this->database);
}
(Actually private was suggested but not confirmed.)
I have multiple classes, in this case Core and User. At this moment User is an extension of Core. In Core, I have my main functions that are required in multiple classes, for example a database connection through PDO. I use a __construct function to build the database connection, no problems with that.
However, in my User class, I want to pass values to multiple attributes through __construct. For example a Firstname, Lastname, Email, Password and a few other attributes.
When doing this, I get a warning from Netbeans that the parent constructor should be used, and a lot of vague errors, I don't ask you to fix these errors.
I would like to know if there is a way for me to use the database connection function from Core in User without making the extension. I hope it is more clear with a little bit of background information!
Below both classes, only showing the parts related to the question:
abstract class Core implements ICore {
private $_dbcon;
public function __construct($_database){
$this->_dbcon = $_database;
}
public function _connectDB(){
return $this->_dbcon;
}
class User extends Core implements IUser {
public $_username;
private $_password;
protected $_email;
protected $_adres;
protected $_phone;
protected $_contactperson;
protected $_company;
protected $_kvk;
public function __construct($_username, $_password, $_email, $_adres, $_phone, $_contactperson, $_company, $_kvk){
$this->_username = $_username;
$this->_password = $_password;
$this->_email = $_email;
$this->_adres = $_adres;
$this->_phone = $_phone;
$this->_contactperson = $_contactperson;
$this->_company = $_company;
$this->_kvk = $_kvk;
}
You have to call the parent constructor.
class User extends Core
{
public function __construct($db, $username, ...)
{
parent::__construct($db);
$this->_username = $_username;
...
}
}
But in your case I would think about a better overall design. Read about Dependency injection. In this way you'd only have one DB connection and use that connection in other classes.
class User
{
protected $db;
public function __construct(Db $db)
{
$this->db = $db;
}
}
I created an ssh2 wrapper. I have read that a constructor should not fail, so the ssh2 connection is not done in the wrapper, but by a method connect(). My question is: how do I make sure that connect() is called? I also really only need it to be called once.
class uploader {
private $user; private $pass; private $host;
private $ssh = null; private $sftp = null;
public function __construct($host, $user, $pass) {
$this->host = $host; $this->user = $user; $this->pass = $pass;
}
public function connect() {
if ($this->ssh === null) {
$this->ssh = ssh2_connect($this->host);
ssh2_auth_password($this->ssh, $this->user, $this->pass);
$this->sftp = ssh2_sftp($this->ssh);
}
}
}
What is the best way to ensure that connect() is called? Should the application call it?
$ssh = new uploader('host', 'user', 'pass');
$ssh->connect();
Or in the class methods?
...
public function upload($source, $dest, $filename) {
$this->connect();
...
}
public function delete($file) {
$this->connect();
...
}
Neither of these seems ideal.
I also thought about making a static method that would wrap the constructor and connect, but then the constructor would have to be private and I have also read that static methods are undesirable (mostly just for unit testing).
I have also read that static methods are undesirable (mostly just for unit testing).
Static methods are undesirable for some things, but factory methods isn't one of them. They make perfect sense there and do not impact unit testing. So, go ahead and make a static factory method.
The easiest way is to call connect() in your constructor and be sure to make a destructor function to disconnect your connection.
I've trying to learn PHP OOP and have made some research on how to make a global database class to use around in my project. From what I've seen the most appropriate pattern available is a singleton which would ensure that only one database connection are present at all times. However as this is my first time working with the Singleton pattern, I am not sure that I have made it right.
Is this a proper singleton? Will this code ensure one database connection only? Is there any way I can test this? (Learn a man to fish and he will have food for the rest of his life...)
I am using redbean as my ORM and here's how I set it up plainly:
require_once PLUGINPATH.'rb.php';
$redbean= R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
I've made the following script based upon this source, as my own singleton Database class;
class database {
private $connection = null;
private function __construct(){
require_once PLUGINPATH.'rb.php';
$this->connection = R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
}
public static function get() {
static $db = null;
if ( $db === null )
$db = new database();
return $db;
}
public function connection() {
return $this->connection;
}
}
Thanks!
The instance variable needs to be a static member of the class. I haven't tested this code, but it should work. Connection should probably be static too. With this code, you will have one instance of your database class, and one instance of the connection. It is possible to do this without connection being static, but making it static will ensure there is only one connection instance. I also changed the literal names of the class to php magic constants. This make your code more maintainable. If you change the name of your class down the road, you won't have to go and find all of the literal instances of the old class name in your code. This may seem like overkill now, but trust me, as you work on more and more complex projects, you will appreciate the value.
class database {
private static $connection = null;
private static $db;
private function __construct(){
require_once PLUGINPATH.'rb.php';
self::$connection = R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
}
public static function get() {
if ( !(self::$db instanceof __CLASS__) ) {
$klass = __CLASS__; // have to set this to a var, cant use the constant with "new"
self::$db = new $klass();
}
return self::$db;
}
public function connection() {
return self::$connection;
}
}
You're singleton is almost correct.
The private member (no pun intended) $connection needs to be static as well. You might go with the following too:
class database {
private static $instance = NULL;
protected $conn;
private function __construct() {
$this->conn = mysql_connect( ... );
}
public static function init() {
if (NULL !== self::$instance)
throw new SingletonException();
self::$instance = new database();
}
public static function get_handle() {
if (NULL === self::$instance)
; // error handling here
return self::$instance->conn;
}
}