use an object previously declared in an other class - php

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?

Related

Set $mysqli as a global variable for OOP

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

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 !

Could someone give a perfect example of a basic "user" object system, using PDO?

What I'd like is to see the ideal framework for a system which has a group of objects (ie User) whereby the data is contained in a database. I've been advised to have a User class and a UserMapper class and this is my understanding of how it should look:
user.class.php
/* The class for constructing any user's information
*/
class User {
protected $userId, $email, $userGroup;
protected function getEmail() {
return $this->email;
}
protected function getUserId() {
return $this->userId;
}
public function __construct($userId, $email, $userGroup) {
$this->userId = $userId;
$this->email = $email;
$this->userGroup = $userGroup;
}
}
class UserMapper {
// database connection
private $db;
public function __construct($db)
{
$this->db = $db;
}
public function findByUserId ($userId) {
$userObject = new User();
$q = $this->db->prepare("SELECT userId, email, userGroup FROM user WHERE userId = :userId");
$q->bindValue(":userId", $id);
$q->setFetchMode( PDO::FETCH_INTO, $userObject);
$q->execute();
$q->fetch(PDO::FETCH_INTO);
return $userObject;
}
}
?>
main.php
<?php
include user.class.php;
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
$getUser = new UserMapper($dbh);
$user = $getUser->findByUserId(41);
echo $user->getEmail();
?>
But this seems a bit messy in terms of the main.php side. Can I not make one PDO object and have that defined in all of my scripts? As well as a UserMapper object? Or do every time I want to get a user from the database do I need to make a NEW userMapper object, then do findByUserId (as above). Or is there a simpler way to doing this?
If I wanted to call a UserGroup object within the class User, how would I do this? (This would also need to connect to the database through PDO). To do the following seems messy:
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
$getUserGroup = new UserGroupMapper($dbh);
$userGroup = $getUserGroupMapper->findByUserId($this->userGroup);
?>
one thing that i can think of is making this class a singleton, and create the $user above the declaration of the class, so whenever you include this class you'll have that user object.
Can I not make one PDO object and have that defined in all of my
scripts? As well as a UserMapper object?
You're actually looking for a Front Controller.
That is, in order to avoid the same instantiation of the same classes, you should have prepared them. Most people usually do this in bootstrap.php, that "tweaks" all required dependencies.
But a front controller implementation also includes a dispatcher and a router. I won't go deep into this, but focus on the problem you're trying to solve instead.
Factory pattern
It basically abstracts instantiation logic. The benefits are: 1) you can delay object instantiation 2) You avoid global state, which is bad for unit-testing. The simplified version of it would look like as:
class UserFactory
{
private $pdo;
private $cache = array();
public function __construct($pdo)
{
$this->pdo = $pdo;
}
public function build($mapper)
{
if (isset($this->cache[$mapper])) {
return $this->cache[$mapper];
} else {
// Inject an instance into a mapper
$instance = new $mapper($this->pdo);
// Save the state into a cache
$this->cache[get_class($instance)] = $instance;
return $instance;
}
}
}
And finally
A very simplified version of bootstrap-er would look like as,
<?php
/* File : bootstrap.php */
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
// Include here UserFactory class
$userFactory = new UserFactory($dbh);
// Its kinda ready to be used
You would simply include in all scripts that need to access Users
<?php
/* File: main.php */
include(__DIR__ . '/bootstrap.php');
$getUser = $userFactory->build('UserMapper');
$user = $getUser->findByUserId(41);
echo $user->getEmail();
You need to use FETCH_CLASS instead and you don't need a userMapper just extend PDO then set the right fetch mode all in one class.
Don't forget to make the class definition available or use an autoloader
$this->statement->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE,"className");
FETCH_PROPS_LATE is there to get the constructor fired first in your class But you don't need a constructor in your case so just lose it. If you decide to keep it though than you should take a look here first.
Hope this helps good luck

OOP efficiency when using a class in another class

I have a class called DB (class.pdo.php) that does all the handling on mysql queries using PDO and another class called user that I use to manage a login system.
My question relates to always having to instantiate the $db in every public function of users so I can use DB. Is this efficient? Shouldn't I be instantiating DB inside the __construct() of users?
This is my code
require_once("../../class.pdo.php");
class user {
private $db = null;
public function __construct(){
/* Empty? */
}
public function find_by_email($email){
$db = new db();
$db->query('SELECT * FROM users WHERE email = :email LIMIT 1');
$db->bind(':email',$email);
$result = $db->single();
return $result;
}
public function create($email,$password,$first_name,$last_name){
$db = new db();
$db->query("INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (:email,:password,:first_name,:last_name,NOW())");
$db->bind(':email',$email);
$db->bind(':password',$password);
$db->bind(':first_name',$first_name);
$db->bind(':last_name',$last_name);
$result = $db->execute();
return $db->lastInsertId();
}
[more similar functions ommited]
Well, despite of some comments suggesting the use of the Singleton pattern, I totaly disagree in using it for this purpose.
Your application will not always use a single connection to just one database.
Let me show you how I'd do this:
class DbConnector {
private $dbh;
private $dsn;
public function __construct($dsn) {
$this->dsn = $dsn;
}
private function connect() {
if($this->dbh === null) {
$this->dbh = new PDO($this->dsn);
}
}
public function disconnect {
if($this->dbh !== null) {
$this->dbh = null;
}
}
public function query($sql) {
$this->connect();
//... do the rest
}
public function fetchAll($sql) {
$this->connect();
//... do the rest
}
public function insert($table, $values) {
$this->connect();
//... do the rest
}
public function update($table, $values, $cond) {
$this->connect();
//... do the rest
}
public function delete($table, $cond) {
$this->connect();
//... do the rest
}
}
class User {
private $dbConn;
public function __construct(DbConnector $dbConn) {
$this->dbConn = $dbConn;
}
public function create($email,$password,$first_name,$last_name){
$this->dbConn->query("INSERT INTO users(email,password,first_name,last_name,created_at VALUES (:email,:password,:first_name,:last_name,NOW())");
$this->dbConn->bind(':email',$email);
$this->dbConn->bind(':password',$email);
$this->dbConn->bind(':first_name',$email);
$this->dbConn->bind(':last_name',$email);
$this->dbConn->execute();
return $this->dbConn->lastInsertId();
}
// ...
}
Results:
No singleton used = testable.
Connection to the database is just openned when needed
Your connection is persistent. If you open and close connections in every method, you loose the capability of creating transactions.
What about using the Singleton pattern to create one object for the connection and use it everytime you need it, instead of creating new objects all the time?
I would do something similar with lazy loading: don't initiate in the constructor unless you're sure you actually need the connection every time an object is created but absolutly don't create a new object on each method call. Instead, save the resulting object into an object var which is checked on each method call and initiates the connection if missing.
class user {
protected $_db = null;
private function _init_db() { $this->_db = new XXX; }
public function create( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# use $this->_db ..
}
public function find_by_email( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# etc
}
}
This has the advantages of avoiding global static state (singletons..) and only creates the connection / object at the very last moment so you're sure you actually need it and it's not just a useless connection.
Speaking of efficiency, the main problem with your code is that it establishes new connection for the every method called. This one is indeed inefficient to the point of killing your database server. And it's incomparable to the other problem you have.
So, in general, you can have whatever way you want - either get somehow an instance of db class in the every function or use a class variable - but either way have to use single PDO instance throughout whole application.
Also I find your functions quite inefficient from the amount of code point of view, and would have optimized them this way
public function create($email,$password,$first_name,$last_name){
$sql = "INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (?,?,?,?,NOW())";
$this->db->query($sql);
$result = $db->execute(func_get_args());
return $db->lastInsertId();
}
From a object point of view, I'd leave database instantiating within the methods, rather than an entire class.
Each method should only see the variables and data it needs, in order to perform its function.
For instance, a createUser() method would need to see variables or properties such as $username, $usergroupId, as well as $database etc.
However, you may have a function which is called randomPassword(), which generates a random password from numbers and letter.
This randomPassword() function doesn't need the database object and therefore, an already initialised database connection in the object scope would be wasteful.
It would be better only to create the new database object in methods that required it.
In addition, in my application, I don't create a new database connection each time I used new database. Instead, I've opted for a singleton PDO database object which keeps the connection active.
I can then just call the database object statically to retrieve an existing connection. Therefore, if, in the process of running my application I need to have 20 database objects, my application then only returns the same object, and the same connection.

Database and OOP Practices in PHP

Its difficult to explain this situation but please see the example.
I have coded a website where the page loads, I initialize a database class. I sent this class as a function parameter to any functions that needs to access database.
I know this is bad approach but currently I have no clue how to do this any other way. Can you please help me.
Example
class sms {
function log_sms($message, $db) {
$sql = "INSERT INTO `smslog` SET
`mesasge` = '$message'
";
$db->query($sql);
if ($db->result)
return true;
return false;
}
}
then on the main page..
$db = new db(username,pass,localhost,dbname);
$sms = new sms;
$sms->log_sms($message, $db);
Is there any better approach than this ?
there are number of options how to resolve dependencies problem (object A requires object B):
constructor injection
class Sms {
function __construct($db) ....
}
$sms = new Sms (new MyDbClass);
setter injection
class Sms {
protected $db;
}
$sms = new Sms;
$sms->db = new MyDbClass;
'registry' pattern
class Registry {
static function get_db() {
return new MyDbClass;
}}
class Sms {
function doSomething() {
$db = Registry::get_db();
$db->....
}}
'service locator' pattern
class Loader {
function get_db() {
return new MyDbClass;
}}
class Sms {
function __construct($loader) {
$this->loader = $loader;
function doSomething() {
$db = $this->loader->get_db();
$db->....
}}
$sms = new Sms(new Loader);
automated container-based dependency injection, see for example http://www.sitepoint.com/blogs/2009/05/11/bucket-is-a-minimal-dependency-injection-container-for-php
interface DataSource {...}
class MyDb implements DataSource {...}
class Sms {
function __construct(DataSource $ds) ....
$di = new Dependecy_Container;
$di->register('DataSource', 'MyDb');
$sms = $di->get('Sms');
to name a few ;)
also the Fowler's article i gave you before is really worth reading
For starters you can make a protected $db variable in each of your classes that need to utilize the database. You could then pass $db in to the class constructor. Here's the updated code:
$db = new db(username,pass,localhost,dbname);
$sms = new sms($db);
$sms->log_sms($message);
class sms {
protected $db;
public function __construct($db) {
$this->db = $db;
}
public function log_sms($message) {
$sql = "INSERT INTO `smslog` SET
`mesasge` = '$message'
";
$this->db->query($sql);
if ($this->db->result)
return true;
return false;
}
}
This example is in PHP 5.
Singleton is also good practice in application design. They are very useful to avoid repeated queries or calculations during one call.
Passing Database object to every method or constructor is not a very good idea, use Singleton instead.
extend your database, or insert static method inside your db class. (I would also call for config within db constructor method)
class database extends db
{
public static function instance()
{
static $object;
if(!isset($object))
{
global $config;
$object = new db($config['username'],$config['pass'],$config['localhost'],['dbname']);
}
return $object;
}
}
make your method static
class sms {
public static function log($message) {
$sql = "INSERT INTO `smslog` SET `mesasge` = '$message'";
database::instance()->query($sql);
return (bool) database::instance()->result;
}
}
Next time you need to log sms just do static call like this
sms::log($message);
You could either have a static class that has two lists, one of available connections, the other of handed out connections, and just have a connection pool.
Or, if you are using something that has a quick connection time, such as MySQL, then just create the connection in your database class, do all the queries needed for that functionality, then close it. This is my preferred approach.

Categories