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);
Related
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.
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!
I know there are loads of questions on this, I have done quite a bit of reading. I'd like to ask this in context of my project to see what suggestions you may have.
I have quite a large web application with many classes, e.g. users and articles (which i consider to be the main classes) and smaller classes such as images and comments. Now on a page, lets say for example an article, it could contain many instances of images and comments. Makes sense right? Now on say an articles page I call a static method which returns an array of article objects.
That's the background, so here are the questions.
Since building a large amount of the app I came to realise it would be very useful to have a core system class containing settings and shared functions. There for I extended all of my classes with a new core class. Seemed relatively simple and quick to implement. I know CodeIgniter does something similar. I feel now though my app is becoming a bit messy.
Question Is this a good idea? Creating an instance of core is exactly what I want when calling an instance of an article, but what about when i'm creating multiple instances using the static method, or calling multiple images or comments on a page. I'm calling the core class unnecessarily right? Really it only needs to be called once per page (for example the constructor defines various settings from the database, I don't want to this every time, only once per page obviously), but all instances of all classes should have access to that core class. Sounds exactly like I want the singleton approach, but I know that's a waste of time in PHP.
Here's an idea of what my code looks like at this point. I've tried to keep it as simple as I can.
class core {
public function __construct(){
...define some settings which are retrieve from the database
}
public function usefulFunction(){
}
}
class user extends core {
public function __construct(){
parent::__construct();
}
public function getUser($user_id){
$db = new database();
$user = /* Get user in assoc array from db */
$this->__setAll($user);
}
public static function getUsers(){
$db = new database();
$users = /* Get users from database in assoc array from db */
foreach($users as $user) {
$arrUsers[] = new self();
$arrUsers[]->__setAll($user);
}
return $arrUsers;
}
private function __setAll($attributes) {
foreach($attributes as $key => $value)
{
$this->__set($key, $value);
}
}
public function __set($key, $value) {
$this->$key = $value;
}
}
The other issue I'm having is efficiently using/sharing a database connection. Currently each method in a class requiring a database connection creates a new instance of the database, so on a page I might be doing this 5 or 10 times. Something like the dependency injection principle sounds much better.
Question Now if i'm passing the instance of the DB into the new user class, i know I need something like this...
class user{
protected $db;
public function __construct($db){
$this->db = $db;
}
... etc
}
$db = new database();
$user = new user($db);
... but when I want to run the static function users::getUsers() what is the best way to gain access to the database instance? Do i need to pass it as a variable in each static method? (there are many static methods in many classes). It doesn't seem like the best way of doing it but maybe there isn't another way.
Question If extending all of my classes off the core class as suggested in part 1, can I create an instance of the DB there and access that some how?
Question I also have various files containing functions (not oop) which are like helper files. What's the best way for these to access the database? Again i've been creating a new instance in each function. I don't really want to pass the db as a parameter to each one. Should I use globals, turn these helper files into classes and use dependency injection or something different all together?
I know there is lots of advice out there, but most info and tutorials on PHP are out of date and don't ever seem to cover something this complex...if you can call it complex?
Any suggestions on how to best layout my class structure. I know this seems like a lot, but surely this is something most developers face everyday. If you need any more info just let me know and thanks for reading!
You asked in a comment that I should elaborate why it is a bad idea. I'd like to highlight the following to answer that:
Ask yourself if you really need it.
Do design decisions for a need, not just because you can do it. In your case ask yourself if you need a core class. As you already have been asked this in comments you wrote that you actually do not really need it so the answer is clear: It is bad to do so because it is not needed and for not needing something it introduces a lot of side-effects.
Because of these side-effects you don't want to do that. So from zero to hero, let's do the following evolution:
You have two parts of code / functionality. The one part that does change, and the other part that is some basic functionality (framework, library) that does not change. You now need to bring them both together. Let's simplify this even and reduce the frame to a single function:
function usefulFunction($with, $four, $useful, $parameters)
{
...
}
And let's reduce the second part of your application - the part that changes - to the single User class:
class User extends DatabaseObject
{
...
}
I already introduced one small but important change here: The User class does not extend from Core any longer but from DatabaseObject because if I read your code right it's functionality is to represents a row from a database table, probably namely the user table.
I made this change already because there is a very important rule. Whenver you name something in your code, for example a class, use a speaking, a good name. A name is to name something. The name Core says absolutely nothing other that you think it's important or general or basic or deep-inside, or that it's molten iron. No clue. So even if you are naming for design, choose a good name. I thought, DatabaseObject and that was only a very quick decision not knowing your code even, so I'm pretty sure you know the real name of that class and it's also your duty do give it the real name. It deserves one, be generous.
But let's leave this detail aside, as it's only a detail and not that much connected to your general problem you'd like to solve. Let's say the bad name is a symptom and not the cause. We play Dr. House now and catalog the symptoms but just to find the cause.
Symptoms found so far:
Superfluous code (writing a class even it's not needed)
Bad naming
May we diagnose: Disorientation? :)
So to escape from that, always do what is needed and choose simple tools to write your code. For example, the easiest way to provide the common functions (your framework) is as easy as making use of the include command:
include 'my-framework.php';
usefuleFunction('this', 'time', 'really', 'useful');
This very simple tow-line script demonstrates: One part in your application takes care of providing needed functions (also called loading), and the other part(s) are using those (that is just program code as we know it from day one, right?).
How does this map/scale to some more object oriented example where maybe the User object extends? Exactly the same:
include 'my-framework.php';
$user = $services->store->findUserByID($_GET['id']);
The difference here is just that inside my-framework.php more is loaded, so that the commonly changing parts can make use of the things that don't change. Which could be for example providing a global variable that represents a Service Locator (here $services) or providing auto-loading.
The more simple you will keep this, the better you will progress and then finally you will be faced with real decisions to be made. And with those decisions you will more directly see what makes a difference.
If you want some more discussion / guidance for the "database class" please consider to take a read of the very good chapter about the different ways how to handle these in the book Patterns of Enterprise Application Architecture which somewhat is a long title, but it has a chapter that very good discusses the topic and allows you to choose a fitting pattern on how to access your database quite easily. If you keep things easy from the beginning, you not only progress faster but you are also much easier able to change them later.
However if you start with some complex system with extending from base-classes (that might even do multiple things at once), things are not that easily change-able from the beginning which will make you stick to such a decision much longer as you want to then.
You can start with an abstract class that handles all of your Database queries, and then constructs them into objects. It'll be easy to set yourself up with parameterized queries this way, and it will standardize how you interact with your database. It'll also make adding new object models a piece of cake.
http://php.net/manual/en/language.oop5.abstract.php
abstract class DB
{
abstract protected function table();
abstract protected function fields();
abstract protected function keys();
public function find()
{
//maybe write yourself a parameterized method that all objects will use...
global $db; //this would be the database connection that you set up elsewhere.
//query, and then pack up as an object
}
public function save()
{
}
public function destroy()
{
}
}
class User extends DB
{
protected function table()
{
//table name
}
protected function fields()
{
//table fields here
}
protected function keys()
{
//table key(s) here
}
//reusable pattern for parameterized queries
public static function get_user( $id )
{
$factory = new User;
$params = array( '=' => array( 'id' => $id ) );
$query = $factory->find( $params );
//return the object
}
}
You'll want to do your database connection from a common configuration file, and just leave it as a global variable for this pattern.
Obviously this is just scratching the surface, but hopefully it gives you some ideas.
Summarize all answers:
Do not use single "God" class for core.
It's better to use list of classes that make their jobs. Create as many class as you need. Each class should be responsible for single job.
Do not use singletones, it's old technique, that is not flexible, use dependecy injection container (DIC) instead.
First, the the best thing to do would be to use Singleton Pattern to get database instance.
class Db{
protected $_db;
private function __construct() {
$this->_db = new Database();
}
public static function getInstance() {
if (!isset(self::$_db)) {
self::$_db = new self();
}
return self::$_db;
}
}
Now you can use it like db::getInstance(); anywhere.
Secondly, you are trying to invent bicycle called Active Record pattern, in function __setAll($attributes).
In third, why do you wrote this thing in class that extends Core?
public function __construct(){
parent::__construct();
}
Finally, class names should be capitalized.
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.
I have a CORE class that pertains only to my specific site, ie, it performs site specific functions. I have a database class (for mysql), and other classes like access, validator, upload, template etc etc... I know that php classes can only extend one class each, so almost all of my classes extend the database class. I was looking over a public twitter class used on the twitter API. In it, there are functions to do almost everything you could do by going directly to the website, insert, delete, whatever... Should I put all site relatie functions inside my Core class and keep it out of the general scope of my scripts. Right now I have something like this....
Heres an example, as of right now I have functions like
$core = new Core();
$core->get_user_info($user_id);
$core->get_user_articles($user_id);
Inside that function, i perform database queries to select the needed information so i dont have to do it directly since it can get messy.
I also have functions to delete things, like
$core->Delete_Article($article_id);
However, I dont have functions to insert. Instead I use the Database class directly to add information, like so.
$article = array(user_id => $_SESSION['user_id'], body => $_POST['body']);
$db = new Database();
$db->Insert($article, 'articles');
or
$user = array(name => $_POST['name'], email => $_POST['email']);
$db->Insert($user, 'users');
Now, in the topic of separation of one aspect from another, should I put ALL of my database select/insert/update/delete queries inside my general CORE class and do ALL the database actions in the background
Like instead of $db->Insert(), i could use $core->insert_user() or just continue as I'm doing.
This is a pretty common mistake for people new to object-oriented programming. You don't want to extend a class just because it has some functions that you need. In fact, you may want to avoid extending classes at all while you're getting started. Although most intros to OOP make a big deal out of inheritance, I would steer clear for the moment.
Instead, think of how you can group together functions in terms of the way they're used. For example, say you're managing users. You need to keep track of user information, add users, delete them, etc. You could create classes like this:
class User {
function getName()...
function getID()...
}
class UserAdmin {
function addUser(User $user)...
function getUser($id)...
function deleteUser($id)...
}
These classes are organized according to concepts, not according to what functions you need to call.
When you do need reusable functions for things like database access, you'll generally want another separate object doing the work. So instead of having your UserAdmin class extend a Database class to format its SQL:
// wrong
class UserAdmin extends Database {
function getUser($id) {
$this->openConnection();
$this->runQuery("select * from users where id = {1}", $id);
}
}
... you can just use the Database class from within your UserAdmin class:
// right
class UserAdmin {
function getUser($id) {
$db = new Database();
$db->openConnection();
$db->runQuery("select * from users where id = {1}", $id);
}
}
class Database {
function openConnection() ...
function runQuery() ...
}
Initially it will seem like more work, but it keeps your various classes independent. That makes them easier to write, maintain, and test.
Because PHP is reloading everything on each page view, I do not see much advantage to instanciating classes for everything. If you break the functionality up into files that are roughly coorspond to your database schema, you can scale up and up without adding more and more functions that are loaded on each page hit.
It matters when you have dozens or hundreds of tables / classes.
Specifically for PHP, we prefer this style:
class Member
{
public static function Insert($aData)
{
//Insert member and return ID
}
public static function Select($Member_ID)
{
//select member and return Array
}
public static function List($aFilter)
{
//Return list of members filtered by specific criteria
}
}
To take it one step further, we have a static class App which holds relevant "singletonish" variables.
class App
{
public static $DB = NULL;
}
App::$DB = new Connection();
Now, anywhere in your app, you can say:
App::$DB->Query(...);
Generally, what I do is add a simple query() method to my database class which just takes SQL is an argument. Then I abstract all my general CRUD methods to the specific class. so if you have an Article class, the the deleteArticle() method would go in that class, and would extend the Article class with the database class. use $db->query($sql) within that class. and so on with your other classes...