Class loop creates mysql too many connections - php

So I am working with a LOT of classes... Everything was working fine until I included my session class (verifies and creates/destroys sessions) into my user class (does user operations, login, register, etc).
Basically, I am getting a "mysqli Too many connections!" error... I think this is because my sessions class is included in the users class and vice versa:
__construct of class User:
$this->db = new DB($db);
$this->password = new Password();
$this->session = new Session($db);
$db is just an array of database info...
__construct of class Session:
$this->error = new Error();
$this->users = new User($db);
$this->db = new DB($db);
So you see how they both are including each other, I think this is what's causing my connection error.

It isn't the user's job to create a database connection. (When you think of it, it doesn't make much sense, does it?)
Instead, ask for the database connection in the constructor.
class User {
public function __construct(DB $db) {
This way, you can reuse the connection object all over the application.

You have to create one first, and pass it into the constructor of the other.
Like:
Session:
__construct($db){
$this->db = $db; //Don't reconstruct
$this->users = new User($db,$this);
...
}
User:
__construct($db,$session){
...
$this->db = $db; //Don't re-construct
$this->session = $session;
...
}

in the session class
do
$this->db = $db;
and in your user class
$this->session = new Session($this->db);

Would if you make a third class that constructs with both the two classes and run the loop on the 3rd class? Then run all your DB instances on UserSession? I dont know?
__construct of class User:
$this->password = new Password();
__construct of class Session:
$this->error = new Error();
__construct of class UserSession:
$this->db = new DB($db);
$this->users = new User($db);
$this->users = new Session($db);

Related

PHP OOP best practices or how to code right?

I'm trying to learn how to properly code PHP OOP.
This is where I'm running into issues.
I created several classes that extend main Application class and I want to make things work properly.
I have main file that's index.php that looks like this:
include_once('classes/Application.php');
include_once('classes/Configuration.php');
include_once('classes/Database.php');
$app = new Application;
$config = new Configuration;
$db = new Database;
var_dump($app->db_connected);
var_dump($db->db_connected);
$db->connect($config->dbhost, $config->dbuser, $config->dbpass, $config->dbname);
var_dump($app->db_connected);
var_dump($db->db_connected);
The output is:
1. bool(false)
2. bool(false)
3. bool(false)
4. bool(true)
My main application file looks like this:
class Application {
public $db_connected = false;
}
And my Database class looks like this:
class Database extends Application {
function connect($dbhost, $dbuser, $dbpass, $dbname) {
if(!$this->db_connected) {
mysql_connect($dbhost, $dbuser, $dbpass) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
$this->db_connected = true;
}
}
}
So the question is, why would line #3 of the output of index.php display false? The db_connected property has been overridden in Database class and set to TRUE, but it still returns false.
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
Also when does the class EXTEND command occurs? Whenever parent class' instance is created or I have to manually create instance of the child class?
It seems you are reaching for the concept of of a static variable all instances of a class share the same static variable so using the new twice will not be an issue.
You can see the code on ideaone.
// your code goes here
class Application {
static $db_connected = false;
}
class Database extends Application {
function connect() {
if(!static::$db_connected) {
static::$db_connected = true;
}
}
}
$app = new Application;
$db = new Database;
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
$db->connect();
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
Your comment make me think you are looking for a better pattern all together. I would like to throw out some key principles namely OCP and LSP SOLID.
In this case you would avoid having Application being an instance of Database but instead use dependency injection. Here is the refactored code.
class Database {
private $db_connect = false;
public function connect () {
if(!$this->db_connect) { /* do connection */ }
}
}
class Application {
private $db;
public function setDatabse(Database $db) {
$this->db = $db;
}
public function getDatabase() {
return $this->db;
}
}
$db = new Database;
$app = new Application;
$app->setDatabase($db);
$app->getDatabase()->connect();
This line is your hint
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
You have 2 instances. Above you are checking $db instance which you connected with, and then you print from $app which was never connected. They are separate entities, one is connected one is not.
Extend occurs as soon as the file is loaded, read by the php interpreter, this happens regardless of ever using the class.
Extend is called from the child and inherits everything form the class it extends. So if you call a child method in the parent, well you are doing it backwards. It goes one way, Prent -> Child.
I would use Dependance injection for the database, then you can reuse it's code.
Like this:
//parent class
class Application {
//holds a reference to the Database class
protected static $db_conn = false;
public function __construct($db){
self::$db_conn = $db;
}
}
//child class of Application
class Application2 extends Application {
public function getSomething($id){
return self::$db_conn->getbyId($id) ;
}
}
//separate utility class
class Database{
static $conn;
public function __construct( $dbhost, $dbname, $dbuser, $dbpass, $dbname) {
static::$conn = mysqli_connect($dbhost, $dbuser,$dbpass,$dbname);
}
public function getbyId( $id ){
..code to get stuff by id using $conn - previous connection ...
return $result;
}
}
$db = new Database("myhost", "myuser", "mypassw", "mybd");
$app = new Application2( $db );
$app->getSomething(1);
//create another app with the same database connection, this is the value of injecting it.
$second_app = new Application2( $db );
See you can reuse database over and over, you can replace it without changing the code in Application as long as the calls for the functions of the Database class don't change. Each thing is responsible for it's own business.
This is called separation of concerns.
Inheritance is good, when it's needed. You might have an basic application for free users of you're services and then extend that with a premium application for paid members. Sense they paid they get all the free functionality, but also the premium stuff to.
In my example above the database is something they both need, as well as other things will probably use this. Such as a login system may need a database connection, payment system might, a shopping cart might. These are all separate objects, they don't / nor should they extend off of one Master Class, that's a bad idea. Keep them separate.
STATIC
I seen mention of the :: static object operator. My example is a bit flawed when using the static property protected static $db_conn = false;
$app = new Application2( $db );
$second_app = new Application2( $db ); //assigning db 2x is not needed.
The reason for :: and the -> normal way. Is that static :: is shared across all instance of a class, and -> is just this instance of the class. I had assigned the $db class to a static variable 2 times a better way would have been like this.
//parent class
class Application {
protected static $db_conn = false;
//separate method then construct.
public function connect($db){
self::$db_conn = $db;
}
}
//we'll keep the rest of the code the same here.
$db = new Database();
$app = new Application2();
$app->connect( $db );
$second_app = new Application2();
$second_app->getSomething(1);
Now in this example $second_app never ran it's connect method. But because the first $app did and because the static for the database variable protected static $db_conn. Now all classes that have extended the Application class have a database connection. This is what static does. It's value is shared across all instance of the class. So when you see :: think all class instance and when you see -> think only this class instance. It's actually one thing I love about php, makes it so much easier to keep track of then in some other languages.
Not to confuse you but the other use of the :: is not actually needing an instance at all. Assume you have a Config class like this.
class Config{
static $db = 'hello';
static $items = array('one' => 'item 1' );
private __construct(){} // no construction allowed
static function getItem( $which ){
return self::$items[$which];
}
}
Now without ever creating an instance of the class by calling new Config() , you can simply.
echo Config::$db;
// prints hello
echo Config::getItem('one');
// prints 'item 1'
This is quite use full for config type classes. Where they are an empty shell just used to store data in and you don't need an object for them, essentially a way to keep things organized. So tying this in to the previous examples
$db = new Database(Config::$myhost, Config::$myuser, Config::$mypassw, Config::$mybd);
In your case best OOP practice is to use Mediator pattern. Concrete Mediator will be Application class:
class ApplicationBase {
private $db;
private $cfg;
public function setDb(Database $db) {
$this->db = $db; return $this;
}
public function setConfig(Config $cfg) {
$this->cfg = $cfg; return $this;
}
}
class Application extends ApplicationBase {
public function getDsn() {
return $this->cfg->getDsn();
}
public function getDbUser() {
return $this->cfg->getDbUser();
}
public function getDbPass() {
return $this->cfg->getDbPass();
}
public function getConnection() {
return $this->db->getConnection();
}
}
class AppComponent {
protected $app;
public function __construct(Application $app) {
$this->app = $app;
}
}
class Config extends AppComponent {
private $dsn;
private $dbuser;
private $dbpass;
// ... getters and setters
}
class Database extends AppComponent {
private $connection;
private function connect() {
$this->connection = new PDO(
$this->app->getDsn(),
$this->app->getUser(),
$this->app->getPass()
);
}
public function getConnection() {
if (null === $this->connection) $this->connect();
return $this->connection;
}
}
class Model extends AppComponent {
protected $table;
// Model stuff here
}
class Content extends Model {
public function getNews() {
$db = $this->app->getConnection();
return $db->query("SELECT * FROM $this->table LIMIT 5")->fetchAll();
}
}
Such architecture will be enough for simple, clean-looking applications and classes will be ready for easy unit-testing:
$app = new Application();
$cfg = new Config($app);
$db = new Database($app);
$app->setDb($db)->setConfig($cfg);
$content = new Content($app);
$news = $content->getNews();

PHP: using MySQL connections in singleton class

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.)

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.

Using db connection everywhere inside PHP application

I have db class which looks like that
class db {
protected $db;
public function __construct() {
$this->connect();
}
protected function connect() {
$this->db = new MySQLi(db_host, db_user, db_pass, db_name) or die($this->db->error);
$this->db->set_charset('utf8');
}
}
Every class inside my PHP app extends this db class
Like
class registration extends db {
var $validation;
function __construct() {
parent::__construct();
$this->validation = new validation();
...
And validation looks like that
class validation extends db {
var $ajax, $common;
function __construct() {
parent::__construct();
...
Getting error message "Too many connections". I feel that, this is not right approach: I'm every time reconnecting to db. So what's right way in your opinion? Is that possible to define('db', ...) 1 time and use everywhere inside app?
registration and validation are classes the use db but are not a sub-class of it.
Your code should look like:
$db = new DB();
$db->connect();
$registration = new Registration($db);
class Registration {
private $db;
public function __construct(DB $db) {
$this->db = $db;
...
You pass a reference to an instance of $db to all classes that require it.
The reason you're opening too many connections is probably because currently each class makes it's own connection to your database, and that is not what you want to do, or need to do.
You want to use composition here instead. Also might consider investigating Singleton pattern.
To elaborate, using composition, each class in your library will have an instance of the db class rather than be an instance of the db class.
Singleton will make the db class enforce only one instance of the class is ever created which is useful for shared resources like database connections. Have a look at this link for further reading on the topic.
http://php.net/manual/en/language.oop5.patterns.php
EDIT: Adding some code
Turning the db class into a Singleton
<?php
class db
{
static private $_oInstance = null;
protected $db;
private function __construct()
{
$this->connect();
}
static public function getInstance()
{
if(self::$_oInstance === null)
self::$_oInstance = new db();
return self::$_oInstance();
}
protected function connect()
{
$this->db = new MySQLi(db_host, db_user, db_pass, db_name) or die($this->db->error);
$this->db->set_charset('utf8');
}
}
Revising the rest of your classes to compose the db instance rather than extend the db class
class registration
{
private $_oDb;
public $validation;
function __construct()
{
parent::__construct();
$this->_oDb = db::getInstance();
$this->validation = new validation();
}
// ...
}

PHP class scope

I have several classes in an application that I am currently building, and I want to have one access some of the other's member functions but i can't seem to do it.
The first class is called MySQLDB:
class MySQLDB{
public $connection;
function __construct(){
//connects to database
}
function login($username, $password){
//queries database...
}
}
Then I have a class called Session:
class Session{
//variables
//constructor
function processlogin($username, $password){
$database->login($username, $password);
}
Then after this I have two class declarations:
$database = new MySQLDB();
$session = new Session();
No matter where i put these statements in relation to the classes I still get the same error:
PHP Notice: Undefined variable: database in C:\inetpub\wwwroot\cmu\include\session.php on line 52
PHP Fatal error: Call to a member function login() on a non-object in C:\inetpub\wwwroot\cmu\include\session.php on line 52
I have seen some suggestions that would suggest putting the new database object inside the Session class declaration but I want to avoid doing so because I use the database class several other places in the code and I don't want to open up multiple connections to the database.
since you want to have acces on a globally set variable, you can either gain access to it with global:
function processlogin($username, $password){
global $database;
$database->login($username, $password);
}
or use the variable as a parameter for the contructor and remember the database object reference in the class Session:
class Session{
private $database;
function __construct($database){
$this->$database = $database;
}
function processlogin($username, $password){
$this->database->login($username, $password);
}
}
and then you call:
$database = new MySQLDB();
$session = new Session($database);
this comes in handy, if you use more functions afterwords, that also need access to the database object.
you could pass a reference to the MySQLDB instance in the Session constructor.
class Session{
public $db;
function __construct(&$db=null){
if($db == null)
$this->db = new MySQLDB();
else
$this->db = $db;
}
// ....
}
$database = new MySQLDB();
$session = new Session($database);
You are creating two global variables. If you're doing such thing, you need to declare variables you want to use in function with "global" keyword:
function processlogin($username, $password){
global $database;
$database->login($username, $password);
}
Despite this will work, I highly recommend reading about Dependecy Injection mechanism in which you'd pass $database variable as a parameter to processlogin() method, or set it as a private member of that class in constructor / setter. That way database connection will be interchangeable and you'll get more flexibility in your code.
$database is not defined inside processlogin nor passed as parameter, hence the function has no access to it.
You could pass it as constructor parameter to Session:
class Session {
private $db;
public function __construct($database) {
$this->db = $database;
public function processlogin($username, $password){
$this->$db->login($username, $password);
}
}
$database = new MySQLDB();
$session = new Session($database);

Categories