I have mysqli connection that is created in the __construct part of my database class:
public function __construct() {
$link = new mysqli($this->host, $this->user, $this->password, $this->db);
}
because of that, every time that I want to create an object of a database (for query) It's create new connection, and that cause "Too many connections" in my script.
The way I am calling to the database (from another class) is like this:
$db = new Database;
$db->query("SELECT language_iso_code FROM languages WHERE language_iso_code = ");
Is there another way to call the query function? Or maybe a way to pass the connection of mysqli to another classes?
You might consider to use a static variable for your class and only connect to the database if the connections not up:
class Example {
private static link = null;
public function __construct() {
if(self::$link === null) {
self::link = new mysqli($this->host, $this->user, $this->password, $this->db);
}
}
}
Related
I work now on a project for learning i'm a beginner, i use singelton pattern to make sure, that there is just one PDO connection to the Data Base.
I made var_dump() for all possible connections to the Mysql and I founded that there were 10 objects of pdo.
how can i found, from where come all this objects?
Are 10 objects of PDO normal?
I wanted to use just one for all the project.
my singelton
<?php
namespace App\Database;
use PDO;
use PDOException;
class DataBase
{
private static $instance;
private PDO $pdo;
private function __construct()
{
try {
$db= parse_ini_file("..//..//..//config.ini");
#$db= parse_ini_file("..//..//config.ini");
$type = $db['type'];
$host = $db['host'];
$name = $db['name'];
$user = $db['user'];
$password = $db['password'];
$this->pdo = new PDO($type . ':host=' . $host . ';dbname=' . $name, $user, $password);
}
catch (PDOException $e) {
echo "there is an error";
die();
}
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $this->pdo;
}
private function __clone() {}
public static function getInstance()
{
if (!static::$instance) {
static::$instance = new DataBase();
}
return static::$instance;
}
public function getPdo(): PDO
{
return $this->pdo;
}
}
?>
then I made a connection of the pdo like this in another place, where I need to use pdo init.
function makePdo(){
$db= DataBase::getInstance();
$pdo= $db->getPdo();
var_dump($pdo);
return $pdo;
}
Thank you
10 connections are not normal, you should have only one to one DB. Use singleton pattern for database connection:
https://gist.github.com/jonashansen229/4534794
https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
In this case, you will have one connection and always will get it instead of creating duplicates.
No it should be only one object, the best way to implment it, is to create a separate config file to store your DBMS credentials as associative array, like mysql db_name, host .. etc.
Then create a config class to get those values by creating a static get method.
and finally use this get method inside your db constructor to get the credentials.
I'm pretty sure If you do that you'll get only one instance of PDO object.
I am trying to find a way to get the variable called $connect to run but don't know how.
Filename: /engine/init.php
class Engine {
function MySQL() {
$connect = new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char", $db_user, $db_pass);
}
}
Filename: /inc/database.php
require 'engine/init.php;
$engine = new Engine;
$conn = $engine->MySQL;
// Activate $connect variable
If it's not clear, please request for more info.
Thanks,
CrAzYz_
You will have to update the class to access members outside.
You have several options to do it.
1: store the connection in a public property
class Engine {
public $connection;
public function MySQL() {
$this->connection = new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char",$db_user, $db_pass);
}
}
This way you can retrieve it by
$engine = new Engine();
$engine->MySQL();
$conn = $engine->connection;
2: Make the function return the connection
class Engine {
public function MySQL() {
return new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char",$db_user, $db_pass);
}
}
This way your example will work (if you use Mysql as a function):
$engine = new Engine();
$conn = $engine->MySQL();
3: A more complicated but generally better aproach:
class Engine {
protected $connection;
public function __construct($db_host, $db_name, $db_user, $db_pass $db_char = "utf-8") {
$this->connection = new PDO("mysql:host=$db_host;dbname=$db_name;charset=$db_char",$db_user, $db_pass);
}
public function MySQL() {
if ( !$this->connection instanceof PDO ) {
throw new Exception("Connection is not set up");
}
return $this->connection;
}
}
This would work almost as you wanted, except you cant access the connection directly (its protected), but only through the MySql function. This way if you forgot to init the connection an exception is thrown.
$engine = new Engine("localhost", "db_name", "user", "pass");
$conn = $engine->MySQL(); // you don't even need to save the connection to a local variable, because the function only references the connection and won't start a new one
Footnote:
If you had to as this kind of question you should probably look up and learn more about OOP. For php this is a start: http://php.net/manual/en/language.oop5.php
About to run off so this is a little quickly done.
class Engine
{
public $db;
public function connect($host, $database, $charset, $user, $pass)
{
$this->db = new PDO("mysql:host=$host;dbname=$database;charset=$charset", $user, $pass);
}
}
First of we have your Engine class that you want to create, we've created a property named db on the class that we can access with ->db. We also have a method called connect which we pass our database variables into so that PDO can connect to our database.
Now we pass in our database credentials to our connect method, in a production environment I really would advise against hard coding these and instead use something like environment variables.
$engine = new Engine();
$engine->connect('127.0.0.1', 'example_database', 'UTF-8', 'root', 'root');
We can then use our newly initiated PDO connection like so:
$statement = $engine->db->query('SELECT * FROM some_table');
$result = $statement->execute();
That should at least give you a starting point, there are other ways to go about this but I didn't want to stray too far from your original code.
Also if anyone spots anything wrong, let me know and i'll update it when I'm back in, need to run off in a sec.
This question already has answers here:
Can't connect to MySQL with PDO
(2 answers)
Closed 26 days ago.
I have to create getConnection function inside of Database class. The function should connect to a database using PDO object and returning it.
I have something like this:
class Database {
public function getConnection() {
$result = new PDO('mysql:host=localhost;dbname=demo', 'root', '');
return $result;
}
}
Is it correct? How can i know if i'm connected to database?
PDO will throw an exception if the connection attempt fails, so you can normalize that like this:
class Database {
private $_conn = null;
public function getConnection() {
if (!is_null($this->_conn)) {
return $this->_conn
}
$this->_conn = false;
try {
$this->_conn = new PDO('mysql:host=localhost;dbname=demo', 'root', '');
} catch(PDOException $e) { }
return $this->_conn;
}
}
$db = new Database();
$conn = $db->getConnection();
if (!$conn) {
die("Error connecting to the database");
}
$conn->whatever();
How can i know if i'm connected to database?
PDO will throw an exception in case of connection error.
Is it correct?
Nope, it's not a good idea, because the method is called getConnection while in reality it creates a connection. And a public property asks to call it in the application code, resulting multiple connections from the same script.
Besides, you should always set PDO in exception mode. And you should set charset in DSN as well.
Depends on the proposed use of this function the code could be
protected function connect()
{
$pdo = new PDO('mysql:host=localhost;dbname=demo;charset=utf8', 'root', '');
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
return $pdo;
}
if it's intended to be used only once in the constructor.
While for the getConnection() function you are bound to use a static variable ho hold the single instance of PDO.
Recently I took time to compile all the common mistakes for the database wrappers in the article Your first DB wrapper's childhood diseases. You may find this reading extremely useful.
I'm new. Below is the beginning of an attempt to interface with a database. Please let me know if the syntax is not correct, it seems to work on my localhost.
I think I could have typed class Database extends Mysqli, right? which would then have made the methods of Mysqli directly accessible to Database rather than through an instance created in the class itself. Would that have been preferable to what I have done?
class Database {
#The variable that stores the database handle
public $db;
#The Database objects's datbase parameters
public $host;
public $user;
public $password;
public $database;
#creates a Database object with the required databases details
public function __construct($host, $user, $password, $database) {
$this->host = $host;
$this->user = $user;
$this->password = $password;
$this->database = $database;
}
#Stores the database handle as a var $db of the Database instance
public function connect() {
if ($this->db = new Mysqli($this->host, $this->user, $this->password, $this->database)) {
if ($this->db->connect_errno) {
echo "No connection could be made <br/>";
} else {
echo "database succesfully connected <br/>";
}
}
}
}
If your class Database represents the database handle, then it should not have it public:
#The variable that stores the database handle
public $db;
Otherwise you would not encapsulate that detail and therefore you wouldn't need your class at all.
Next to that, when you start to write classes, echo does not belong in there:
if ($this->db = new Mysqli($this->host, $this->user, $this->password, $this->database)) {
if ($this->db->connect_errno) {
echo "No connection could be made <br/>";
} else {
echo "database succesfully connected <br/>";
}
}
Because classes consists of methods returning via their return value and not via standard output. Instead you want to throw an exception here. Which is also a feature of Mysqli already, therefore, you don't need to write that error handling code your own to get started:
Turning query errors to Exceptions in MySQLi
After getting these more or less obvious ones out of the way, you're asking yourself whether or not you should inherit mysqli instead of aggregating it.
I actually can not tell you. So far the code you've shared just shows standard functionality of a mysqli therefore I would suggest to drop that class completely as the code looks superfluous. So I would say: neither. I see no reason for your Database class as you just could use mysqli instead.
I'm quite new to PDO and also OOP with PHP in general so please be nice :) Basically I'm trying to make a connection object based on PDO so that I can have one connection that I call throughout my site.
I need some prepared statements that simply look up different results based on an ID I pass through using the same db object that I'm trying to create below.
How do I make and access the db class I set below and then use functions within it to extract the relevant info I need? Any examples would be great so I can get an idea of the best practices etc.
Many thanks in advance.
class db {
private static $connection;
private function __construct(){}
private function __clone(){}
private static function connect($db_server="localhost", $db_user="user", $db_pass="password") {
if(!$this->connection){
try{
$this->connection = new PDO($db_server, $db_user, $db_pass);
} catch (PDOException $e) {
$this->connection = null;
die($e->getMessage());
}
}
return $this->connection;
}
}
$dbh = new db::connect();
$stmt = $dbh->prepare("SELECT * FROM questions where id = ?");
if($stmt->execute(array($_REQUEST['testid']))) {
while ($row = $stmt->fetch()) {
print_r($row);
}
}
You could begin by not ever using Singleton pattern again. It (and static classes in general) is bad for all the same reasons why global variables in procedural programming are bad.
That said ... Instead of trying to enforce the uniqueness of the connection object, you should be just making sure that you using the same connection all over the place.
Here's an example of what i mean by that:
class Foo
{
protected $connection = null;
public function __construct( PDO $connection )
{
$this->connection = $connection;
}
}
class Bar
{
// all the same as in Foo
}
$connection = new PDO('sqlite::memory');
$foo = new Foo( $connection );
$bar = new Bar( $connection );
At this point both $foo and $bar objects will have access to the same PDO instance. If you have an object that needs access to database, then you just provide it with a connection in the constructor.
There are two videos you might want to watch (slides will contain Java code, but you should have no troble understanding it):
Global State and Singletons
Don't Look For Things!
Persistent connections are built in:
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
PDO::ATTR_PERSISTENT => true
));
See Example #4 Persistent connections