How to structure classes in PHP - php

I have been working on moving over to OOP in PHP. I have reading explanations on php.net, but I was hoping I could get some specific answers here.
I tried to create the following example to illustrate my question. Say I have "Database", "Products", and "Users" classes, and I want to display products if a user has access.
So I call the "Products" class "showProducts()" function, which in turn creates an instance of the "User" class, which creates an instance of the "Database" object and checks the users access level.
If the user has access, then the "showProducts()" function creates another instance of the "Database" object, and queries the database.
class Database{
public function query(){
//runs query here
}
public function __construct() {
//sets up connection here
}
}
class User{
public function checkAccess(){
$db = new Database();
$db->query( //pass in query to check access )
//does stuff, then returns true or false
}
}
class Products{
public function showProducts(){
$user = new User();
if($user->checkAccess())
$db = new Database();
$db->query( //pass in query to get products )
}
}
I was hoping someone could illustrate how to do this the proper way.
I would like to have some sort of controller class, that creates one "Database" object, that is available to all of the classes that need to access it, without having to create multiple instances of the "Database" object. I would like the same thing with the users class, so there is one $users object that all the classes can access, without having to create a new object every time I need to use something in the "User" class.
I apologize if my question is not clear, and thanks in advance for any responses!!
Thanks to everybody for the replies!

When moving form procedural to Object Oriented programming you should grasp more then just how to build classes. OOP is not writing classes, its about following best practices, principles and patterns in OOP.
You should not instantiate new objects inside another, you should give the User object, his Database object that User depends on, through constructor, or setter method. That is called Dependency Injection. The goal is to give objects to a class that needs them through constructor or setter method. And they should be instanciated from outside of that class, so its easier to configure class. And when building a class you want its easy to see what dependencies that class have. You can read about Inversion of Control principle here: IoC
So then your code would look like this:
<?php
// User object that depends on Database object, and expects it in constructor.
class User
{
protected $database;
public function __construct($database)
{
$this->database = $database;
}
// -- SNIP --
}
?>
Now to use that user class you do this:
<?php
$database = new Database($connParams);
$user = new User($database);
?>
You can also use Dependency Injection using setter methods to set dependencies, but Il let you google that for yourself :)
Thats it, joust read about Inversion of Controll principle, and about Dependency Injection and Dependency Injection Containers, these are the best ways to manage classes.
I have seen lots of PHP code that is "OOP" and in fact they are only using Classes as functionality namespaces :) So joust learn about OOP principles and patterns.
Have fun! :)

Don't instantiate objects inside your constructors or other methods. Pass them as parameter, preferably inside a different class known as factory. This will make it easy to test your code, but also make it easy to create the objects.
Also, don't try to use singletons. This is the object oriented version of "global variables", and you do not want to use global variables. It makes testing of your code really hard, nearly impossible.
Watch this video http://www.youtube.com/watch?v=-FRm3VPhseI to understand why it is bad to use singletons. Especially the CreditCard example at 19:00 is worth watching.
If you really want to do it state-of-the-art, have a look at the concept of "dependency injection". Essentially, passing stuff that is needed from outside into a class is the whole secret, but there are frameworks that do this for you automatically, so you do not have to write a factory yourself anymore. These are called "Dependency Injection Container" or "DIC".

To make one object for all your code use Singleton pattern:
class Database{
private $db_descriptor;
private function __construct(){
/* connect and other stuff */
}
public static function getInstance(){
static $instance;
if($instance === null){
$instance = new self();
}
return $instance;
}
}
And you can use the same technique with users, i say more with php 5.4 you can use 1 trait for singleton pattern.
One last tip: when you work with database and other heavy things use technique called lazy initialization. When you improve your OOP skills look at Doctrine Project they use that techniques a lot!

Related

Reuse Database Connection When Creating PHP Objects

In PHP, I have two classes: Database and Item.
Database contains the connection properties and methods. For example, Database::Query can be used to pass a query string, etc.
Item is a generic item identifier. It's built by passing it an itemID which is then used to query the database for the rest of the item information.
In this case, what's the best practice for creating Item objects if they require database access? Is it normal to create each one using this syntax:
$item = new Item(12345, $db);
Or is it better, acceptible, or possible to create the Database object and have it used for each Item created in the application, such that the call could become:
$item = new Item(12345);
The second seems a lot cleaner (and can be expanded so that similar types of objects don't also need that $db addon), but I'm looking for suggestions from those who have more experience at this than I do! Thanks!
I would suggest that most seasoned developers would lean toward the approach of dependency injection as demonstrated in your first example.
Why?
Well largely because this allows you to decouple the class to which the dependency is being injected from the dependency's implementation.
So consider this dependency injection example:
Class some_class {
protected $db;
__construct($db) {
if($db instanceof some_db_class === false) {
throw new Exception('Improper parameter passed.');
}
$this->db = $db;
}
}
Here you could pass any type of object so long as it was an instance of some_db_class it could be a subclass of that object that implements the same methods used by this class. That doesn't matter to this class as long as the methods are implemented (you of course could also check that a passed object implements a specific interface in addition to or in lieu of checking its instance type).
This means that, for example, you can pass a mock DB object for testing or something like that. The class doesn't care as long as the methods are implemented.
Now consider the singleton approach (or similar instantiation of DB from with the class):
Class some_class {
protected $db;
__construct() {
$this->db = some_db_class::get_instance();
}
}
Here you have tightly coupled your class to a specific database class. If you wanted to test this class with a mock DB implementation it becomes very painful in that you need to modify the class to do so.
I won't even get into discussion of using global as that is just poor practice and should not be considered at all.
I would recommend using the Singleton Pattern for your database connection. This is actually the best practice. As you really dont need to instances of your database connection.
class Database_Instance
{
private static $database;
public static function getDatabaseObject() {
if (!self::$db) {
self::$db = new PDO( );
}
return self::$db;
}
}
function callWhatSoEver()
{
$connection = Database_Instance::getDatabaseObject();
}
For more information about the singleton pattern, see: http://en.wikipedia.org/wiki/Singleton_pattern
Typically a database connection object is global, or accessible globally. That works well for the vast majority of applications.
I do something like this (simplified for example purposes):
$db = connect_to_db();
function GetDB()
{
global $db;
return $db
}
//inside the item object
function Load( $id)
{
$db = GetDB();
$db->query(..);
}
There are, of course, cases where this isn't the best route. As always, it depend on the specific needs of your application.

Should a PHP user class extend a database class?

I am not sure if this is totally the wrong thing to do, so I am looking for a bit of advice.
I have set up a database class with the constructor establishing a PDO connection to a MySQL database.
I've been looking at singletons and global variables, but there always seems to be someone who recommends against either/or.
I'm experimenting with a user class which extends the database class, so I can call upon the PDO functions/methods but maintain separate user class code. Is this a stupid thing to do?
You should generally pass a connection into your user, so your user class would take a database type object into its constructor and then use that database object to execute queries against the database. That way your data access logic remains separate from your business logic. This is called composition, as opposed to what you're talking about, which is inhertance.
If you really wanted to be technical, it would be best to have a user object with nothing but public variables, and then you would use a 'service' to implement your business logic.
class UserService implements IUserService
{
private $_db;
function __construct(IDb $db) {
$this->_db = db;
}
function GetAllUsers() {
$users = Array();
$result = $this->_db->Query("select * from user")
foreach($result as $user) {
//Would resolve this into your user domain object here
users[] = $user;
}
return users;
}
}
Well, ask yourself if User is a special case of Database. I'm not sure how others perceive it, but I would be kind of offended. I think what you need is to read about the Liskov substitution principle.
As for solving your "people tell me that globals are bad" issue, here are two videos you should watch:
The Clean Code Talks - Don't Look For Things!
The Clean Code Talks - Global State and Singletons
The idea behind class extensions in OOP is for child classes to be related to the parent classes. For instance, a school might have a Person class with extension classes of Faculty and Students. Both of the child classes are people, so it makes sense for them to extend the Person class. But a User is not a type of Database, so some people might get upset if you make it an extension.
Personally, I would send the database object as an argument to the User class in the constructor and simply assign that object to a class property. For instance:
class User
{
protected $db;
function __construct($username, $password, $db)
{
//some code...
$this->db = $db;
}
}
Alternatively, though some might yell at you for it, you can use the global keyword to inherit a variable in the global scope for use within your methods. The downside is that you would then have to declare it global in every method that needs it, or you could do:
class User
{
protected $db;
function __construct($username, $password)
{
global $db;
//some code...
$this->db = $db;
}
}
But in answer to your question, no I don't think you should make User an extension of Database; even though it would do what you need, it isn't a proper OOP practice.
It is pretty simple according to the definition of an object. It is the encapsulation of data and the operation which is performed on that data so if we only consider the theoretical point of view it would leads us in pleasurable environment.
My suggestion would be to create an abstract data access class with the generalized basic crud operations and a simple query execution using either PDO, ADO or some other database abstraction library. Now use this class as a parent for most of your model classes like the User.
Now the basic CRUD is provided by the abstract data access class and you can write the behavior specific to the user object like getting all posts for the user by consuming the simple query interface of the abstract parent class.
This approach will bring more modularity in term of coupling functionality and more readability and reuse-ability.
I don't see anything wrong with it for specific cases. You could use it for something as simple as wrapping a user's DB credentials in an object so they don't have to specify them everywhere the DB object is used.
$db = new UserDB();
would be a bit nicer than
$db = new StandarDB($username, $password, $default_db);

Understanding PHP Inheritance

I understand the basic principles of inheritance in OOP, but I have a specific thing I am trying to do and want advice on how best to do it.
Lets say I have a core class:
class Core {
....
}
and I also have 2 or more other classes that extend this functionality
class MyClass1 extends Core {
....
}
class MyClass2 extends Core {
....
}
and I also have a database class in which I perform my queries, I want to pass an instantiated object of the database class (possibly by reference) to each one of my classes. One of the reasons for this would be to store a list or count of the queries that page as executed.
How should / can I go about this?
You could pass your instance of your database object to a constructor for your classes :
class Core
protected $db;
public function __construct(Your_Db_Class $database) {
$this->db = $database;
}
}
And, then, from your methods, work with $this->db, to access your database.
Of course, when instanciating your classes, you'll have to specify the database object :
// somewhere, instanciate your DB class
$db = new Your_Db_Class();
// And, then, when instanciating your objects :
$obj = new MyClass1($db);
Another way would be to use the Singleton design pattern, so there can be only one instance of your database class.
Probably a bit easier to setup ; but less easy to unit-test, after.
You could pass the database object as a parameter to the __construct function of your class, and then in said function assign the db object to member of the class, for instance $this->database_handler.
Another possibility is to work with a global variable that is your database object, but global variables are evil for many reasons, so let's disregard that.
Another note: By default, all objects are passed by reference, so you don't need to worry about that.

Is this a good use of Registry?

Main goal is to make core classes (instantiated with params) available from any place in application - in controllers, mappers, models, helpers etc.
For example, we have mapper which depends on Database object:
class Foo_Mapper
{
private $database;
public function __construct(Database $database)
{
$this->database = $database;
}
public function getFoo(array $criteria)
{
// ...
}
}
Variant 1: Basic dependency injection. The problem is that every time when I need to create mapper, I also need to instantiate a database object (with params).
$database = new Database($params);
$foo_mapper = new Foo_Mapper($database);
Variant 2: Registry. Core objects are instantiated and put into registry so every other object can easily access them.
// Somewhere in bootstrap...
$registry = Registry::getInstance();
$registry->database = new Database($params));
// Usage
$registry = Registry::getInstance();
$foo_mapper = new Foo_Mapper($registry->database);
Is there a better way to do what I want? Any drawbacks?
Variant 1: Basic dependency injection. The problem is that every time when I need to
create mapper, I also need to instantiate a database object (with params).
or passing it along. If you use a Dependency Injection Container, you would even have to do that manually: you simply add that you need to retrieve a Database, and a Database will be created (or reused) for you. Ask the Container to create a controller, and make sure you list your dependencies in the constructor. There are a few decent Dependency Injection containers for PHP, to wit:
Bucket https://github.com/troelskn/bucket
Symfony Dependency Injection http://components.symfony-project.org/dependency-injection/
Phemto http://phemto.sourceforge.net/
Sphoof\Container http://code.google.com/p/sphoof/source/browse/lib/container.php?repo=v2
For full disclosure: I wrote the last one.
Variant 2: Registry. Core objects are instantiated and put into registry so every other
object can easily access them.
You could make the registry non-static, but if you're going to rely on a Registry object in your application, you might as well leave it static. This is a perfectly viable solution, with one obvious drawback: you don't know what objects are used by what objects by looking at the API. You'll have to dig into the code.
You could make this a Singleton. Like this:
class Database
{
private static $instance = null;
public static getInstance()
{
if (self::$instance == null) self::$instance = new Database();
return self::$instance;
}
// ... METHODS ... //
// ... METHODS ... //
// ..... //
}
Then you can use
new Foo_Mapper(Database::getInstance());
It looks like you did this with your registry. Then you don't really need your registry anymore. Though if your classes are coded by someone else you would still have to use something like a registry or make a helper class/function for every of those classes that do not use the singleton pattern.
I think the way you illustrated it seems ok to me. It would be bad if you call your registry from within Foo_Mapper, because that class should probably not know about the existence of the registry, but this way looks ok.

Using my database class with other classes in my project

I have a custom database class that I wrote myself, and I also have a user class and a site class.
The MySQL class has methods like this:
connect
query
clean
fetch
The user class:
register
login
logout
resetPass
The site class:
updateTopics
addTopic
addPost
addReply
etc.
These classes need to interface with a database, which is what I wrote the MySQL class for. But, I have no idea how to properly use the MySQL class with these classes. Do I define the class as global and just reference it in the other classes? Do I do something like:
$db = new MySQL();
$user = new User($db);
and then reference it like that?
Any help is appreciated, thank you. :)
In addition to Daniel Vandersluis's answer:
Instantiating the object within your class creates a strong dependency between those classes. You might instead be interested in dependency injection and inversion of control (+ ioc containers).
see:
http://en.wikipedia.org/wiki/Dependency_injection
http://martinfowler.com/articles/injection.html
btw: Do you really need your own MySQL class implementation? There are already so many database access and abstraction layers available. E.g. http://docs.php.net/pdo.
you might be interested in stantiating the MySql class just one time. it prevents the connection to be opened and closed many times during execution. i like to use the Factory concept. it's a class that handle the instantiation of objects and you can write it to allow only one instance, following the Singleton concept.
someting like this:
class Factory {
private static $objects = array();
static function get_database() {
if( ! isset(self::$objects['database']))
self::$objects['database'] = new MySql();
return self::$objects['database'];
}
}
you would use like that:
$db = Factory::get_database();
note that it always return the same instance of MySql instead of creating new ones.
well, but it's just a very simple implementation of a Factory, just for understanding. it could be a lot better =]
You could instantiate your MySQL class within your other classes, like so:
class User
{
private $db;
function __construct(...)
{
$this->db = new MySQL();
}
function accesses_database(...)
{
$this->db->query(...);
}
}
And then reference $this->db inside your class when you want to access the database.
Also, if you want there to only be one instantiation of MySQL, you can make it a singleton.

Categories