I started making a website, and quickly i found out that my code is a mess. It's been a while since I've been programming in PHP, and since then I learned OOP. Now while making an application in C# or java is pretty easy from this point of view, PHP is giving me trouble.
I used to program everything (in php) just from one line to another, with minimum amount of methods and no classes at all. So how much should be in methods, and where should this classes be?
Example:
I have account.php, and i want to update user information. So after checking that someone has sent some data if(isset($_POST[.. what next? I used to just make
all the checks like $email=CheckForRisksOrSomething($_POST["email]); and then just update mysql.
This brings me to the question, should I create a class User and what methods should it contain? Also WHERE should this class be saved, assuming that user.php would show you user's profile.
Back to how much should be in classes, should i just use in a file like:
$smth = new Someclass();
if($smth->checkIfSaved()){
$user = new User();
$user->updateUser(/* all the $_POST stuff here? */);
} else {
$smth->showUserDetailsForm();
}
Also where should Someclass be saved?
So if ayone would give me an example of how to structure the following functionalities (in files, classes and possibly methods).
users (registration, login, editing account..)
picture with comments of it
news (also with comments)
administration
This is just an example of course, but i don't want to keep on with my mess and then look at it three days later and just facepalm and wonder what did i write there. Well, i already did that today, that's why I'm asking.
EDIT 24.2.2016
While this is an old question, as suggested look into a framework. While it might take a bit to set it up it increases development speed, code is nice and clean and a lot safer. I personally use Laravel.
There's more than one way to skin this cat, but I'll recommend some helpful links and books for you.
Zend's Coding Standards: If you're looking at how to structure, name, etc. your files, then I would look at how Zend suggests to do these things. By following their guidelines, you can create a package that is compatible with somebody else's code using these same methods, as well.
What you will want to do is create a folder specifically for your classes. How do you know when you'll need to make a new class, and what to include? Good question!
If you find yourself running into groups of information that is related, needs to be handled together a lot, or solves a particular problem, chances are you should create a new class that can handle it.
For example, a User class to handle any sort of changes you want to make to a user of your site. Another example is a Role class that can perform tasks (or not) depending on if they're an admin or not. The wonderful thing about Objects and Classes is you can create a User::$role (variable named $role in the User class) that is a Role class. So for instance, you will have a Role object in your User object. From here, your user object can now call to the role object by doing something like:
class User {
private $username;
private $role;
function __construct($username){
$this->username = $username;
}
public function setRole($roleType){
switch($roleType){
case "admin":
$this->role = new Admin(); // contained in another class file
break;
case "staff":
$this->role = new Staff(); // contained in another class file
break;
default:
$this->role = new Visitor(); // contained in another class file
} // end case
} // end setRole
} // end Class User
$loggedInUser = new User("Bubba");
$loggedInUser->setRole("admin");
$loggedInUser->role->deleteMessage();
In general, you will want to keep your code structured and separate, so that each class only handles information that it should have, and not do anything more than it should. If you find a class doing too many things, this means you found a good time to create another class to handle this new responsibility. How you tie it all together is generally a problem answered with "design patterns". There is a very good book that covers both programming using objects and classes, as well as using design patterns.
Check out the book "PHP 5 Objects, Patterns, and Practice" by Matt Zandstra, and published by Apress. It's a wonderful book that dips your toes into OOP with PHP!
It is very hard to tell you how you should do that. There are many different preferences out there. Look at frameworks like Zend, Kohana, CodeIgniter, and so forth.
When I create smaller applications with OOP design, I usually try to follow the following hierarchy:
In the index.php include a bootstrap.php.
In the bootstrap.php include all classes and the config.
Make a classes directory where you can save core functionallity in a core folder.
Furthermore, in your classes directory create the two folders controllers and models.
In my projects I usually have another folder templates, where all my html files go in (and afterwards get rendered with the Smarty Template Engine).
This is a very simplified approach, but can lead you in the right direction. For your requirements like users, pictures, etc. create a model that contains all the data of one single user.
class UserModel() {
public $name;
public $email;
}
And then a controller that can modify this model:
class UserController() {
public function update($user) {
...
}
}
My answer might not be directly answering your questions but might do you lot of good.
Go with a real framework. Don't build websites with code from scratch. It will save you huge amount of time and will force you to use good practices of code separation, really good and clean project structure but again, it will save you time! For many things you decide to implement there there will be a ready solution and the common thing you do (as validate email address) would be done the right way.
I would go with a MVC PHP framework and after having used a lot CakePHP, Zend, Kohana and few others in the past, I would recommend you to go with Yii. Very small learning curve, nice docs, nice big active community and you will be able to port whatever you already have, to it in very small time.
I'm pretty sure for the project you've described that framework will cut your time at least 2 times and in the same time you will have all the things you ask above already solved. I know this from experience, having developed projects from scratch quite some time ago.
if you are developing for web, there are high chances that you will be developing a MVC application, simplest MVC framework known to me is CodeIgniter. And I will advice you to use it.
Related
I was starting a project today and after designing the database structure and how the data would be stored etc, I started the implementation. I am doing this on php, but the language isn't really relevant here, since my doubts are more architectured related or I guess, since I'm struggling more than I thought by implenting stuff in OOP on PHP. (Recently jumped on php, I've been coding in c++ and java before).
So, I started by creating my "User" class, simple as that, few attributes, and __construct, insert, update and delete methods. Those last 3, queries to the db.
Then this doubt came to my head, and I probably know the answer myself but I just don't find out.
I can now create instances and create new Users: $user = new User("John", 34) but, what if I want to edit the user "Dave"? Or I want to show all users. That method, for example, getAllUsers() which would return all users where would be implemented? Because it doesn't really belong to the class User does it? If it did, then how I would instance that method if I don't have any User instance?
I guess, I would need a class Users, or UserCollection which would be a collection of all the users, with the methods ´getCertainUser(id)´ and ´getAllUsers()´ which would return certain User or All of them, now then I would have a User I would be able to edit, right?
That being said, my questions is, how this problem should be addressed as the way to go, Am I complicating things too much? How this should be solved 'the correct way' in OOP. The times I've handled similar problems I've never used a database, so having a collection of users was the only way to store them, but having the database which stores the users feels redundant to have that collection of users.
Thanks in advance.
First, you are doing the right thing, by challenging yourself.
Obviously, there are many ways of doing things.
I highly believe that trying to keep concerns separated as much as possible and keeping classes small and simple are always two good guidelines when you want to write code that is easy to maintain and to test.
This would be one way of doing it :
To handle Models & Structures
Entity/User (Define the properties of a user)
Collection/User (implements ArrayIterator, just a structure)
To handle communication with your repository (db).
Repository/Mysql/User (implements getAllUsers, saveUser, deleteUser, etc.)
Those classes should implements common interfaces or inherit common abstract classes (if they share common logic).
For the basic persistency operation (update, delete, create), I have a little preference of moving them in the repository class instead of the entity. I prefer to avoid using "smart" entity objects. In my mind, it makes more sense. But, there are plenty of people who would disagree (and there is really no right or wrong here).
I have a Data Model structure similar to yours, where classes represent their table counterparts. In the case of retrieving multiple of a "User" or "Categories", etc, I have a static method inside the class, that returns instances of the class. In example:
class User{
public static function fetchUsersForBusiness(Business $business){
//fetch code here into variable $users from database...
$userObjs = [];
foreach($users as $userData){
$userObjs[] = new User($userData);
}
return $userObjs;
}
}
class Business{
}
The following code would return all the users that fit a certain criteria (in this case, a business they're associated with). I then return them as the objects themselves.
I've found this model to be fairly successful, and have used it in a multitude of languages including Java, PHP, and Swift. Hope it helps you.
Background
This is a long and complicated question. I'm using php/MySQL as an example (since it's an actual example) but this could theoretically apply to other languages. Bear with me.
MVC Framework with no ORM
I'm creating an application that uses its own framework. For a variety of reasons, the following answers to this question will not be accepted:
Why don't you just use X framework?
Why don't you just use X ORM?
This application does its own queries (written by me) and that's how I'd like it to stay for now.
Business Logic?
"Business Logic" seems to be a meaningless buzzword, but I take it to essentially mean
The queries and the logic that builds the result set based on those queries
I've also read that the Model in an MVC should do all the business logic.
User.php is 884 lines
Now that I've gotten my app working fairly well, I'd like to refactor it so as not to have such abominations. User.php is essentially the model for Users (obviously). There are some responsibilities I see in it that I could easily pluck out, but a major hurdle I'm running into is:
How can I reconcile SOLID with MVC?
The reason that User.php has grown so large is because I do any query that requires a User member in that file. User is used for a ton of operations (it needs to do so much more than just CRUD), so any query that needs userid, username, etc. is run by a function in this file. Apparently the queries should be in the model (and not the controller), but I feel that this should definitely be split up somehow. I need to accomplish the following:
Create an API that covers all of these necessary queries in a compartmentalized way
Avoid giving access to the DB connection class when it's not necessary
Add User data to the view (User.php is doing that right now -- the view object is injected by a setter, which I think is also bad).
...so what I could do is create other objects like UserBranchManager, UserSiteManager, UserTagManager, etc. and each of those could have the relevant queries and the DB object injected to run those queries, but then how do they get the coveted User::$userid that they need to run these queries? Not only that, but how could I pass Branch::$branchid? Shouldn't those members be private? Adding a getter for them also makes that pointless.
I'm also not sure where to draw the line of how much an object should do. A lot of the operations similar but still different. A class for each one would be huge overkill.
Possible Answer
If I can't get any help, what I'll do (or at least try to do) is have a dependency injection container of some kind build dependencies for the objects above (e.g. UserBranchManager) and inject them into the relevant controller. These would have a DB and Query object. The Query object could be passed to low level models (like User) to bind parameters as needed, and the higher level models or whatever they are called would give the results back to the controller which would add the data to the template as needed as well. Some possible hurdles I see are creating proper contracts (e.g. the UserController should preferably depend on some abstraction of the user models) but some specifics are inevitably required, especially when it comes to the view.
Can anyone offer some wisdom in response to my rambling question?
Response to #tereško
He has provided a great answer not only here, but also at How should a model be structured in MVC?
Code
As requested, here is some extremely pared down code (basically services one request). Some important notes:
Right now, controllers are not classes, just files
The controller also handles a lot of the routing
There are no "view" objects, just the templates
This will probably look really bad
These are also things to improve, but I'm mostly worried about the model (User in particular since it's getting out of control):
#usr.php -- controller
$route = route();
$user = '';
$branch = '<TRUNK>';
if (count($route) > 0) {
if (count($route) > 1) {
list($user, $branch) = $route;
}
else {
list($user) = $route;
}
}
$dec = new Decorator('user');
$dec->css('user');
if (isset($_SESSION['user']) && $_SESSION['user']->is($user)) {
$usr = $_SESSION['user'];
}
else {
$usr = new User(new DB, $user);
}
$usr->setUpTemplate($dec, $branch);
return $dec->execute();
# User.php -- model
class User {
private $userid;
private $username;
private $db;
public function __construct(DB $db, $username = null) {
$this->username = $username;
$this->db = $DB;
}
public function is($user) {
return strtolower($this->username) === strtolower($user);
}
public function setUpTemplate(Decorator $dec, $branch) {
$dec->_title = "$this->username $branch";
// This function runs a moderately complicated query
// joining the branch name and this user id/name
$dec->branch = $this->getBranchDisplay($branch);
}
}
Questions about answers
Answer here:
You talk about leaving off caching/authentication/authorization. Are these important? Why aren't they covered? How do they relate to the model/controller/router?
The Data Mapper example has the Person class with methods like getExemption, isFlaggedForAudit .. what are those? It seems like those calculations would require DB data, so how does it get them? Person Mapper leaves off select. Isn't that important?
What is "domain logic?"
Answer 5863870 (specifically the code example):
Shouldn't these factory objects be abstractions (and not rely on creation via new) or are these special?
How would your API include the necessary definition files?
I've read a lot about how it's best for dependencies to be injected in the constructor (if they're mandatory). I assume you set the factories in this way, but why not the objects/mappers/services themselves? What about abstractions?
Are you worried about code duplication (e.g. most models requiring an _object_factory member in their class definition)? If so, how could you avoid this?
You're using protected. Why?
If you can provide any specific code examples that would be best since it's easier for me to pick stuff up that way.
I understand the theory of what your answers are saying and it's helped a lot. What I'm still interested in (and not totally sure of) is making sure that dependencies of objects in this API are handled in the best way (the worst would be new everywhere).
Dont confuse SOLID (You can get a good explanation of what it is on my blog at: http://crazycoders.net/2012/03/confoo-2012-make-your-project-solid/
SOLID is great when considering the framework that goes around the application you are trying to build. The management of the data itself is another thing. You can't really apply the Single Responsibility of the S of SOLID to a business model that RELIES on other business models such as User, Groups and Permissions.
Thus, you have to let some of the SOLID go when you build an application. What SOLID is good for, is to make sure your framework behind your application is strong.
For example, if you build your own framework and business model, you will probably have a base class MODEL another for DATABASEACCESS, just remember that your MODEL shouldn't be aware of how to get the data, just know that it must get data.
For example:
Good:
- MyApp_Models_User extends MyApp_Framework_Model
- MyApp_Models_Group extends MyApp_Framework_Model
- MyApp_Models_Permission extends MyApp_Framework_Model
- MyApp_Framework_Model
- MyApp_Framework_Provider
- MyApp_Framework_MysqliProvider extends MyApp_Framework_Provider
In this good part, you create a model like this:
$user = new MyApp_Models_User(new MyApp_Framework_MysqliProvider(...));
$user->load(1234);
This way, you will prevent a fail in the single responsibility, your provider is used to load the data from one of the many providers that exist and your model represents the data that you extracted, it doesn't know how to read or write the data, thats the providers job...
Bad way:
- MyApp_Model_User
- MyApp_Model_Group
- MyApp_Model_Permission
define('MyDB', 'localhost');
define('MyUser', 'user');
define('MyPass', 'pass');
$user = new MyApp_Models_User(1234);
Using this bad method you first of all break the single responsibility, your model represents something and also manages the input/ouput of the data. Also, you create a dependency by stating that you need to define constants for the model to connect to the database and you completly abstract the database methods, if you need to change them and have 37 models, you'll have TONS of work to do...
Now, you can, if you want work the bad way... i still do it, i'm aware of it, but sometimes, when you have crappy structure and want to refactor, you can and should work against a principle just to refactor correctly and slowly, THEN, refactor a little more and end up with something SOLID and MVC looking.
Just remember that SOLID doesn't apply to everything, it's just a guideline, but it's very very good guideline.
Well .. it depends on what is actually inside your ./user.php file. If i had to guess, you would be a situation, where your user "model" has too many responsibilities. Basically, you are violating single responsibility principle and not sure how to go about fixing that.
You did no provide any code .. so , lets continue with guessing ...
It is possible that your user "model" is implementing active record pattern. This would be the main source of SRP problems. You could watch this part of lecture slides. It will explain some of it. The point would be, instead of using active record, to go with something similar to a data mapper pattern.
Also, you might notice that some of the domain logic, which works with User class instances, seems to happen outside your "model". It might be beneficial to separate that part in a different structure. Otherwise you will be forcing the domain logic inside the controller. Maybe this comment could shine some light on the whole subject.
Another thing you might have crammed inside your user "model" could be parts of the authorization (no to confuse with authentication) mechanism. It could be pragmatic to separate this responsibility.
Update
You talk about leaving off caching/authentication/authorization. Are these important? Why aren't they covered? How do they relate to the model/controller/router?
Caching is something that you would add later in the application. The domain objects do not care where the data comes from. For that reason you can wither add the caching with in the service-level objects or inside the existing data mappers. I would advise to choose former option, because changing existing mappers might have unforeseen side effects. And because it would just over-complicate the existing mappers.
namespace Application\Service;
class Community{
public function getUserDetails( $uid )
{
$user = $this->domainObjectFactory->build('User');
$cache = $this->cacheFactory->build('User');
$user->setId( $uid );
try
{
$cache->pull( $user );
}
cache( NotFoundException $e)
{
$mapper = $this->mapperFactory->build('User');
$mapper->pull( $user );
$cache->push( $user );
}
return $user->getDetails();
}
}
This would illustrate a very simplified acquisition of user information based on user's ID. The code creates domain object and provides it with ID, then this $user ovject is used as condition to search for cached details or, if it fails, fetching that pulling that information from DB via the data mapper. Also, if that is successful, the details are pushed into the cache, for next time.
You might notice, that this example did not handle situation, when mapper cannot find such user with such ID in storage (usually - SQL database). As I said , it's a simplified example.
Also, you might notice, that this sort of caching can be easily added on case-by-case basis and would not drastically change how your logic behaves.
Authorization is another part, which should not directly influence your business logic. I already linked my preferred way for providing authentication. The idea is that, instead of checking for credentials inside controller (like here, here, here or here), the access rights are checked before you execute a method on the controller. This way you have additional options for handling the denial of access, without being stuck within a specific controller.
The Data Mapper example has the Person class with methods like getExemption(), isFlaggedForAudit() .. what are those? It seems like those calculations would require DB data, so how does it get them? Person Mapper leaves off select. Isn't that important?
The Person class is a domain object. It would contain the part of domain logic, that is associated directly with that entity.
For those methods to be executed, the mapper should at first load the data. In PHP it would look something like this:
$person = new Person;
$mapper = new PersonMapper( $databaseConnection );
$person->setId( $id );
$mapper->fetch( $person );
if ( $person->isFlaggedForAudit() )
{
return $person->getTaxableEearnings();
}
The names of methods in the PersonMapper are there as an example, so that you would understand, how the class is supposed to be used. I usually name methods fetch(), store() and remove() (or push/pull/remove ... depends on how much GIT have I been using). IMHO, there is no point to have a separate update() and insert() methods. If object's data was initially retrieved by mapper, then it is an UPDATE. If not - it is an INSERT. You can also determine it whether the value, which corresponds to PRIMARY KEY has been set or not (in some cases, at least).
What is "domain logic?"
It is part of the code which knows how to create an invoice and apply discount price for specific products. It's also the code which makes sure, that you do not submit registration form, you do not state that you have been born in 1592.
The MVC is made from two layers: presentation (can contain: views, templates, controllers) and model layer (can contain: services, domain objects, mappers). The presentation layer deals with user interaction and responses. The model layer deals with business and validation rules. You could say that domain business logic is everything in model, that does not deal with storage.
I guess there is no easy way to explain.
Shouldn't these factory objects be abstractions (and not rely on creation via new) or are these special?
Which "factory objects", where? Are you talking about this fragment ?
$serviceFactory = new ServiceFactory(
new DataMapperFactory( $dbhProvider ),
new DomainObjectFactory
);
$serviceFactory->setDefaultNamespace('Application\\Service');
That whole code fragment is supposed to be in bootstrap.php file (or you might be using index.php or init.php for that). It's the entry point for the application. It is not part of any class, therefore you cannot have *tight coupling" there. There is nothing to "couple with".
How would your API include the necessary definition files?
That fragment is not entire bootstrap.php file. Above that code are includes and initialization for autoloader. I am currently using dynamic loader, which lets classes from same namespace to be located in different folders.
Also, such autoloader is a development-stage artifact. In production code you have to use loader, which works with predefined hashtable and does not need to actually walk the tree of namespaces and locations.
I've read a lot about how it's best for dependencies to be injected in the constructor (if they're mandatory). I assume you set the factories in this way, but why not the objects/mappers/services themselves? What about abstractions?
What are you talking about ?!?
Are you worried about code duplication (e.g. most models requiring an _object_factory member in their class definition)? If so, how could you avoid this?
Did you actually LOOK at how old that code fragment in comments was ?!?!?
You're using protected. Why?
Because, if values/methods are defined with protected visibility, you can access them when you extend the original class. Also, that code example was made for old version of answer. Check the dates.
And no. I will not provide any specific code examples. Because each situation is different. If you want to do copy-paste development, then use CakePHP or CodeIgniter.
I run an arcade site and over the past few years it's had many features added, it's got to the point where procedural programming just looks way too complicated and adding new features or making simple design modifications can be very tricky.
Therefore I've decided to try and recode the site from the ground up with the same features but in an OOP format.
The issue I have is picking the classes, I understand OOP and how it should work but always seem to have trouble getting started. I am unsure whether I should be trying to make functions for classes such as a user class with log in user function or if the user class should just be to add/update/show user details and the log in part would be better in a system class?
At the moment I've started with the following class and functions but do they fit in this category?
<?
class User {
var $userId,
$username,
$userRole,
$userEmail;
function isLoggedIn(){
}
function login($postusername, $postpassword)
{
}
function increaseLoginCount(){
}
function logout(){
}
}
?>
I could then have something like the following in a page.php .. (connect class not shown)
<?
$db = new Connect;
$db->connect();
$user = new User;
if(!$user->isLoggedIn())
{
echo "Please Log In.";
if($_POST['user'])
{
$user->login($_POST['username'], $_POST['password']);
}
}
else
{
if($_POST['logout'])
{
$user->logout();
exit;
}
echo $user->username." Logged In.<br />";
}
?>
But then the site would have pages to show game categories and I don't know where the displayGames() function would fit as it's not a single game so wouldn't go in the 'Game' class?
I've tried to find 'real world' examples but php code showing me how to make an elephant change colour or dance doesn't really help ...
Let's start with some textual analysis, highlights by me:
I run an arcade site and over the past few years
Think about how much you are able to cope with and what you are dealing with. Also understand that over the years you have gained specific knowledge about running arcade site. You have gained profession in your area. Never underestimate your own position and assets, it's the base you're operating from and you will introduce changes to. This includes your site's userbase.
it's had many features added, it's got to the point where procedural programming just looks way too complicated and adding new features or making simple design modifications can be very tricky.
If systems grow, they become more and more complicated. That's not specific to procedural programming only, it's a matter of fact. As you're running the site now for many years, you know how things changed, especially in the area how the user interfaces with your site.
Therefore I've decided to try and recode the site from the ground up with the same features but in an OOP format.
It's said that it could be possible to use OOP techniques to make re-useable software, there is (and can not be) any proof of this.
But there are only very few examples in commercial software development where re-writing the whole application from scratch was a success. Very few. The rules of commercial software development might not apply in your specific case, so just saying.
Think twice before you recode the site. Doing a lot of work only to achieve the same is somewhat fruitless and can be disappointing. Instead probably look more specifically which of your current design is introducing the biggest problem you would love to change.
It is possible with PHP to mix procedural and object-oriented style, which can be especially useful when you have legacy code (a common definition of legacy code is code w/o automated tests).
The issue I have is picking the classes,
I try to rephrase that: For what write classes for?
I understand OOP and how it should work but always seem to have trouble getting started.
The beginning is always the hardest step. You're in the position ready to make decisions now, but you can't look into the future. Reduce the risk by eliminating the most risky part. You've probably started to ask a question here to gain some feedback to base your decisions on, but that will probably not reduce the burden and might lead to confusion. However, getting educated is most often a good thing.
I am unsure whether I should be trying to make functions for classes such as a user class with log in user function or if the user class should just be to add/update/show user details and the log in part would be better in a system class?
That highly depends on the nature of your application and the nature of the user. Probably the most of your script only need to know if a user is concrete or anonymous (an anonymous user has not logged in), it's ID, name or nickname.
The application should provide that user to any consuming component, so each command/script does not need to deal with a) obtaining users information and handling users (like logging in), b) verifying if the component is valid for the user (access control). That should be placed somewhere else, e.g. in the application controllerPofEAA.
Each of your scripts/commands that has the application controller object, can ask for the user and just interact with the user.
However this is just technically speaking. Deal with the fact of yourself being unsure, work with that information. Try to better formulate your concrete problem, list pros and cons for a specific way of solving it, get away from concrete code again before starting to code. Then compare pros and cons. Try to make things more simple and less complicated.
Probably write down in simple words what should be happening instead of writing code.
At the moment I've started with the following class and functions but do they fit in this category**?**
Your code is quite bare, so it's hard to say much about it - especially as I don't know what your arcade site is (and what the category is you write about). It's still good for an example probably. What can be seen in your classes is that you tightly integrate everything with each other.
For example you start with the DB. That's common, because the DB is a central component for any application. The application needs the DB to operate on. However you want to keep things loosely coupled so that all your commands can be run with some other DB or a new user object that is connected with some even other DB than the rest of your application's data objects.
$application->getDB();
As the user is such a central subject in each application, it should have a very simple interface. All the glory details about authentication, retrieving of the users properties etc. should be delegated into another class/component, so that you can change the implementation where users are stored and how they authenticate:
/**
* #package command.modules.games
*/
function ListGamesCommand(Request $request, Response $response)
{
$application = $request->getApplication();
$user = $application->getSession()->getUser();
$games = $application->getModels()->build('games');
$games = $games->findByUser($user);
$response->setProp('games', $games);
}
As this example shows, you can add the functionality when you need it. E.g. as long as your application does not need to actually log in users, why care about how it's written now?
Create a factory that is producing the user for the application object - whatever it will need now or in the future (see the Two Piles of Objects in The Clean Code Talks — Inheritance, Polymorphism, & Testing). If you then need the authentication, either add it to the session object or the user object interface.
The authentication itself would be implemented in a class of it's own anyway, the Authenticator. So you can review your interfaces later on as well, by moving the invocation of authentication from session to user or whatever. Only a fraction of your commands will need to deal with these specific task and as all new code is under automatic tests as you want to rewrite and benefit from OOP, you have ensured that all the places are covered and properly re-factored.
Same is true for accessing request variables. If you want to make use of the benefits of OOP - which is highly connected with indirection (and each layer of indirection comes with a price) - you should first of all make your base classes operate on specific data and not on any data (like globals and superglobals, I've seen $_POST in your example code).
So enable your new code to operate on a request and deliver a response (Input - Processing - Output):
$request = new Request($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES, $_ENV);
$response = new Response;
Example taken from the BankAccount - Sample application used for PHPUnit training
Now everything below this can operate on a Request and a Response object - process input and turn it into output. The domain command (your scripts/commands that do the thing) do not need to care any longer about extracting input from the HTTP request like using $_POST or $_GET they can take it directly from the Request - or if you write a class of commands of it's own - this can be even more tailored. And some commands can operate on requests and responses of their own.
The next big topic is the user-interface. You write you want to:
I've decided to try and recode the site from the ground up with the same features but in an OOP format.
I already wrote that such a doing can be fruitless. To have a benefit of OOP code would mean that the next time you change your code, you're still able to re-use components. As software changes constantly, this time now is already the next time. So you want to already re-use existing code. I assume one part of your existing code is the output logic. So the existing output logic needs to interface with the exemplary Request and Response above.
I bet you love websites. You love to make them just work and look great. You've build your site over the years and even not everything is like you wish it to be, you don't want to drop it. So it's crucial for your re-write that you don't destroy everything but you can preserve it's working form from now to the future (See as well Preserve a Working Application; last point of the list).
In webapps the view is such a crucial part. If you loose the view, your site will loose it's identity. If you change too much of it, your site will loose users that are comfortable with using it today.
If you break it,
will you even notice?
can you fix it?
On the other hand you want your application code (the features, the functionality) to not be that tightly bound to it any longer to have a benefit in rewriting your code. As you want to rewrite your application, let's take a look:
.---------. .-------------.
| website | ---> [interface in ] ---> | application |
| user | <--- [interface out] <--- | |
`---------´ `-------------´
As this schema shows, to make your application more independent to whatever the interaction looks like (can be a website, a (smartphone) GUI or the ticketing system), the application code should be replace-able. You don't want to code the logic to obtain a users games for example for every type of user-interface in the new application code, but you did in the old application code.
Taking the User object as an example here. How it authenticates and where it is stored shouldn't be something your new application commands code are concerned about. It's just there if the command needs it. Not globally but specifically if the command asks for it.
Where-as the registration and lost password procedures are part of your existing application and continue to exist.
Now you need to bring the old and the new code together.
So you will probably start with an interface for HTTP requests and a HTTP response. The view kicks in with that Interface Out. You assign/pass all needed data for the view via that interface, your application does not know the view any longer. You don't deal with any CSS, Javascript or HTML code within your new application code. That's just the sugar on top for the output. Your application should interface as well via console/telnet in plain text or as a remote XMLRPC service, AJAX endpoint - whatever.
So you can probably just generalize your view code and inject variables to it. To write a view layer could be as simple as including a PHP file. It operates on variables that are available within it's scope. It can make use of "helper" functions (template macros) that are available in it's scope. It can make use of view model objects. It's even possible to write your own language for the view (templating language, a Domain Specific Language (DSL)).
But this is only possible if you create an interface that allows the application code to do so.
So what you now do is to move away the HTTP/HTML/CSS/JS from your application into an adapter of it's own. That adapter is able to formulate the generic command that can be passed to any application via interface in.
The application will only take care to execute the command and deliver it's response via interface out. So you have two domains now: Your application and the website.
You can start to create these two new domains and then offer an interface in and out for your legacy code and one for your new code.
You also have "two" applications next to each other. They are finally bound together (invisible in their own code) with your database which takes care that the data of your site is in order. And that's what the database is for. Separate the data from your code, so you can change your code over time.
Also if you want to re-code, draw a border between the existing code and the new code.
Good luck! And I hope reading this will show you some options for your specific case. Also take note that you don't turn your controllers into just another facade to the database. Probably you've got the best benefits (don't know your concrete biggest problem) by using a lightweight HTTP abstraction and a view layer only as it might be that your application is for websites only.
Because as in HTTP / PHP:
[Interface In] Plain Text HTTP request
[Application] Free to go
[Interface Out] Plain Text HTTP response
You normally need only some functionality to parse the input and build the output.
Additionally not using fat models has the benefit that you access your data quickly and sequentially, e.g. if you don't need to pass the output at once (buffered, one-block), you can make of the benefit to stream the output to the server.
You should decide which parts are important to refactor for your application, not OOP or not. Like procedural, OOP needs to be done well as well. If you today run into problems by writing procedural code, OOP code might not the answer to your problem. The need to write better procedural code might be it. Just saying, it's not easy to refactor an application and you should identify the actual problem first.
If you break it, will you even notice?
If you break it, can you fix it?
The crucial part is that you can notice and that you have everything at hand to do the fix.
Get your website under test, so you can say if changing code here or there is actually doing good. Be able to turn any change back if it comes to light it's not working (better).
That done you can easily decide about a new feature or not. As long as you don't need to introduce new features, there is no need to change anything in how you write features. And until there, you can't plan for the new features.
So better think twice before re-writing your application. As written, this can kill the project.
See as well: How to implement MVC style on my PHP/SQL/HTML/CSS code?SO Q&A
OOP is all about identifying areas of responsibility and constructing self-contained units of code intended to handle one, and only one, of those areas. A general rule of thumb is that each object in your system should embody an equivalent object or concept in the real world but that's not always true as you need to also worry about abstract things that are needed to make your system work (I mean abstract here in the sense that they don't represent an item of business logic, but are still needed to make the system work. I don't mean abstract classes, which is something else altogether).
For example, in your gaming site, you're probably going to have to deal with Games, Users, Moderators, Accounts, Reviews, Comments and so on. Each of these should be a class in its own right, and every instance of that class should represent a particular User, Game, Comment and so on.
But classes have areas of responsibility, and a stated above, a class should deal with its area of responsibility and nothing else. Rendering a page is not the responsibility of any of the object classes mentioned above. This is where the classes that don't represent the entities of your system come in. You'll probably need a class for a Page, a class for a Session, a class for database connections (though PHP has you covered there already with PDO and some of the other DB modules such as mysqli).
To render a page you'd use an instance of a page class. You'd pass it a reference to the logged in user object, references to any game objects you'd want it to display, and so on. Then you'd have it render the actual HTML. The Page class doesn't need to know anything about the inner workings of the objects you pass it, other than about the APIs that those objects expose (known in OOP circles as the object's protocol, in otherwords their public methods and properties). A (very basic) Page class might look like this:
class Page
{
private $user = NULL;
private $games = array ();
public function setUser (User $user)
{
$this -> user = $user;
}
public function getUser ()
{
return ($this -> user);
}
public function addGame (Game $game)
{
$this -> games [] = $game;
}
public function getGames ()
{
return ($this -> games);
}
public function generate ()
{
$user = $this -> getUser ();
$games = $this -> getGames ();
$pageFile = '/path/to/a/php/script/representing/the/page/markup.php';
require ($pageFile);
}
public function __construct (User $user, array $games)
{
$this -> setUser ($user);
foreach ($games as $game)
{
$this -> addGame ($game);
}
}
}
The actual markup.php script would probably look something like this:
<html>
<head>
<title>Games page for <?php echo ($this -> user -> getName ()); ?>
</head>
<body>
<p>Hello, <?php echo ($this -> user -> getName ()), here are your games.</p>
<?php if (count ($this -> games)) { ?>
<ul>
<?php foreach ($this -> games as $game) { ?>
<li><?php echo ($game -> getName ()); ?>: your best score is <?php echo ($game -> getHighScore ($this -> user)); ?></li>
<?php } ?>
</ul>
<?php } ?>
</body>
</html>
As you might have noticed, if you use this approach then your application's modules will tend to fall into one of three categories. Your business logic objects like User and Game, your display logic like the markup.php file, and the third group that serves as a form of glue logic and coordination like the Page class.
Whilst in this particular case it's specific to your site, if you were to generalize this approach further it would fall into a design pattern known as MVC, which stands for Model, View, Controller (well actually it's closer to a pattern called PAC for Presentation, Abstraction, Controller, but it's almost always called MVC in the PHP community for some reason, so we'll just say MVC for now). A pattern is a generalization of a class of problems that programmers run into on a regular enough basis that having a toolkit of pre-made solutions is handy.
In the case of your gaming application, User and Game are models, Page is a controller, and markup.php is a view. If you substitute a different markup.php script into this code you can use it to present the exact same data in a completely different way, say as an XML file for example. You could also use the same models with a different controller to get them to do different things. The important thing to keep in mind here is that models should not concern themselves with how they are being used, that way they can be used in different ways depending on what the controller needs to achieve.
As MVC is a pattern, there are already toolkits that exist to build MVC (though they aren't really MVC ;) ) applications in PHP. These are called frameworks. There are plenty to choose from out there, such as Symfony, CodeIgnitor, Zend Framework and so on. The most popular framework these days is Zend, though I'm not personally a fan of it. (I would say that the beta versions of Zend Framework 2 do look a lot better than the current version of the framework though).
I hope this has been helpful for you. I know OOP can be daunting at first. It does require you to change your way of thinking as a programmer, but don't worry, it will come with enough practice.
All the members in the user class look like they belong there. It's important to separate the gui code from other code, I'd put displayGames() in some sort of gui class.
GordonM's post is a good one to get you started. I would certainly recommend using an established framework to get you started - they do a lot of the heavy lifting for you and will help you get used to OOP within PHP. Personally, if you're using PHP5.3 I'd recommend Symfomy2 but that's purely a personal preference. What I would also suggest is you get hold of a copy of the "Gang of Four" book. It's pretty much essential reading and although it comes mainly from a non-request-driven-environment background many of the patterns are still relevant in PHP.
I'm developing several web sites in Kohana using its template system so that one code base is running several web sites using the same back end DB. I'm starting to see a lot of if statements in the views to say if this site do this, if that site do that. It starting to look very non-MVC or Object Oriented. Do other developers have any rules they follow when deciding to breakout view into separate partial views? I want to reuse as much of the code as possible but not swim in if statement in every view. Any reference would be great also.
If you are using Kohana, you should use modules for stuff you don't want to duplicate for every application. Then you can keep specifics in your application with extended classes or specific settings in config files.
http://kohanaframework.org/3.2/guide/kohana/modules
A lot of if statements are mostly an indication that you need to do refactoring. A large cascading if statement to allow for different sites to be loaded is bad practice in the sense that you make files tightly coupled causing to edit multiple files when you need to make a simple addition or change. Furthermore, it will eventually become ugly if every site needs to load different dependencies or settings or whatever in your if statement.
It's difficult to say what you need to change without seeing the code, but try looking at design patterns like the factory or abstract factory design patterns to create site objects.
A good book that deals with the subject of patterns and best practices with PHP is PHP 5: Objects, Patterns and Practice by Matt Zandstra: http://www.amazon.com/PHP-5-Objects-Patterns-Practice/dp/1590593804. A very good book.
I had a similar issue cropping up with this, to keep the views nice and neat I extended the view class into a theme class. I would give the factory method two (or more) views ie Theme::factory(array('site1/home','default/home'),$data)->bind(...); If a themed view existed it would use that, else just serve up the default. That way I, or someone else less competent could easily override to display structure and view behaviour.
The class looks like this
class Theme extends View {
public static function factory($pages = NULL, array $data = NULL){
if (is_string($pages)) {
$pages=array($pages);
}
if (!is_array($pages)) {
$pages=array(0=>null);
}
foreach ($pages as $page){
if ((Kohana::find_file('views', 'themes/'.$page)) !== FALSE){
return new View('themes/'.$page,$data);
}
}
throw new Kohana_View_Exception("None of the requested views ':file' could not be found.", array(
':file' => join($pages,"' or '"),
));
}
}
You really want ViewModels, only you don't know how to name them yet. Little birds have been tweeting that it'll be in Kohana 3.3 but unless you have a year or so to wait, I recommend trying either View-Model module by Zombor or moving away from Kohana's templating system whatsoever in favour of KOstache (it's Mustache for Kohana)
If for any reason you want to stick with your current codebase, I'd go with splitting the view into several smaller interchangable parts and loading them when necessary (echo View::Factory(($something == 'one' ? 'view_one' : 'view_two')) or a custom written helper would be a nice toy here)
I have been reading a lot about dependency injection recently, and in theory it has made a lot of sense. The idea of having easy to test, single responsibility classes just sounds smart. However, I'm struggling with how far to take it.
I'm working on a PHP web application right now that has a CMS component and is heavily database driven. Within the CMS, you can create pages, and the pages themselves are built using various widgets. The widgets can be straight HTML (from a WYSIWYG editor), or can be a little more complex, like a photo gallery. And this is the important part, the photo gallery widget depends on other db models, like the PhotoGallery and PhotoGalleryImages in order to function properly.
According to Miško Hevery, I should not be passing references to dependencies through the different layers of my application. Instead, each class should simply "ask for" whatever dependencies it requires. Using his example, this is how this looks:
$db = new Database()
$repo = new UserRepository($db);
$page = new LoginPage($repo);
While I can see this working fine for the service layers of my application, I really don't understand how this would work with my value objects/entities. It seems to me that this pattern requires me to instantiate all my models in the highest layer of my application. However, how I can I instantiate all my widgets at that level, when I need my page class to tell me what widgets I need to instantiate? And without knowing what widgets I'm creating, how can I know what widget dependencies need to be created and injected in?
In theory DI makes a lot of sense to me. However, actually implementing this pattern in my new web application is proving to be more difficult. Is there still something I'm missing with respect to DI and IoC? Thanks!
Update: Response to Tandu
Thanks a lot for the response Tandu. I think that DI may not actually be my problem here, because I think I have a very clear understand of what it is, whether it be constructor or setter injection, or whether it be done using a container or the poor man's way. What I do think is happening is that DI is challenging me to rethink how I'm currently programming. I think my OOP design is the problem. To illustrate this, here is how I would have normally programmed this problem:
class Page
{
public $id;
public $name;
public function widgets()
{
// Perform SQL query to select all widgets
// for this page from the database, and then
// return them as Widget objects.
}
}
interface Widget
{
public $id;
public $page_id;
public $type;
public function widgetize();
}
class PhotoGallery_Widget implements Widget
{
public $id;
public $page_id;
public $type;
public function widgetize()
{
$gallery = new Photogallery();
foreach($gallery->images())
{
// Create gallery HTML code
}
}
}
// Finally, to create the page, I would:
$page = new Page(1);
foreach($page->widgets() as $widget)
{
$widget->widgetize();
}
Clearly there are some issues here. The Page model depends on the Widget models. The PhotoGallery_Widget model depends on the PhotoGallery model, and even further the PhotoGallery model depends on the PhotoGalleryImages model. The thing is, developing this way has worked well for me. As I get deeper and deeper into the layers of my application, each layer takes on the responsibility of creating the objects it requires. Introducing DI throws a major wrench into my way of thinking. However, I want to learn how to do this properly. Just because this works for me right now, doesn't mean I should continue doing it this way.
You mention using factories. But don't factories actually break DI because they are instantiating objects?
You may also notice that my models have the responsibility of interacting with the database. I suspect that this is also a problem with my design. Should I be using data mapping of some sort to remove this responsibility from my models?
Given this more specific example of how I'm currently implementing my code, do you have any other recommendations or can you further illustrate how I should be doing it differently?
Without looking at specific implementations, it's hard to give specific advice, so instead I'll provide the general advice that I can (I'm not very good, actually). It sounds like you could use a "dependency injection container" (google it .. find one you like or roll your own for your purposes) that manages the large interlocking dependencies of classes.
One thing you should keep in mind is that your code should gently fall around the design, which will hold it up very strongly. You shouldn't have to work hard to get your code to follow the design you've created. If what you are trying to do isn't working according to your understanding of the design, it's probably time for a rewrite.
You also only use examples of constructor injection. I'm sure you are aware that it's possible to use other kinds of injection such as setter injection when appropriate.
As I said, I haven't seen your code, but the problem with your design is that it's not the Page that should know about what widgets it needs, it's the service. If you are tying specific widget implementations to a page, this violates dependency inversion (and makes dependency injection harder). Instead your code should be more along the lines of:
interface Widget {
function widgetize();
}
class ConcretePage {
private $widgets = array();
public function addWidget(Widget $widget) {
$this->widgets[] = $widget;
}
public function run() {
foreach ($this->widgets as $widget) {
$widget->widgetize();
}
}
}
The service will create a page and add the widgets it requires. The page shouldn't care about those widgets. You may also have to implement a bridge between the page and the widgets. The service can handle that too.
As the very article writer you mention states here, you should have code that is devoted to building your entire object graph (this is where all of your new operators go). Imagine how difficult it would be to test your Page that expects five specific widgets without the class definitions of those widgets! You need to depend on abstractions.
This might not be in the spirit of DI, but a simpler solution would be to have a WidgetFactory:
class Page {
private $wf;
private $widgets = array('whiz', 'bang');
public function __construct(WidgetFactory $wf) {
$this->wf = $wf;
}
public function widgetize() {
foreach ($this->widgets as $widget) {
$widget = $this->wf::build($widget);
}
}
}
The WidgetFactory interface can be separate from application to application and even in testing. This still gives you some level of abstraction for the widgets Page expects.
To me dependency injections is only useful because I can choose beetween the syntax $this->method(); or $obj->method(); to call the same method. This can be done by using the magic functions set, get and call.
Sorry for taking so long to respond, but I've had to put a lot of thought into this. Once again, this is not correct, it's purely my opinion and speculation. This is a response to the response in your question:
In a way, your page does need to know what sort of widgets it needs (it gets them from a specific DB query, apparently). However, it shouldn't actually care what widgets it gets. It's also not necessarily the case that a page has to be tied to the widgets (e.g. as a member, even though this contradicts my previous answer) at all.
In fact, I think your new code is mostly okay. You have a factory for the widgets even though it's tied to a specific page. The only problem I would note is the creation of new PhotoGallery in the PhotoGallery_Widget class. You're not depending on an abstraction there, but a concretion, and it's even worse to create that object in the method. You can create these required objects with another factory in the controller.