Passing an include file from a function in a function - php

I'm pretty new to classes and struggling to connect a simple function to another function. Whenever I add an echo 'test' inside the ConnectDB function it passes through the 'test'. However, it doesn't include the include files.
It's probably a noob mistake.
Note: When I copy/paste the content from ConnectDB to the UpdateFollowers function it works. I'm looking for a way to save time without using an include file.
class UpdateAccountInfo {
public function ConnectDB() {
if (strposa($_SESSION['geturl'], $_SESSION['folders']) != FALSE) {
include '../_includes/config.php';
include '../_includes/opendb.php';
} else {
include './_includes/config.php';
include './_includes/opendb.php';
}
}
// update followers
public function UpdateFollowers($getid) {
$this->ConnectDB();
//find the source of the ig account
$sql = "SELECT * FROM ig_accounts WHERE iid = $getid";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$igname = $row["igname"];
}
............

What is a class?
Before going into any explanation concerning the case at hand, I think it's important to get some OOP concepts straight first. From the example in the question, I get the feeling that your understanding of classes is that they simply are "function buckets" so to speak. This isn't the case. A class is a generic data structure you can use to define objects, behavior related to those objects and data used by those objects.
class Human {
private $firstName;
private $lastName;
private $dateOfBirth;
public function __construct($fn, $ln, $dob) {
$this->firstName = $fn;
$this->lastName = $ln;
$this->dateOfBirth = $dob;
}
public function getFullName() {
return $this->firstName.' '.$this->lastName;
}
}
In the example above, we've defined a basic structure shared by all objects of type Human as well as encapsulated some very basic functionalities (getting the full name of our Human).
If we take a look at your example, UpdateAccountInfo is more of a functionality rather than an object. It is a process that will always be performed by some other component of the system, for the purpose of this example let's call that other component an Account.
class Account {
private $id;
private $name;
private $conn; // <-- our DB connection
/* other Account properties */
public function __construct($id, $name) {
$this->id = $id;
$this->name = $name;
/* Initialize DB connection */
}
public function updateFollowers() {
/* Perform any logic required to update the followers */
}
}
Now we have an object of type Account to which we add however many functions we need in the future. addFollowers(), removeFollowers(), changeUsername(). Those are all examples of processes that belong to the Account object and will likely never be used by any other component of the system.
Initializing the Database connection
You may have noticed that I have left out the database initialization part out of the previous example. There is a few reasons for this but mainly:
Opening and closing a connection each time create an instance of Account (or any object for that matter) using the new keyword is very costly.
It breaks the Single Responsibility Principle. I won't get into that too much as it is a pretty lengthy topic. What you need to know for the time being is that it essentially means that an object should only deal with its own data/processes, and no more. In this case, opening a database connection simply isn't the job of Account.
To get around this, we can simply encapsulate the database connection logic in a Database object.
class Database {
private $connection;
public function connect($localhost, $name, $password, $database) {
$this->connection = new mysqli($localhost, $name, $password, $database);
if($this->connection->connect_error) {
/* throw an exception */
}
}
public function getConnection() {
return $this->connection;
}
}
Now you simply need to initialize the database connection once at the beginning of the script, and pass it around to other objects/functions that may need it.
<?php
include_once('../../config.php');
/* include any other required files */
$database = new Database($config['localhost'], $config['username'], $config['password'], $config['dbname']);
// get a specific account
$account = new Account(/* ... */, $database);
// update the account's followers
$account->updateFollowers(/* ... */);
If we want to modify a second account, we can do so using the same database connection we just opened.
<?php
/* ... code from previous example ... */
// initialize a new Account with the same Database
$otherAccount = new Account(/* new account's info */, $database);
$otherAccount->updateFollowers(/* ... */);
Further readings
PHP documentation on OOP
Wikipedia page on Single Responsibility Principle
How to initialize a database connection

Related

Singleton v Single Instance DB Connection in PHP

I'm moving onto teaching myself OOP in PHP.
I'm creating a couple of little web apps and have followed a lot of tutorials that either create the database (using PDO) via a Singleton, or via passing the global around. I've read that these are pretty much the same thing and are both to be avoided like the plague.
So I've watched the Google Tech Talks on clean code, and read almost every SO article on dependency injection and the like. I have a couple of questions.
The clean code videos suggest you shouldn't do 'work' in your constructors. Is this 'work' in reference to business logic. Ie. If my class's job is to create another object, is that an OK kind of 'work'?
For example, in trying to conform to single repsonibility classes I created three.
Class DB - which actually connects to the database.
Class DBFactory - which creates the DB object which connects to the database.
Class DBInstance - which returns a single instance of the DBFactory created PDO object.
Please note that I'm trying to create a single instance, without creating a Singleton pattern.
So I try and pass my dependencies for each class up the chain. I find myself in a position where I have to create all of the objects (from DB down) so I can inject the dependencies. For some reason I thought it would work the other way, I'd create the first object, which would create the second for me etc. I'm clearly missing something?
Hopefully this helps others as well - there seems to be a myriad of questions relating to this stuff and databases but very little good examples.
(I should mention this does work, I do get a list of hotel names out of the database!)
TestCode.php
include './classes/DB.php';
include './classes/DBFactory.php';
include './classes/DBInstance.php';
include './classes/Location.php';
$db = new DB;
$dbfactory = new DBFactory($db);
$dbinstance = new DBInstance($dbfactory);
$dbh = $dbinstance->getDbInstance();
//Example business logic
$location_names = Location::getLocationNames($dbh);
print_r($location_names);
Class DB.php:
class DB {
private $_dbhost = 'myhost';
private $_dbname = 'myname';
private $_dbuser = 'myuser';
private $_dbpass = 'mypass';
private $_error;
public function connect() {
try {
return new PDO("mysql:host=$this->_dbhost;dbname=$this->_dbname",
$this->_dbuser, $this->_dbpass);
}
catch (PDOException $e) {
$this->_error = 'Error! ' . $e->getMessage() . '<br />';
die();
}
}
public function getError() {
if (isset($this->_error)) {
return $this->_error;
}
}
}
Class DBFactory.php
class DBFactory {
private $_dbh;
public function __construct(DB $db) {
$this->_dbh = $db;
}
public function Create() {
return $this->_dbh->Connect();
}
}
Class DBInstance.php
class DBInstance {
private static $_dbinstance;
public function __construct(DBFactory $dbfactory) {
if (!isset(self::$_dbinstance)) {
self::$_dbinstance = $dbfactory->Create();
}
}
public function getDbInstance() {
return self::$_dbinstance;
}
}
Your code seems to do what you want it to.. but maybe we can use less object instantiation using inheritance and maybe we can avoid static properties in instanciated classes.
Also in regard to using a pattern of dependency injection that is able to handle multiple connections, but support using a single instance of it. exemple first, classes after
$params = array
('host'=>'localhost',
'db'=>'ice',
'user'=>'kopitar',
'pass'=>'topnet',
'charset'=>'utf8'); // passing the charset explicitely is great
$handle = new handle($params);
$db = $handle->getInstance();
we can either pass the $db to our functions
$location_names = Location::getLocationNames($db);
or the whole $handle. as long as $handle is not reconstructed, it will always return the same database connection.
$location_names = Location::getLocationNames($handle);
if I want to reconstruct I need the whole $handle
$handle->__construct(/* params but with another database infos */);
$db2 = $handle->getInstance();
As for the classes, I think we want the params to arrive from the instanciated class, so we can change them later.
class db {
function __construct($params) {
foreach ($params as $param => $value) {
$this->{$param} = $value; // assigns the connections infos
}
}
protected function connect() {
$dsn = 'mysql:host='.$this->host.';dbname='.$this->db.';charset='.$this->charset;
return new PDO($dsn,$this->user,$this->pass);
}
}
the factory creates a connection from params and passes it to something else, good factory
class factory extends db {
protected function create() {
return $this->connect();
}
}
now we want to have our object to keep it's connection as long as we do not rebuild it. so we give it to instance
class instance extends factory {
function instantiate() {
$this->instance = $this->create();
}
}
and last but not least, our handle which returns the instance. it could be in instance class.....................
but I feel like having four and find no real reason not to.
class handle extends instance {
function __construct($params) {
db::__construct($params);
$this->instantiate(); // when we construct a handle, we assign an instance to the instance property
}
function getInstance() {
return $this->instance;
}
}
KISS
Don't make things more complex than they are, of course this is just my opinion, but as I see it you are building a complex solution for a problem that someone else says might exist is some cases.
Php is not multi threaded so there goes one of the biggest arguments overboard. (in very rare-occasions it might be)
I'm using singletons for my database connections for about 15 years now and never ever had a problem with them, I do play around with different connections having one singleton handle several connection instances, but whatever... it works great and everyone that looks at the code.. understands it directly.
I'm not using globals because they can be overwritten and are kind of hard to predict (when it holds the correct object, and when/why they don't)
Use OOP to make your code cleaner, easier to work with and more flexible.
Don't use it to fix problems that aren't there and make your code more complex because others tell you to.
An very simple example of a db-connection singleton class handling several different connections.
class singleton{
private static $_instances=array();
public static function getInstance($connectionName){
if(!isset(self::$_instance[$connectionName]){
self::$_instance[$connectionName]=self::_getConnection($connectionName);
}
return self::$_instance[$connectionName];
}
}
just my 2 cents
Why do you have a factory if you have a singleton? This is needless.
This is a never-ending debate, but I'm advocate of do not use singletons for database connections.
As far as in most applications, you have only one data channel, you can consider your database connection unique, but this might not be always true.
In deed, the effort made to create a singleton database connection is even bigger than just create a regular one.
Also, your class DB is not configurable, therefore, you need to change it when your connection parameters change. And I think DB is a very bad name for this.
I'd rather call this Storage and do something like:
inteface Storage {
public function insert($container, array $data);
public function update($container, array $data, $where);
public function delete($container, $where);
public function getAll($container);
public function getOne($identifier);
}
final class PdoStorage implements Storage {
private $dbh;
private $dsn;
private $user;
private $pswd;
public function __construct($dsn, $user, $pswd) {
$this->dsn = $dsn;
$this->user = $user;
$this->pswd = $pswd;
}
// Lazy Initialization
private function connect() {
if ($this->dbh === null)
$this->dbh = new PDO($this->dsn, $this->user, $this->pswd);
}
public function insert($container, array $data) {
$this->connect();
// ... omitted for brevity
}
}
Now, when you need a database storage, you do:
$someObj = new SomeClass(new PdoStorage(...));
Now you might be wondering if you will need to create an PdoStorage for each single object that depends on it.
The answer is: no!
Now you can use a factory to simplify your life.
class SomeFactory {
private $defaultStorage;
public function __construct(Storage $storage) {
$this->defaultStorage = $storage;
}
public function create($type) {
// Somehow fetches the correct class to instantiate and put it into $class variable , for example... and then
return new $class($this->defaultStorage); // Or you'd better do this with reflection
}
}
$factory = new SomeFactory(new PdoStorage(...));
$factory->create('SomeClass');
This way, you can have just one database connector or more if you need.

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.

What are other PHP class designs for DB object interactions?

I have a table called "User" that holds user info. I'll call my user class and create a user object so that I can grab whatever info is needed for that user.
I have been using the below classes and hybrids of them for my sites but have been never really happy with them mainly because I'm unsure how other developers handle this situation and if there is a better solution. Below are a few methods I have been using, I'm curious to see how other developers are doing.
Idea # 1
class User
{
//public user
public function __construct()
{
//get user - queries table and returns all fields in array
}
//get name function - references user array and returns name
//set name function - sets new name in array
//commit function - commits array to db (saves changes)
}
Idea # 2
class User
{
//user id
public function __construct(user id)
{
//set user id
}
//get name function - calls db directly and returns name
//set name function - calls db directly and sets name
//commit function - commits array to db saves changes
}
Idea #1 seems to be the most efficient, or least amount of DB calls but a little more complex and less straightforward than Idea #2.
I like idea #2 better but I'm afraid of it's scalability because each function makes a call to the DB.
Thoughts
I would recommend for you to learn about DataMapper pattern. The basic idea goes like this :
Lets say (for the sake of example ) that you have an MVC structure for application that deals with books.
It would make sense to have a model Library which is responsible with domain logic of managing different books.
The model deals with unknown number of Book instances ( many books in a library ). Each book :
knows everything about itself ( authors , publishing date , language .. etc.)
has no idea where it is stored or where the data come from
can be related to a table in Database , but contains information from multiple tables
And then you have an instance of BookMapper class, which :
model receives in the constructor ( implementing predefined interface )
knows how to ( and where ) store the Book objects , and how to read data into them
can be switched to a different object, if storage medium changes
if it works with DB, then it in constructor has already requested a DB object ( like PDO )
has methods store( Book $book ) and retrieve( Book $book ) for saving book's data , or getting new info from storage
This is how i would do it ..
What about something like:
class Db
{
function __construct()
{
$this->engine = DB_ENGINE;
$this->dbname = DB_NAME;
$this->host = DB_HOST;
$this->username = DB_USERNAME;
$this->password = DB_PASSWORD;
$this->connect();
}
function connect()
{
$this->db = new PDO($this->engine.':host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password);
}
}
class Table extends Db
{
protected $from = null;
function __construct()
{
parent::__construct();
}
function select($columns, $where, $order, $offset, $limit)
{
}
function update($where, $data)
{
}
function delete($where)
{
}
etc...
}
class User extends Table
{
function __construct()
{
parent::__construct();
$this->from = 'blog';
}
function get_user()
{
$this->select(params);
}
function get_user_count()
{
}
etc...
}
This way you can easily use it to get other info as well just be creating a new class with it's functions to retrieve / delete / etc the info.
Firstly the user object is meant to hold user data, so i would suggest method #1, method #2 is more of a amodel object that send's commands to fetch data.
Now, you can automatically map user rows to an object in 1 single query, for example:
class User
{
//Predefine Here
public $id;
public $username;
public $password;
public $email;
public $hash;
public function profileLink()
{
return sprintf('%s',$this->id,$this->username);
}
}
//Fetch the results
$result = $sth->fetchAll(PDO::FETCH_CLASS, "User");
$userObjects = array();
foreach($result as $user)
{
$userObjects[] = $user;
}
//Now you can use like so:
echo $userObjects[2]->profileLink();
so my other answer here : PDO PHP Fetch Class
I think that if you are going to implement your own User class, then it should look something similar to the following:
class User {
private $UserID;
private $Username;
private $AvatarImg;
// ... First Name, Last Name, ALL other user information that you store in the DB.
function __construct( $uid ) {
// Populate all private members from the DB for the given user id.
}
function update( $assocArrayOfValues ) {
// Commit these values to the Db and Update the private members.
}
// All Associated get functions ( getName, getUID, getUsername etc )
// Any other specialty functions you may want, e.g...
function getAvatar() {
return "<img src = '" . $this->AvatarImg . "'/>";
}
}
What you are trying to archive is the functionally of an ORM (Object-Relational-Mapper). It may be beneficial to use one and not do it yourself.
If you want to do it on your own, I would go for lazy-loading. This is a bit in between your two ideas. In PHP it looks something like this:
class User
{
private $id; // depends on your application, could also be a string
private $dirty;
private $loaded;
private $properties;
public function __construct($user_id)
{
$this->id = $user_id;
}
public function __destruct()
{
if ($this->dirty) {
// commit to DB
}
}
public function __get($name)
{
if (!$loaded)
{
$this->loadFromDb();
}
// error-handling if the key does not exist is missing here!
return $this->properties[$name];
}
public function __set($name, $value)
{
// May be required to load the data here...
// error-handling if the key does not exist is missing here!
$properties[$name] = $value;
$this->dirty = true;
}
private function loadFromDb()
{
// query data from db and store it in properties
}
}
The advantage of this design is, that if you construct objects, which ultimately you don't need, nothing has touched the database yet. Also note the commit done during deconstruction.
If you load collections sometimes it may be useful to have a function load a bunch of rows from the DB and pass the rows as argument to a constructor when creating the objects. This would require only one query instead of possibly hundreds if you would have constructed each object by itself.
As a further enhancement you may provide a User::reset() function, which throws away all the changes made.
I would suggest you to use a PHP-Framework like Yii.
http://www.yiiframework.com/
It has nice Features to interact between Classes and your Database.
You can also get some inspiration there if you really want to do this on your own.

How do you manage database connections in php?

So recently I've really started to use php actively, and I need some insights on different ways to use database connections.
At first I just used the simple mysql_connect():
<?php
$connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_DB, $connection);
?>
After a while I created a database class which I started to include and initialize in every file - something like this:
<?php
class MySQL_DB {
var $connection;
function MySQL_DB(){
$this->connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_DB, $this->connection);
}
function query($q){
$res = mysql_query($q, $this->connection) or die(mysql_error());
return $res;
}
}
$database = New MySQL_DB;
?>
And this is what I'm using at the time - and it's working fine - but there are always ways to improve.
So my question to you is how do you manage your database connections?
Do you use classes?
What does your classes contain (just
the connection or even functions?)
What practices do you recommend?
I recommend to use PDO. Don't reinvent the weel. It's a nice OO-interface to many database engines.
Additionally I create a small function which just inititializes PDO object. So all connection settings can be changed in one place.
Your current approach is pretty standard, and works well. I used it for a long time. It's true that modules like PDO provide base functionality like this now, which is very nice as well and can get you away from problems with home-brew code.
However, I've taken the connection management one step further. If you get into a complex application, you might get into a situation where you have multiple databases, or heavy database use. Including a single database connection file and having a global $database variable becomes unwieldy for multiple databases, and it's unnecessary for application requests that might not need a database connection. Remember, connecting to the database is expensive.
What I've done is create a singleton DatabaseManager class that handles the database object for me, and makes sure multiple connections to a given DB don't get instantiated. Instead of initializing a new database object at the top of your app, you simply call on the DatabaseManager every time you need the object.
$db = DatabaseManager::getDatabase();
Here's an example class that I had whipped up for a CodeIgniter project. You can see in the getDatabase() function it simply loads CodeIgniter's default database object, which you would substitute for your own class (and run the connection routine for it) if you weren't using CI. This is a pretty simplistic management class, and could be extended to manage multiple connections to different databases fairly easily.
<?php
/**
* Implements the Singleton pattern to prevent multiple instantiations and connections
* to the application database.
*
*/
class Database_manager
{
private static $instance;
public $db;
/**
* Constructor function is declared private to prevent instantiation.
*
*/
protected function __construct()
{
parent::__construct();
}
/**
* Returns an instance of a Database_manager.
*
* #return object Database_manager object
*/
public static function getInstance()
{
if (self::$instance == null) {
$className = __CLASS__;
self::$instance = new $className();
}
return self::$instance;
}
public static function getDatabase()
{
$instance = self::getInstance();
if ($instance->db == null) {
//utilize CodeIgniter's database loader
$instance->db = $instance->load->database('',true);
if (! is_object($instance->db)) throw new Exception("Could not load database.");
}
return $instance->db;
}
}
Perhaps the most common advantage I get out of using this style of connection management is when I have to take down an application for database maintenance. By not instantiating a database connection until I need it, I can easily put up a "maintenance in progress" message on a site (short circuiting normal MVC dispatching), and not worry about requests to the application opening a DB connection while maintenance is in progress.
Usage of classes are the way to go to increase customized re-usability.
Bring in all generic implementations into the class. You are on the right track.
This website has the following clean approach.
This website link is no longer present. Archive Link.
class connection {
// Possible Modules are as follows:
// DBX_MYSQL, DBX_ODBC, DBX_PGSQL, DBX_MSSQL, DBX_FBSQL, DBX_SYBASECT, DBX_OCI8, DBX_SQLITE
private $module = DBX_MYSQL;
private $host = "localhost";
private $database = "test";
private $username = "testuser";
private $password = "testpass";
private $link;
private $result;
public $sql;
function __construct($database=""){
if (!empty($database)){ $this->database = $database; }
$this->link = dbx_connect($this->module,$this->host,$this->database,$this->username,$this->password);
return $this->link; // returns false if connection could not be made.
}
function query($sql){
if (!empty($sql)){
$this->sql = $sql;
$this->result = dbx_query($this->link,$sql,DBX_RESULT_UNBUFFERED);
return $this->result;
}else{
return false;
}
}
function fetch($result=""){
if (empty($result)){ $result = $this->result; }
return dbx_fetch_row($result);
}
function __destruct(){
dbx_close($this->link);
}
}
In your database manager example, you did not define a parent for your class.
Therefore, invoking parent::__constructor() yields an exception,
and also, you cannot use the load property of code ignitor.
Which class did you use as an extension for your DatabaseManager?
Since i do not know where you placed your databasemanager code, nor which class you used as its parent, i circumvented the exceptions by making the getDatabase() method receive an input parameter which i called $loader.
Normally, this $loader object will be the model class requiring access to a database.
public static function getDatabase($loader)
{
$instance = self::getInstance();
if ($instance->db == null) {
//utilize CodeIgniter's database loader
$instance->db = $loader->load->database('default',true);
if (! is_object($instance->db)) throw new Exception("Could not load database.");
}
return $instance->db;
}
Best regards.

Categories