How to access variables in OOP - php

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.

Related

mysqli connection done in __construct and cause too many connections

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

Function to connect to database using PDO [duplicate]

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.

How to use $db from another .php to another .php's class using OOP?

I am new to OOP PHP, and I've been working with procedural API since I've started Web Development so I'm having a hard time migrating to OOP.
so let's say I have this four .php file and structures below.
connection.db.php
<?php
define("DB_HOST", "127.0.0.1");
define("DB_USER", "root");
define("DB_PASS", "");
define("DB_NAME", "sample_db");
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
echo (!$db->connect_error) ? NULL : die("<pre>Unable to connect to the MySQL Server -> $db->connect_error</pre>");
?>
sampleclass.class.php
<?php
public $db;
class MySQLqueries {
public function samplefunction($queryString) {
$sqlQry = mysqli->query($queryString);
return ($sqlQry) ? "<pre>Query Executed Successfully</pre>" : die("<pre>An error occured -> $db->error</pre>");
}
}
?>
includes.inc.php
<?php
error_reporting(0);
date_default_timezone_set("Asia/Manila");
require 'connection.db.php';
require 'sampleclass.class.php';
?>
index.php
<?php
require 'includes.inc.php';
$todo = new MySQLqueries;
echo $todo->samplefunction("SELECT `sample_column` FROM `sample_table` WHERE `sample_column` = 'sample_value';");
?>
As you may or may have not noticed, my problem is how to use the $db from connection.db.php in the samplefunction of sampleclass.class.php
You may ask me, why not create a __construct() method in sampleclass.class.php and just move the "$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);" there ?. well if I'm to do this, all other classes will have to have it's own constructor and $db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); declared there right?
With $db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); on the connection.db.php I assume that I can reuse it versatile-ly.
You see I've declared a public $db; in sampleclass.class.php but I don't know what's next. If someone can help me dearly, then I would be a lot grateful.
PS: I've already consulted Dr. Google Ph.D. regarding this matter, and I only got tons of articles or video tutorials showing how to use and do OOP PHP-MySQLi Programming but without using classes and methods.
You'd be best to create a DB class or harnessing an already created one to achieve what you're trying to do.
The usual flow for things like this is call Lazy Loading/Dependency Injection. Where you're passing the required objects into the class.
If you choose this path, I suggest that you read up on Dependency Injection, as many things do, it has pros AND cons but is essential in OOP.
As Ben Stated in the comments:
Dependency injection is a key principle in OOP. I'd like to add that
if you are serious about OOP you should also look into autoloaders in
general, PSR-4 and Composer.
A side not on the above mentioned, you'd be best to look at PHPTheRightWay, they list a lot of stuff, including Dependency Injection.
You'll end up creating something like. It'd be better if you followed this example to understand how it works:
Class DB {
function __construct($host, $user, $pass, $db) {
return $this->connect($host, $user, $pass, $db);
}
function connect($host, $user, $pass, $db) {
//..connect and all.
}
//...the rest of your functions/class...
}
You can construct this anyway you please. Or just make the mysqli object accessible, allowing you to call it.
Now we get to the fun stuff. Actually injecting it into your class;
Class Foo {
$private $db;
// your construct method here will ONLY except a `DB` class instance/object as $db.
// Try it with anything else and learn from the errors to understand what I mean.
function __construct(DB $db){
$this->db = $db;
}
}
$db = new DB($host, $user, $pass, $db);
// you can error check it here
$foo = new Foo($db);// inject the $db object.
If you just want to share the resource, you could harness global, but it is strongly discouraged.
include('connection.db.php');
class MySQLqueries {
public function samplefunction($queryString) {
global $db;
$sqlQry = mysqli->query($queryString);
return ($sqlQry) ? "<pre>Query Executed Successfully</pre>" : die("<pre>An error occured -> $db->error</pre>");
}
}
If you chose this path, you'd be best to assign the global instance of $db to an internal class variable, like $this->db.
As you're alread using objects, you probably should also go to a OOP (Object Oriented Programing) implementation.
So, you may put your $db variable as a static variable in the sampleclass.class.php file, as in:
class MysqlConn
{
public static $db;
}
Like that you instantiate the mysqli object using this code:
MysqlConn::$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
Even better, you could create a method to instantiate the $db connection, initialize the variables in that class:
<?php
class MysqlConn
{
protected
static $DB_HOST = "127.0.0.1",
static $DB_USER = "root",
static $DB_PASS = "",
static $DB_NAME = "sample_db";
protected static $db;
public static function getDB()
{
if (!isset(self::$db) {
self::$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($db->connect_error) {
die("<pre>Unable to connect to the MySQL Server -> $db->connect_error</pre>");
}
}
return self::$db;
}
}
MysqlConn::getDB();
In index.php, you may get the db instance with the following code, not reconnecting every time:
$db = MysqlConn::getDB();
my problem is how to use the $db from connection.db.php in the
samplefunction of sampleclass.class.php
You can use global in your case just incluce or require connection.db.php then use global in php.
Something like this might help you
require_once 'connection.db.php';
class MySQLqueries {
public function samplefunction($queryString) {
global $db;
//You can now use $db variable as you want
print_r($db);
$sqlQry = mysqli->query($queryString);
return ($sqlQry) ? "<pre>Query Executed Successfully</pre>" : die("<pre>An error occured -> $db->error</pre>");
}
}

How do I use multiple classes in PHP

I'm very new to oop in php, so far i'm using multiple classes that I made in one php file, such as:
class Style {
//stuff
}
class User {
//other stuff
}
And many more, yet i'm having an issue on how to connect to mysql within these classes, if I use $db = new Mysqli(); how will I be able to make queries from inside classes? what if i'm trying to make my own connector class like so:
class Connection extends mysqli {
public function __construct($host, $user, $pass, $db) {
parent::__construct($host, $user, $pass, $db);
if (mysqli_connect_error()) {
die('Connect Error (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
}
}
How can I be able to make queries from within different classes? Or what's a better way of using oop in php correctly? with multiple classes to organize different parts of code?
Any help or tips will be appreciated, thanks. What about using PDO? does that make everything easier?
class Style {
public function __construct($conn) {
$this->conn = $conn;
//use $this->conn in the class
}
}
$db = new Mysqli();
$style = new Style($db);
I think the first example is the preferred method, however you could create a simple registry class and use that to store a $db object etc.
If possible I would probably use PDO but that doesn't solve this issue.
Since you are extending the mysqli class you will have access to the functions as you would if you instantiated that class by itself (so long as those functions aren't private). Some folks though (including myself) will instantiate the DB connection in their own custom class with a database connection, then inject that class into classes that need it.
class MyDatabase {
private $this->dbi;
public function __construct() {}
public function connectDB($host, $user, $pass, $db)) {
//You can do this in the constructor too, doesn't have to be its own function
$this->dbi = new mysqli($host, $user, $pass, $db);
}
public function getDBI() {
return $this->dbi;
}
}
You can add all the functions you want to your own class (or an extended class), you can also have any class that needs a database extend your DB class. But that isn't really preferred (each class will have a different db class/connection). The easiest is probably to import your DB connection into your class. Either through the constructor or another function;
class MyClass {
private $this->database;
public function __construct($db) {
$this->database = $db->getDBI();
}
public function query($q) {
//Of course, clean your data first, and best practices use prepared statements
$result = $this->database->query($q);
return $result;
}
}
Then make your database connection and inject it into your class.
$db = new MyDatabase();
$db->connectDB('localhost', 'username', 'password', 'mydb');
$class = new MyClass($db);
$resultSet = $class->query("SELECT * FROM MyTable"); //Obviously anything the user could add here is to not be trusted.
using PDO will give you a lot of functions and flexebilty and it has many drivers built-in.
to make what you are trying to do here is a sample :
STEP 1 :
Make a Main class that will handle your database :
class app extends PDO {
protected $database_hostname = "localhost";
protected $database_username = "root";
protected $database_password = "";
protected $database_name = "testdb";
protected $database_type = "mysqli";
public function __construct() {
try {
parent::__construct($this->database_type . ':host=' . $this->database_hostname . ';dbname=' . $this->database_name, $this->database_username, $this->database_password, array(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION));
} catch (PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
}
}
STEP 2 :
then you need to initilze a globale variable as your Database :
$db= new app() ;
STEP 3 :
include a local variable to handle database in the other classes :
class User{
public $db ;
}
STEP 4 :
in the constructor of the other classes ( user for exemple ) you need to pass the local variable by reference to the globale variable :
class User{
public $db ;
public function __construct(){
global $db;
$this->db =& $db;
}
}
STEP 5 :
then if you want to execute a request from inside a class you do it by the local variable :
$this->db->query("SELECT * FROM user");
and from the outside just by using : $db->query("SELECT * FROM user");
I hope that helped !

Best way to make a PDO mysql static connection class?

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

Categories