Recently I started looking more seriously into classes and OOP in general in PHP. I'm trying to create a simple site while taking advantage of classes as much as possible but there have been some questions that have been stuck in my mind.
More specifically I'd like to know how would a 'proper' site structure look like with classes and methods that deal with users, pages, menus, etc. Currently I'm using this wrapper to get around MySQLi more effectively and I can't seem to decide how should I implement this wrapper with other objects - do I create a new class for users, menus, etc. separately and just pass the database variable through the class every time I create an instance?
$db = new Mysqlidb (DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
$user = new User ($db);
Or do I just extend the SQL class as "models" like the wrapper's author has pointed out here.
Also in general, what should remain a class, what should I handle with only functions? How should I handle things with my MySQL class?
Is it a good practice to handle every single menu item/user/page as an object?
These are just some of the things confusing my mind right now. There are quite a few examples on the web about OOP but I still haven't found a decent one to explain the questions I asked above.
if you already familar with mysqlidb, its 2.1 and 2.2 releases are coming with a new dbObject class to implement models with some extra features.
Check out their https://github.com/avbdr/PHP-MySQLi-Database-Class/blob/master/dbObject.md
If you still want to stick with a pure MysqliDb classes you can try to do:
class Model {
protected $db;
public function __constuct () {
$this->db = MysqliDb::getInstance();
}
public function __call ($method, $arg) {
call_user_func_array (array ($this->db, $method), $arg);
return $this;
}
}
class user extends Model {
$this->tbl = 'users';
public function create ($data) {
$this->db->insert (...);
}
public function admins () {
return $db->where ("role", "admin")->get($this->tbl);
}
}
This will give you models like:
$user = new user ();
$q = $user->where('login','root')->admins();
Take a look at dbObject as its pretty simple and I bet it will do a job you need it to do.
As for OOP I would avoid storage of the mostly static content in the database.
Just split menus/sidebars/header/etc into separate subviews and you should be fine.
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 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 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);
I've just started using OOP PHP and ran into a question. I've set up a generic mysql class that allows me to connect to a database and has some functions to obtain records from a table:
class mysql{
//some lines to connect, followed by:
public function get_record($sql)
{
$result = mysql_result(mysql_query($sql));
return $result;
//obiously it's a bit more advanced, but you get the picture.
}
}
Next, I have a class to obtain user details:
class user{
__construct($id)
{
$this->id = $id
}
public function get_username($id)
{
$username = get_record("SELECT name FROM users WHERE id = '".$this->id."'");
return $username;
}
}
I tried this, but got the error that the function get_record was unkown. I solved this by adding $mysql = new mysql(); to the user class.
However, it feels quite inefficient to have to instantiate the mysql object for every class that uses my database methods (that's pretty much all of them).
Is there a way to make the mysql class and its methods accessible to all other classes, without having to call the mysql class in every method?
For one, you don't need to use singleton in this case - or actually, you almost never do. See this article, for example.
Second, I think your OO designs are a bit off. The main point of object-oriented programming and design is to isolate responsibility into separate classes. Right now, you're giving your User class two main responsibilities - store / carry one user's relevant data, and query the data service (in this case, a simple MySQL / database abstraction layer).
You should first move that functionality into a separate object. Usually, this is called a Service - so in this case, it's a UserService. A UserService has one responsibility: provide access to User objects. So it'd sorta look like this:
class UserService {
public function __construct($mysql); // uses the mysql object to access the db.
public function get($id) {
$result = $this->mysql->get_record("select x from y");
$user = new User($result['id'], $result['name']); // assuming user has a constructor that takes an id and a name
return $user;
}
public function save($user);
public function delete($user);
}
You tie it all together at the start of your request (or where you need to access users):
$mysql = new MySQL($credentials);
$service = new UserService($mysql);
$user = $service->find(1337);
It's not perfect, but it's a much neater design. Your MySQL object does what it needs to do (build a connection, execute queries), your user object is plain dumb, and your service does only one thing, i.e. provide a layer between the actual storage layer and the thing calling it.
Design your mysql class to be called statically:
$username = Mysql::get_record("SELECT name FROM users WHERE id = '".$this->id."'");
http://php.net/manual/en/language.oop5.static.php
This is a common problem, and so there is a common solution to this.
As you might know, in software development common solutions on common problems are called Design Patterns.
There are two design patterns that can help you solve this problem.
In a more abstract sense the problem you are facing is:
How can i make class A available in class B?
The Singleton pattern
"In the singleton pattern a class can distribute one instance of itself to other classes."
This is not exactly what you are looking for, as your website may use multiple database connections. However, it is used by a lot of people in this way.
Read some information about using a singleton class as a database provider here:
https://www.ibm.com/developerworks/library/os-php-designptrns/#N10124
More information on the singleton pattern in PHP:
http://www.fluffycat.com/PHP-Design-Patterns/Singleton/
Another sensible approach is the registry pattern:
Registry Pattern
You can find information about the registry pattern on the link below, as well as an implementation almost identical that you are looking for:
http://www.sitecrafting.com/blog/php-patterns-part/
Even more powerful is a combination between the singleton and the registry.
Good luck and enjoy learning OOP PHP!
You should pass in the mysql object to each user object. So it would look like this:
$mysql = new mysql();
$user = new user( $mysql, $id);
$name = $user->get_username();
class user {
public function __construct($mysql, $id) {
$this->mysql = $mysql;
$this->id = $id;
}
public function get_username() {
$username = $this->mysql->get_record("SELECT name FROM users WHERE id = '".$this->id."'");
return $username;
}
}
using global variables, although that is probably not the best option.
$mysql = new mysql();
function someFunction() {
global $mysql;
$mysql->get_record(...)
}
or a static method for your mysql class (see Singleton)
class mysql {
public static $theInstance = new mysql();
public static function getInstance() {
return $this->theInstance;
}
}
function someFunction() {
$database= mysql::getInstance();
$database->get_record(...)
}
Start to think to use Doctrine, it's better
http://www.doctrine-project.org/
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...