I don't know my method is correct for connecting to the database in php.
Here is the method i am used.
1.created a db_functions.php file.
db_functions.php
/*----for connecting db----*/
function db_connect(){
$connect=new PDO('mysql:host=localhost;dbname=keralalotteryapp','root','');
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $connect;
}
function get_student_data(){
$con=db_connect();
//rest of my query
}
function get_marks($id){
$con=db_connect();
//rest of my query
}
2.In every my page i've included this and call the functions like this way
<?php
require 'db_functions.php';
get_student_data();
get_marks($id);
?>
But everytime call the functions get_student_data() and get_marks() it will again call the db_connect function.
So this is right way to do this?
Create a connection class in a Connection.php file :-
class Connection{
public static $PDO =null;
public static function getConnectionInstance()
{
try{
$PDO = new PDO('mysql:host=localhost;dbname=keralalotteryapp','root','');
return $PDO;
}catch(PDOException $e)
{
die($e->getMessage());
}
}
}
or use this class any other php file like that :-
require_once './Connection.php';
function __construct() {
$this->dbh = Connection::getConnectionInstance();
}
create construct or call static method of connection call
There are many ways to manage database connections, I've seen a global connection object, I've seen some people do connection factories, at the end of the day it really comes down to your needs in your specific application.
That being said, if you have the support for it, I have always been a fan of a closure-based setup as I find it becomes easy to write clean code.
function execute_in_db_context($callback) {
$connect=new PDO('mysql:host=localhost;dbname=keralalotteryapp','root','');
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$callback($connect);
$connect=null; //cleanup because we can
}
execute_in_db_context(function ($db_connection) {
//blah blah
});
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.
Ok,
This is sort of an involved problem, but any help or advice would be incredibly appreciated.
So I'm working with a site that (using .htaccess) redirects all traffic to a load.php. For any sql functionality, I have an abstract class that has a lot of query statements as functions that pass parameters to define the specifics of each query.
e.g.
$table->update("constraints")
I'm trying to figure out how to set the connection to the database on load.php, and then set the connection as a variable ($mysqli) that can then be referenced in my abstract query class without having to pass the parameter to every single query function call.
Again, any help or advice would be appreciated.
Here's an example of a function:
function clearTable (){
$mysqli = dbConnect::connect();
$sql = "TRUNCATE TABLE $this->tablename";
$mysqli->query($sql);
}
If I connect to the database in a construct function and set $this->mysqli and replace $mysqli = dbConnect::connect(); with $mysqli = $this->mysqli, none of the queries work. Though they work with a fresh reconnect on each call.
You should use Dependency Injection for this.
Basically it means that the class that needs the database connection doesn't create the connection, it just receives the already instasiated instance.
Example
In some init file:
// Create the db connection
$db = new Mysqli(......);
// Pass it to the query class that needs it
$queryClass = new QueryClass($db);
Then in your class file:
class QueryClass
{
protected $db;
public function __construct($db)
{
// $this->db will now be the same Mysql instance
$this->db = $db;
}
public function doSomeQuery()
{
$this->db->query(....);
}
}
A bonus for this is that you don't need to touch the QueryClass, if you ever want to start making some unit tests. You only need to pass a DB connection to a test database instead.
After looking through this a bit more, I can also create my db::connect() function to look like this:
class dbConnect {
private static $db;
private $mysqli;
private function __construct() {
$this->mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
}
function __destruct() {
$this->mysqli->close();
}
public static function connect() {
if (self::$db == null) {
self::$db = new dbConnect();
}
return self::$db->mysqli;
}
}
and pass that as $this->mysqli in the query functions file
Greetings good people,
I am running with some issue with OOP recently. First, I am looking to create CRUD Db class from scratch. This is a code:
class Database{
public static $link;
public $message;
public function __construct () {
try {
self::$link = mysqli_connect(HOST, USER, PASS, DB);
if (!self::$link) {
echo self::$link->error;
}
} catch (Exception $e) {
die(" Failed connecting to DB") ;
}
}
public static function query($SQL){
return self::$link->query($SQL);
}
public static function select($table, array $columns){
$columns=implode(",",$columns);
$result=self::query("SELECT $columns FROM $table");
return self::$link->fetch($result);
}
}
So the problem is this:
If I call my static select function like this:
Database::select('users', array('username'=>'user'));
It returns: Fatal error: Call to a member function query() on a non-object in ..
And if I debug connection like this: var_dump(Database::$link) it returns NULL
But if I place "$db = new Database();" above that line, it works?
Can anyone instruct me what I am doing wrong?
Thanks!
You are calling a static method. So, the object WILL NOT be instantiated. So, __construct() method WILL NOT be called. Which means $link property will not be populated.
Whatever you do, you need to connect to your DB. You can either call a static method connect() which will connect to database and populate $link, or make sure in every method that require the connection, that the connection is established:
public static function connect()
{
try {
self::$link = mysqli_connect(HOST, USER, PASS, DB);
if (!self::$link) {
echo self::$link->error;
}
} catch (Exception $e) {
die(" Failed connecting to DB") ;
}
}
public function select(SQL)
{
if (!static::$link) {
static::connect();
}
// your stuff
}
It's a good thing you want to learn. Before dealing with specific projects like that, you need to be comfortable with OOP: constructors/destructors, accessors, mutators, static methods, etc. It's important since it's the basis of all what you will want to do next.
This is my general php page:
<?php
require_once('includes.php');
require_once('cms.class.php');
.....
rest of the page
?>
in includes.php an pro object called $db is initiated which I want to use in the class specified in the cms.class.php
includes.php:
$db = new PDO('mysql:host=localhost;dbname=xxxxx','xxxxx','xxxxxx');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
How can I use this database object in my classes without having multiple places where my credentials are stored?
You need want a dependency manager or a bootstrapper or whatever you want to call it.
class Dependency_Manager {
private $db;
public function __construct($settings) {
$this->db = new PDO('mysql:host=localhost;dbname=' . settings["dbname"],settings["username"],$setings["password"]);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
public function getDB() {
return $db;
}
}
class CMS {
public function __construct(PDO $db) {
/* .. */
}
}
$setting = array(/* etc */);
$dm = new Dependency_Manager($settings);
$cms = new CMS($dm->getDB());
This approach scales very well and can handle any dependecy. It also aims to put all the settings in one place so you don't have configuration settings littered everywhere. The $dm is the only one who knows the settings, if you need to construct something based on the settings, put it in the $dm.
There are 2 ways that you could go about this.
The first way, injection, is growing in popularity. Injection means you would supply $db to your class. You could do something like this.
Injection:
class CMS_class {
protected static $db;
public function __construct($db) {
if ( ! isset(self::$db))
self::$db = $db;
}
public function __get($name) {
if ($name === 'db')
return self::$db;
}
}
Now when you construct the CMS class you pass it the $db variable which is accessible via ->db, but there is only one instance.
The second method would be to call it globally in every function you use it.
Global:
class CMS_class {
function hello_world() {
global $db;
var_dump($db);
}
}
This way is losing popularity because globals are generally frowned upon and you will have to declare it in every function that you need $db.
There are other good answers out there that relate to your question.
How can I use "Dependency Injection" in simple php functions, and should I bother?
A beginner question: I don't know how best to structure this bit of code, but basically it goes like this (pseudo code time):
if (form = submitted) {
submitted();
}
else {
printForm();
}
function submitted() {
process data from form;
if(errors = found) {
print warnings;
printForm();
} else {
submit to database;
}
}
function printForm() {
print form with databound elements;
}
I use the following bit of code to create a User object, but it seems weird to call it twice -- once in submitted() and once in printForm(), especially since submitted() calls printForm() if errors are found.
Unfortunately database access is required for processing the data from the form (checking for existing email address, etc), so I have to call the following bit of code in both submitted() and printForm()...
try {
$db = new Database();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($db);
}
catch (PDOException $e) {
echo "<p>Error connecting to database: </p>".$e->getMessage();
}
But my instincts tell me that this is bad. Is it? If so, how should I fix it?
Use dependency injection:
function submitted(Database $db, User $user) {
// ...
}
function printForm(Database $db, User $user) {
// ...
}
try {
$db = new Database();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($db);
}
catch (PDOException $e) {
echo "<p>Error connecting to database: </p>".$e->getMessage();
}
submitted($db, $user);
printForm($db, $user);
Of course, it's better to use OOP, as then you wouldn't have to inject the dependencies into every single function:
class Foo {
protected $db;
protected $user;
public function __construct(Database $db, User $user) {
$this->db = $db;
$this->user = $user;
}
public function submitted() {
// use $this->db and $this->user here
}
public function printForm() {
// use $this->db and $this->user here
}
}
try {
$db = new Database();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($db);
$foo = new Foo($db, $user);
}
catch (PDOException $e) {
echo "<p>Error connecting to database: </p>".$e->getMessage();
}
$foo->submitted();
$foo->printForm();
There are several ways of making this better...
One would be to initialize $user before the function calls and inject it into each function (dependency injection).
Another way would be to make a singleton of the user instance (although I could see this leading to problems down the road) and retrieve the instance in the function using something like User::instance().
Dependency injection is better in my opinion because it makes your functions easier to test.
Now, on to the rest of the code:
It's typically not good practice to echo anything within a function or class method. You should be returning data instead and handling it outside the function.
Your db instantiation should probably go in a bootstrap file that's included at the top of every script. It's also probably better if your script handles the connection error gracefully (let the user know something went wrong, send yourself an email, stop the rest of the script execution) if the connection fails rather than simply echo'ing an error message.
Although the Singleton pattern is considered to be evil in some cases, it seems that in PHP (with a separate worker process for each request) and in your case it is the easiest way to implement what you want.
So that you have the instance of User who initiated the request available in any script on any page, and you have to initialize the $user object only in one place per project (not in one per script as you were wanting to do).