php prevent database connection in each request - php

I have a method in connection class which returns a dbconnection instance so I can make query with that.
class Connection
{
public $dbh; // handle of the db connexion
private static $instance;
public $resultBool;
public $connectedDbName;
public $resultString;
public $directed;
public static $deviceid;
private function __construct()
{
$this->dbh = new PDO('mysql:host=localhost;dbname=webfilter;port=3306;connect_timeout=15', 'root', 'company');
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->directed = false;
$this->resultBool = true;
}
public static function getConnection()
{
if (!isset(self::$instance))
{
$object = __CLASS__;
self::$instance = new $object;
}
...
return self::$instance;
}
At first request, there is a connection required so I step into this connection function that's ok. but why I need to make connection again even there is so obvious I will use same connection.. it seems cause performance issue..
here is my function which makes real job. I use dbObject to make queries on db, but for each time I need to connection instance(getconnection) to do it.
$dbObject = Connection::getConnection();
$request = $dbObject->dbh->prepare($sql);
$request->bindParam(':username', $username, PDO::PARAM_STR);
is it possible to save existing connection for next request of same users or another way to pass connection operation

You already use the singleton pattern. This is only working for multiple connections in one request. For every request this class creates a new object of the connection class. A PDO instance can't be serialized or unserialized or saved on a session. I think there is no way at the moment to do this.

Related

Danger of Declaring Multiple Database Connections in Public __Constructor vs Static Variable Connection

I recently started to update my Api code on an Apache server by using more inheritance. As I was a bit careful to use it in the past due to inexperience.
The thing is I noticed that for each Model instance a new database connection is set. So I created an alternative connection on a Static variable to pass to each Model. My question is will multiple database connection on each new Model instance cause problems if I create a connection such in my example below using __construct?
class ApiEnterprises {
protected $db;
private $table;
public function __construct(){
$this->messager = new Messager();
$this->table = 'enterprisetable';
$this->db = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
if ($this->db === NULL || !$this->db) {
// set response code
echo $this->messager->databaseFailed();
}
}
}
class ApiUsers {
protected $db;
private $table;
public function __construct(){
$this->messager = new Messager();
$this->table = 'usertable';
$this->db = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
if ($this->db === NULL || !$this->db) {
// set response code
$this->messager->databaseFailed();
}
}
}
Alternatively will a Static variable be safer? As I can remove it in the Controller __destruct method.
class Database {
static $connect;
protected static function conn() {
self::$connect = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
return self::$connect;
}
}
class ApiUserController extends Database {
private $user_model;
private $enterprise_model;
public $connection;
public function __construct($data){
$this->connection = parent::conn();
//pass connection to models
$this->user_model = new ApiUsers($this->connection);
$this->enterprise_model = new ApiEnterprises($this->connection);
}
}
What you need is IoC container, but before you get there you need to design your models in a such a way that they accept the database instance as a parameter in the constructor. This is called dependency injection. All dependant instances are injected into the new object at the time of instantiation.
Since your Database is useless I would not recommend to use it, but you should write some database abstraction library or use one that is already available on the web. e.g. EasyDB
Here is an example of a single dependency injection:
class ApiEnterprises {
protected $db;
protected $messager;
private $table = 'enterprisetable';
public function __construct(mysqli $db, Messager $messager) {
$this->db = $db;
$this->messager = $messager;
}
}
// mysqli connection somewhere at the start of your application
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
$mysqli->set_charset('utf8mb4'); // always set the charset
// instantiate the model and pass mysqli as an argument
$enterprise = new ApiEnterprises($mysqli, $messager);

Assign resource to a class property from trait method

I've decided to write a trait that will be responsable to connect and disconnect from ftp using the php built in functions. I want to login, connect and disconnect to the host by using trait methods.
I need to use $this->conn from inside the instance of the class to use the ftp functions. The variable will hold the ftp connection. I want to assign to $this->conn the value returned from the connect trait method. I want to know if there is a way to call it inside the class.
I'm unable to get the $this variable inside the class that will use the trait. How can I access it inside the class?
<?php
trait ConnectionHelper
{
public function connect(string $host, string $user, string $pwd)
{
$this->conn = ftp_connect($host);
if ($this->conn && ftp_login($this->conn, $user, $pwd)) {
ftp_pasv($this->conn, true);
echo "Connected to: $host !";
}
return $this->conn;
}
public function disconnect()
{
return ftp_close($this->conn);
}
}
class FTPManager
{
use ConnectionHelper;
private $url;
private $user;
private $password;
/* Upload */
public function upload(array $inputFile, string $dir = null)
{
if (!is_null($dir)) {
ftp_chdir($this->conn, "/$dir/");
}
$upload = ftp_put($this->conn, $inputFile['name'], $inputFile['tmp_name'], FTP_BINARY);
if ($upload) {
echo 'File uploaded!';
}
}
}
?>
NB: Can be a good solution to call the connect method of the trait inside the class constructor?
<?php
class myclass{
use mytrait;
public function __construct(){
$this->conn = $this->connect($host, $user, $pass);
}
}
?>
Traits can be used to do what you want, but it would be better to actually use traits for what they can do: assign and read from class properties.
In the trait, when you assign to $this->conn:
$this->conn = ftp_connect($host);
The property is defined for the class instances that use the trait. As such, no need to use $this->conn = $this->connect() because $this->conn will already contain the connection resource.
So in the constructor, simply call the connect method:
public function __construct()
{
$this->connect($host, $user, $pass);
// $this->conn will now contain the connection made in connect()
}
No need to return $this->conn; in the trait. To make sure you free your resource, call disconnect() from FTPManager's destructor:
public function __destruct()
{
$this->disconnect();
}
That being said, it is a rather quirky way of managing this. Having to manually call connect() in every class that use the trait is error prone, and might lead to maintainability issue (every one of those class need to be aware of ftp credentials, for instance, tightly coupling them to configuration).
Thinking about it, these class instances are not dependant upon ftp credentials, they are dependant upon an active ftp connection. As such, it's way cleaner to actually ask for the ftp connection in the class's constructor, and not bother about calling connect() and disconnect() in every class that actually needs the ftp connection.
We could think of a connection wrapper class that would greatly simplify things here:
class FTPWrapper {
private $connection;
public function __construct(string $host, string $user, string $pwd)
{
$this->connect($host, $user, $pwd);
}
public function __destruct()
{
$this->disconnect();
}
public function getConnection()
{
return $this->connection;
}
private function connect(string $host, string $user, string $pwd): void
{
$this->connection = ftp_connect($host);
if ($this->connection && ftp_login($this->connection, $user, $pwd)) {
ftp_pasv($this->connection, true);
echo "Connected to: $host !";
}
}
private function disconnect(): void
{
ftp_close($this->conn);
}
}
Then, inject that wrapper into whatever class that needs to use it.

Class extends dbConnection class VS passing PDO dbConnection variable into class constructor

I used to extend the Db connection class in every class that needs to connect to the database. I think that this is the most common way. But, by following this way, you open and close a new connection in every class instance that extends the db connection class. Lately, i thought that i could create a pdo object and pass it into class' constructor. So, every class instance that needs access to database use the same connection. It works but i am not sure if this is an efficient way to do it. Also, i have a function called closeCon that i call at the end of the script so as to close the connection via null and unset. I would like to know your opinion about that too. Thank you in advance : )
METHOD 1: New class extends dbConnection class.
class Db {
public $pdo;
public function __construct($usr, $pwd, $db) {
$this->pdo = new PDO("mysql:host=localhost;dbname=".$db.";charset=utf8", $usr, $pwd);
}
}
class Users extends Db{
public function __construct(){
parent::__construct($usr, $pwd, $db);
}
}
METHOD 2: Connect to db by passing PDO dbConnection variable into new class' constructor.
class Db {
public $pdo;
public function __construct($usr, $pwd, $db) {
$this->pdo = new PDO("mysql:host=localhost;dbname=".$db.";charset=utf8", $usr, $pwd);
}
public function closeCon(){
$this->pdo = null;
unset($this->pdo);
}
}
class Users {
protected $pdo;
public function __construct($con){
$this->pdo = $con;
}
}
$db = new Db($usr, $pwd, $db);
$posts = new Users($db->pdo);
$db->closeCon();
There is absolutely no point in extending application classes from DB class. So - Plan B.
The only case Method 1 might be acceptable is if Users were a model. However, this approach is typically bad practice due to coupling, multiple inheritance limitations, etc. And in your case creates multiple database connections.
Method 2, is a better approach of the two. It is a form of dependency injection.
Good work. This is much more efficient than opening a connection every time, and you are properly disposing of your connections when you are done.

PHP: Utilizing singleton pattern correctly?

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;
}
}

How to avoid opening multiple connections to the DB with OOP PHP

I've been a procedural programmer for over 4 yrs and it's time to start looking into OOP. With that said, let's say I needed to call two methods in my class. Each method requires a connection to the DB so that's two trips to the DB, which also opens multiple connections.
Can this be avoided by having some sort of code in the application layer (constructor?) or does a connection pool have to be setup on the DB side? And just for kicks, I'm not using mysql; I'm using mongodb with codeigniter.
Here's what I have so far, not sure if it's ideal to use?
Here's where I setup my DB info:
database_conn.php
class Database_Conn extends Model {
function _connect() {
$m = new Mongo("localhost:27017", array("persist"=>"x"));
$db = $m->selectDB( "foo" );
return $db;
}
}
sample model file
class Home_model extends Model {
public function __construct() {
// Establish connection to "profiles" table
$this->db_conn = Database_Conn::_connect()->selectCollection( "profiles" );
}
function getMyProfile($username) {
$data = $this->db_conn->findOne(array("username" => $username) );
return $data;
}
function getAll() {
$data = $this->db_conn->find();
return $data;
}
}
you should use singleton pattern
EDIT:
the way you did it, it is possible to call _connect multiple times, which means reconnecting.
singleton implementation usually means you have to make constructor private/protected and define a getInstance method which creates connection on first call and returns the created connection on later calls.
this is what i would do:
class Database_Conn extends Model {
static protected $_instance;
protected $db = null;
final protected function __construct() {
$m = new Mongo("localhost:27017", array("persist"=>"x"));
$this->db = $m->selectDB( "foo" );
}
static public function getInstance() {
if (!(self::$_instance instanceof self)) {
self::$_instance = new self();
}
return self::$_instance;
}
public function getConnection() {
return $this->db;
}
final protected function __clone() { }
}
and then use Database_Conn::getInstance()->getConnection() to get the connection object.
You should look into a manager class for your db connections. Then you can have one central place where you request connections from. If there is already an open connection the manager can return that instead of returning a new connection.
This would be one approach. There are tons of examples out there about how to implement something like this. There already some for mysql and mssql. But you could surely extend for your db.
Use a database layer. Dibi is a great library in this case. http://dibiphp.com

Categories