Related
I started learning oop about 6 months ago, although I stopped for a while because of studies.
The problem is that whenever I use oop in my project I usually try to just make every single thing a class... Whether intialization, displaying, looping and much more... to be precise, I haven't gotten the concept of when to use/create classes.
Another problem is that I tend not to know the major benefit of a classes over a functions . Currently, I just mix them up.
I watch a youtube video that talks about classes and client code. In that video they said that classes are more of like developer codes while client codes are codes we write which uses the developer code to make things easier. So he advise we break our code to client/developer code.
But I don't know how to break my code into client code and developer code.
Infact at a point I was creating classes for all my pages like index.php, about.php
<?php
class about{
public $title = 'about page';
public $page_color = 'red';
//functions and more codes
}
After writing the above code I know I am not doing something right. I have tried to search google and have read many oop books but each time they use the car class example which I can not apply to my coding or just wouldn't address the context were a class is or isn't necessary.
Note: I am comfortable building website using procedural codes but I need to learn oop incase I need it someday.
To answer your question: Yes you're using it incorrectly. However it's not a quick fix to get you using it correctly.
There isn't an answer I can give you that will mean you start writing perfect OOP code tomorrow.
You're on the right path, study and practice. Make mistakes, live with those mistakes and refactor them. You'll get sharper the more you do this.
I'm at 16 years experience and I still find new rules and exceptions in OOP. It's not an exact science - it's a method that can yield different results depending on the context.
Just look at all the comments you've had and you'll see no general perfect consensus. Everyone is iteratively improving each others implementation. You can use this approach in your code, keep it tidy and organised, swap bits out as you find better or more correct ways of implementing them.
Well I have not learned php. But I am a good Java developer. And my OOP concepts are good. You mentioned that you do not understand major advantages of classes over function. Both of them are totally different. A class is a blueprint of software.Where as a function represents behaviour of software. You write all the code that does the processing of data provided as input by user and generation of output in functions. Classes contain these functions. The major advantage of writing code in classes is that they can be written in one place and reused anywhere. And OOP concepts are too vast. Each and everything cannot be explained in posts. OOP is much more advantageous than procedural-programming. Consider you are working on a very big project. Some features in the software are common. In OOP you can write code in one place and use them wherever you want.Whereas in procedural-programming you have to rewrite the same code wherever you are using those features. So, your headache of writing code will be minimized in OOP. Also, if the common code works on one place it will obviously work wherever it is being used. This is how OOP evolved from procedural-programming.
OOP is the backbone of most programming languages so you will want to use it basically all the time when you have it fully understood.
Websites are a little trickier to give you good examples of so I'll try and give a generic outline and then a more web-based focus.
Classes should hold data that is related to each-over in a common sense name. For example a Car would obviously hold the Engine (another class), the colour, the name, the owner, etc. And within that the engine would hold it's own set of data that is relative to it (max speed, miles per gallon, etc.). This is the basis of holding your data together, next comes functions within classes.
Now while Car holds data relative to the car, Car also holds functions that the car would do, or functions that the car will use to interact with it's data. Getters(GetColour()) allow outside objects to get information about that specific car (as Car1 and Car2 could hold different colours). Setters are the opposite, to set object specific data. Then we have everything else. Car.start() which internally calls this.engine.start() which may set up some functions to start draining gas from the engine and allow the car to move.
Classes are all about having this easy to read, easy to understand, and easy to re-use. Once your Car class is complete you can re-use as many cars as you need and they are all nicely self-contained.
On to web
Firstly, I highly recommend you look into MVC architecture, which is where the bulk of web architecture is and makes OOP easier to understand for web. Basically your website is split into controllers (in charge of interracting with the DB and giving you back the page), models(Your database data, e.g a user) and your views (HTML with a little templating so your controllers can pass it dynamic data)
For example: You go to website/posts/Stanley , Your Router (another MVC thing) decides that this needs to be handled by the PostsController(a class). The posts controller knows that you want all posts by user Stanley, so it asks the Posts Model(a class)to retrieve all posts by Stanley, the controller then passes these to the view to fill out a template using your Stanley specific posts.
Going away from MVC a second,
With your example given, you will mostly use classes, I would assume, for data manipulation and DB access. For example if you stored blog posts in a database you may have a class Blog with data that matches your db rows (id, user_id, title, body) and functions to access that data to put in your HTML, but also to grab that from the database easily.
For example:
BlogPost::All() may return an array of every blog post newest to oldest.
BlogPost:By(user_id) may return an array of posts by a specific user.
BlogPost:Remove(id) may remove the blog post given it's id.
BlogPost:RatingAtLeast(starRating), get all blog posts with atleast a starRating rating.
You get the idea... This class would exist as you said above, to give you a client code way to access your database that is SPECIFIC to your use case and as BlogPost contains variables related to your BlogPost. So BlogPost::All() will return an array of BlogPost.
My problem is actually not the ajax loading itself, more the capability to load it without javascript. I mean, I cope easily when I code my whole project just based on ajax-availability OR just without the use of ajax.
//EDIT: Although Arend already had a more or less valid answer, at the same time 'there is no direct answer to this question'. However, I'd like to see some other approaches of developers for scenarios like mine though! Even just a few links can help!
Basically I just get frustrated, coding everything twice on the same page to make sure that both users without and with Javascript enabled have the same experience. It's annoying and I was always wondering how others solve this problem.
When I update for example two divs with dependency on the same variables, it gets messy. Here's an example:
non-js-version
require 'classobject.class.php';
$another_var = 'something';
$class = new classobject($_POST['variable']); // just an example to show that this is dynamic - I'm aware of injection!
$function = $class->returnsth(); // returns 1
if(isset($_POST)) {
echo '<div id="one">Module 1 says:'; $require 'module_one.php'; echo '</div>';
echo '<br /><br />';
echo '<div id="two">Module 2 says:'; $require 'module_two.php'; echo '</div>';
}
Now in module_two.php and module_two.php I have code that executes differently depending on the return variable of $function.
Like:
if($function >= 1 && another_var != 'something') {
// do stuff
}
else {
// do other stuff
}
Now as this works easily with a reload, when I want to load the two modules on keyUp/enter/submit or whatever, I have basically a few problems:
I have to send the $_POST variables manually to the modules to use them
I have to re-execute the class & it's methods and make a link (require_once) to them in each of the module-files.
As $another_var is not existent in the modules, I'd have to send this variable to each modules, too (with post for example) and then before it can be used, I'd have to 'change' it like $another_var = $_POST['another_var'];
I find this mildly annoying and I wonder how you guys do that. I hope my way of coding is not too silly, but I can't think of another way. It's probably hard to relate to my very basic example, but to bring a whole project with the code would be too much. To sum it up, I'm looking for a better way to code and clean this mess up - there must be a way! I thought about sessions, but for compatability I don't want to rely on them either (if someone doesn't allow cookies).
In case you can't relate to what I'm trying to accomplish with that way of having my code assembled, I'll explain a scenario I'm facing quite a lot (not important if you already understand my misery):
Basically I have my index.php page where everything gets executed, with the html body and css styling and so on. This page expects some variables, that get set from the page that requires the index (like $another_var in my example).
Now other variables can get set too (from a form for example). Depending on that different classes and methods load new variables (arrays) that get used in while-loops in my modules to echo everything out.
Hope that's not too abstract. Think of a booking system where some variables are set from the page you are coming from (the event you want to book) and then a few more things get set by the user (a timespan, some preferences,...). In the end it's supposed to show results from the database all the way to the end-result - you can say the user narrows the results from step to step.
There is no direct answer to your question, but there is some food for thought.
Seperation of concerns
You can think about if you can perhaps seperate your buisness logic and layout logic. Often the use of a template engine can help greatly with that. I've had positive experiences with for example Twig or Smarty (was some time ago, not sure how they measure up right now). It requires you to write your code in a (less linear) way, but more logical.
A typical example of an OOP like seperation of concerns might be something like this:
$this->setParam('Myparam','myvalue');
if ($this->isAjax())
{
$this->setTemplate('ajax.php');
$this->setLayout(false);
} else {
$this->setTemplate('normal.php');
$this->setLayout('Mylayout');
}
return $this->render();
It is an imaginative situation, which can be found in many MVC like applications and frameworks. The main idea is that you should have the possibility to seperate your layout from your data. I would suggest looking at some of the modern frameworks for inspiration (like symfony, codeigniter, zend framework).
Glossary / Often applied concepts in a decoupled PHP application
Here is a quick list of concepts that can be used.
Example mvc in php: http://www.phpro.org/tutorials/Model-View-Controller-MVC.html
Note: I don't really like the implementation. I much more prefer the existing frameworks. I do like the explanation in total of this tutorial. E.g. for me this link is for learning, not for implementing.
Silex
For a simple decoupled php micro-framework I would really recommend silex, by the makes of symfony2. It's easy to implement, and to learn, but contains mainy of the concepts described here; and uses all the php 5.3+ goodies such as namespacing and closures.
see: http://silex.sensiolabs.org/
Frontcontroller Pattern
Only have one, and one only point of entry for your code. I usually only have one, and one only point in your application. Usually a frontcontroller 'dispatches' the request to the rest of the application
http://en.wikipedia.org/wiki/Front_Controller_pattern
Routing
A routing system is often used in combination with the frontcontroller pattern. It basically describes which URL is connected to which module / controller. This allows you to change the way people access your app without changing the urls.
See: https://stackoverflow.com/questions/115629/simplest-php-routing-framework
Controller
A controller is the place where buisness logic is applied. Getting the data from the database, checking privileges, setting the template, setting the layout, etc. (although this is also moved outside the controller if it becomes too big of a seperate concern).
Model
The model basically is the layer in which use manage your database. This can be a simple class where you move all your mysql_* functions, or it can be a full-featured ORM. The main philosphy is that all the logic related to fetching and placing information in the database is seperated.
One step up: ORM
An often used method in applications are Object Relational Models, these 'map' SQL records to PHP objects. Doctrine and Propel are two of these well worked out libraries. I heavily rely on these systems in my development. In this sense, the doctrine or propel part will represent the model layer.
Doctrine: http://www.doctrine-project.org/
Propel: http://www.propelorm.org/
Other ORMS: Good PHP ORM Library?
PHP ORMs: Doctrine vs. Propel
View:
The view usually consists of a templating engine. Some use plain PHP as a template, others, such as symfony create a seperate scope in which variables are placed. There are many discussions and opinions about what is best, one is right here on stackoverflow:
Why should I use templating system in PHP?
PHP vs template engine
Ones I like:
- Twig: http://twig.sensiolabs.org/
- sfTemplate: http://components.symfony-project.org/templating/
- Smarty: http://components.symfony-project.org/templating/
Decoupling mechanisms:
Event based systems
Using events in your can help to seperate the code. For example if you want to send an email after a record has been saved, events are a good solution to do that; in general the model should not have to know about email. Thus events are a way to connect them: you can let your -email-send-class listen to certain records in order for them to send the right email. (Perhaps you'd rather want your e-mails send from your controller, this is probably a matter of taste).
Dependency injection
When using OOP code in PHP many relied on having singleton classes running around (configuration, etc). From an OOP point of view, this can be considered bad, because it's hard to test it, and it's not considered very elegant to have dependencies running around like that. Dependency Injection is a pattern that came form Java and is now used in the newer frameworks to get around this. It might be a bit difficult to wrap your head around, but you will see it coming back in several new frameworks.
Dependency injection in php: Dependency Injection in PHP 5.3
Frameworks:
A lot of these methods are difficult, or a lot of work to implement yourself. Many will reside to a framework for this. You may or may not need a framework. You may, or may not want to you a framework, it's your choice. But it's still useful to learn how the frameworks do it, and not try to reinvent the wheel yourself.
The no-framework php frameworks: https://stackoverflow.com/questions/694929/whats-your-no-framework-php-framework
Good habits: https://stackoverflow.com/questions/694246/how-is-php-done-the-right-way
Frameworks worth looking at (imho): CodeIgniter, Kahona, CakePHP, Symfony (1.4/2.0), Silex, Zend Franework, Yii. There are many many more, each with their dedicated fans and haters.
I wrote something like this with PHP. I already had abstracted the rendering of every page such that I define a $content variable and then require('layout.php'). The $content variable is just a big HTML string.
I wrote a PHP function to determine if request was AJAX or not.
The non-AJAX responses render the layout with $content in the middle, b/t header and footer layout content.
AJAX requests basically get this: json_encode(Array("content"=>$content)). And I use jQuery to get the HTML out of the JSON response and modify the DOM. Using json_encode() will handle escaping the string for javascript.
In the end, I effectively have AJAXified every page w/o over-engineering a complex solution.
Any browser that supports AJAX can also open a link in a new tab/window to simulate the non-AJAX request. (Or bookmark/share a link, too.)
I'm very new to PHP so far and have been trying to learn it. A big difficulty I face though is I just can't bend my head around to think about how is a PHP website structured with classes, objects, namespaces.
I'm not entirely new to OOP as I do have a little experience in Python and Java but PHP OOP just got me stumped. Many of the newbie PHP books I saw were on procedural PHP. I followed them made 1--2 small website but when I got to OOP, I'm just stuck and any tips on how you made the transition from procedural to OO PHP would be appreciated. In particular these are the questions on my mind at this moment
What are the type of classes one would usually creates? I thought of giving a class for each table in my database (User, Book) as well as maybe a form class, are there any other type of candidates that could be turned into classes too?
Any other way to reduce html code duplication other than the old usual require() and include()?
Any recommended ways to structure a typical PHP website? I currently only knows of having a folder for includes file. But I would like to know more.
Thanks.
You have questions, here are my answers!
The classes you make in PHP can be related to objects like User, Book as you would do in a persistent program. If you look at a framework like Code Igniter you can make a class as specific as constructing database queries to a class that uses an MVC architecture consisting of multiple classes to render your entire website.
To reduce code duplication, you can, for example, write a class to construct a table (or if you are really fancy a div table maker.). Then you can write methods like makeRow(), makeDivision(), etc... get really fancy and then you can write clean PHP code that can generate really large powerful pages.
EDIT:
If you were talking about reducing about the amount of include you'd have to do for classes then yes, Autoloading Classes on the PHP website is something you will want to look at!
Structure of your website can be based on the model you want to use. Right now it seems that MVC models are popular with frameworks, but it is up to you how your want your web app to be made. I'm sure you can take any architecture model and base your website around it.
With all that said, if you don't feel like start from absolute scratch on your project there are a plethora of PHP frameworks to choose from:
Comparison of Web application frameworks: PHP via Wikipedia
A very interesting question that brings us back to the age-old debate of procedural vs. OO programming. Why pick one or the other? The answer is..nobody has one. The whole purpose of designing software is to get something done. Does it matter how you get there? Well, it depends. If you get there very sloppily and a lot of updates are required, that's a big waste of time. Does OO programming prevent this? Absolutely not.
It seems like your real question is how to integrate OO into a website. This is really not something that you should do for the heck of it. What are you trying to achieve with this website? Does it contain many different application states with user interaction in a FSM or is it just a bunch of static pages. How much information do these pages share?
Let's tackle your specific questions first:
What type of classes does one usually create? Whatever type of classes they want! Before you type one character of code, you should sit down and write out a design for your application. No one can tell you how to do this: write up some documentation, pseudo-code (even in php if you like), draw up a UML diagram, etc. Figure out how your application can be compartmentalized. Do not make the mistake of dividing up object based on their logical separation in the real world (User, Book) unless it makes sense to. Why do you need a Book object? How does it interact with a user?
You could build a very simple class to display your standard webpage:
class anypage {
public function header() {
return '<head></head>';
}
public function footer() {
return '<br />Copyright © ' . date('Y');
}
public function render($body) {
return '<html>' . $this->header() . "<body>$body{$this->footer()}</body></html>";
}
}
Then on any page call:
$page = anypage;
echo $page->render("My Page Content");
Anyway, I'm talking more about general OO principles than just PHP, but this is a question that can't be answered. You design classes that your application needs to get the job done. A good example of using an object in PHP is PHPTAL, a template language. Your webpage may look like this:
$page = new PHPTAL('mytemplate.xhtml');
echo $page->execute();
The PHPTAL class takes care of building the html from your template file. That's an example of what an object might be used for.
Of course, PHPTAL is huge, and it's broken down into a lot of compartments. Taking a look at the source code, we see the classes Attr, Element, Node .. these are all pieces of an xml document and they have a class representing them.
An important part of OOP is having objects work together. Each object should serve a purpose and do what it is good at. I don't like objects that are models for nouns like "User" or "Book," unless they do something. PHPTAL does a great job of rendering a view for your page, but how do you know which page to render? You can use an object to handle that:
class controller {
public function __call($_, $_) { return $this->hello(); }
public function hello() {
session_start();
$view = new PHPTAL('hello.xhtml');
return $view->execute();
}
public function goodbye() {
session_destroy();
$_SESSION = array();
$view = new PHPTAL('goodbye.xhtml');
return $view->execute();
}
}
On you main page, you would have:
$c = new controller;
echo $c->$_REQUEST['action']();
If the 'action' is set by the request, the controller responds accordingly by calling that action. hello is used by default thanks to magical __call().
Similar to the other OO languages you are familiar with, you can even have events in PHP:
class controller {
private $models = array();
private $_listeners = array();
public function __construct() {
$model = new model;
$this->models[] = $model;
$this->_listeners[] = $model;
}
public function action($action = 'hello', $events = array()) {
$this->$action();
foreach ($events as $type => $data) {
foreach ($this->_listeners as $listener) {
$event = "fire_" . $type;
$listener->$event($data);
}
}
}
}
class model {
public function fire_hello($name) {
echo 'hello ' . $name;
}
}
As other answers have suggested, a good start is to take a look at a PHP framework. I recommend Kohana, since it is a good OO framework. I'm not necessarily suggesting you build a website from it, but take a look at the documentation and code to get a better understanding of OO development for PHP.
2 PHPTAL or another templating engine is an awesome way to reduce html duplication. Even my miniature anypage class above is an example. You don't necessarily have to have an html file and then use require() include() or virtual() to pass it into your code for reuse. Instead, you can have a wrapper that stores and builds common template html. I cannot stress enough how much I love PHPTAL for this purpose. XSLT is an alternative.
3 There is no set way to do this. Others are suggesting "Use a framework." I don't necessarily disagree. Using a framework helps out a lot in taking care of some of the annoying business of setting things up. It's not a magic problem-solving placebo, but it is nice for some things. If you are just trying to learn and there is no constraint on time, I say write your own framework. That will definitely teach you about OO programming in PHP. If time is a concern, use one of the 500,000 frameworks out there that others are suggesting. As for how to structure your website, I tend to have a _js folder for javascript and a _stylesheets folder for stylesheets. All of the php and xhtml template files I use are just placed in the folders they belong to logically. It's not rocket science, it's software engineering!
The MVC pattern is essentially the de facto pattern for web apps, regardless of language. Several frameworks utilize this pattern, including Zend Framework, CodeIgniter, and Kohana.
Like the others have said, __autoload() or spl_autoload_register() is the way to go when it comes to eliminating the need to follow includes/requires.
Remember that the currency of OOP is objects. You're not gaining much if you simply turn some back end data into OO models and calling it a day. I suggest you look at Matt Zandstra's book PHP 5: Objects, Patterns, and Practice as well as the Gang of Four's Design Patterns: Elements of Reusable Object-Oriented Software to really see how to use objects throughout a project.
You might find that working within a framework means that you're only creating some of the components yourself and that there are plenty of examples of best practice.
I moved from procedural stuff to Zend Framework which is a great framework and includes a full MVC model which helps to clearly define what your different objects should do and how they all fit together.
It's likely to be a bit of a learning curve but after a while it makes so much more sense than procedural stuff!
Use an object-oriented MVC framework like CodeIgniter (which is very easy), Yii (bit harder), or CakePHP or Symfony (much harder). You can see how the different objects link to each other, and the benefits from using them.
A good example of classes is the interaction between 'Form', 'Validation' and 'Schema'. You can instantiate a form by passing it a schema, and then use methods in 'Form' to generate HTML without writing it over and over again. When a user submits the form, you validate each field using an instantiation of the 'Validation' class, and then write it to the database using a 'Model'. Each table in your database has a 'Model' which defines how data is written to and retrieved from the database (CRUD).
You can avoid using lots of requires and includes using '__autoload()'.
It depends on what you want to accomplish. In a relatively complex web application you could follow a typical MVC approach. In that scenario you can create at least two classes, one for the model and one for the controller. And then have several templates (plain PHP files) whose content are filled/completed by the controller. You can create more classes (forms, utilities, code-generators,..) as needed, but be careful to keep your code compact and easy to mantain.
Many frameworks rely on the __autoload() magic method. Another alternative is to build your mechanism to handle all this stuff, probably using an AutoLoader class.
Use a framework. Seriously. Or at least take a framework as an example. I recommend CakePHP or CodeIgniter due to their fil structure simplicity.
I work in a web shop as a PHP programmer. Most of the time we use good coding practices but not much structure to the site as a whole.
I have now entered my phase of being bored with some of our practices and want to branch out and simplify and generate some things in a helpful way not just for me, but the hybrid-programmer web developers in the office.
One employee left us with a MVC site written in PHP, and I have had to maintain it a bit, and I get how it works but have my complaints, my main complaint is that it is tightly coupled with each piece dependent on another. I see the advantage of the seperation of concerns, but this would be confusing to anyone but me looking at the code.
So for example, if I need to add a new page to the site, I have to go add a view, and then add a model, then update the controller. The ad-hoc method of making a new page is way simpler than this and doesn't require a programmer.
My judgement was this was a much better method to build, rather then maintain, a website.
Still, it would be nice if I had some design patterns where I could reuse code effectively without it being dependent on a multiple places in the site.
So my question is, is there a design pattern for building and maintaining websites that is much more loosely-coupled? I'm not looking for slight variations on MVC, I need something quite different to look at, maybe some type of plugin approach.
EDIT:
Thanks for the answers so far! A different way of putting it is I want the code to be done better in my office. Do I A) Push for MVC or B) find/build an alternative not as confusing to the half-programmers. We already use classes for things like DB connectivity and Form helping. The point of this question was to explore B.
There's always a compromise between the code being confusing because it's highly deconstructionist, and the code being confusing because absolutely everything needed to do X is randomly scattered around a single file.
The problem with the latter is that exactly what is an "intuitive" way to split things up into monolithic modules differs between people. Highly decomposed and factored code is nearly always more difficult to wrap your head around, but once you do that, maintenance becomes both easy to do. I disagree that it would be confusing to anyone else but the author looking at it. Large-scope patterns like MVC are used because it becomes easier to spot them and work on projects structured around them over time.
Another advantage of using MVC is that you generally won't make the application more difficult to maintain for someone who comes after you if you don't stick to the layering. This is because now you have a predetermined place where to place any aspect of implementing a new feature.
As far as the tight coupling is considered, you can't really implement a feature without there being some connection between the layers. Loose coupling doesn't mean that the layers are ignorant of each other completely - it means that a layer should be unaware of how the other layers are implemented. E.g.: the controller layer doesn't care whether you're using a SQL database or just writing binary files to persist data at the data access layer, just that there is a data access layer that can get and store model objects for it. It also doesn't care about whether you use raw PHP or Smarty at the view layer, just that it should make some object available under some predetermined names for it. All the while the view layer doesn't even need to know there is a controller layer - only that it gets called with the data to display ready under the abovementioned names provided by /something/.
As frameworks templates go, I find the MVC pattern to be one of the most "loosely coupled" ways of building an application.
Think of the relationships like interfaces, or contracts between the parts of the application. The Model promises to make this data available to the View and the Controller. No one cares exactly how the Model does that. It can read and write from a typical DBMS, like MySQL, from flat files, from external data sources like ActiveResource, as long as it fulfills its end of the deal.
The Controller promises to make certain data available to the View, and relies on the Model to fulfill its promises. The view doesn't care how the Controller does it.
The View assumes that the Models and the Controllers will keep their promises, and can then be developed in a vacuum. The Model and Controller don't care if the view is generating XML, XHTML, JSON, YAML, plaintext, etc. They are holding up their end of the contracts.
And, of course, the View and the Controller need to agree that certain things exist. A View without some corresponding Controller activity might work fine, but could never be used. Even if the Controller doesn't do anything, as might be the case in static pages:
<?php
class StaticController extends ApplicationController
{
/**
* Displays our "about" page.
*/
public function about ()
{
$this->title = 'About Our Organization';
}
}
Then the associated View can just contain static text. (Yes, I have implemented things like this before. It's nice to hand a static View to someone else and say "Just write on this.")
If you look at the relationships between the M, V, and C as contracts or interfaces, MVC suddenly looks very "loosely coupled." Be wary of the lure of stand-alone PHP files. Once you start including and requiring a half-dozen .inc files, or mixing your application logic with your display (usually HTML) you may have coupled the individual pages more loosely, but in the process made a mess of the important aspects.
<?php
/**
* Display a user's profile
*/
require_once 'db.php';
$id = $db->real_escape_string($_GET['id']);
$user_res = $db->query("SELECT name,age FROM users WHERE id = $id;");
$user = $user_res->fetch_assoc();
include 'header.php';
?>
<h1><?php echo $user['name']; ?>'s Profile</h1>
<p><?php echo $user['name']; ?> is <?php echo $user['age']; ?> years old!</p>
<?php
include 'footer.php';
?>
Yeah, "profile.php" and "index.php" are completely unrelated, but at what cost?
Edit: In response to your edit: Push for MVC. You say you have "half-programmers," and I'm not sure which half (do you have front-end people who are good at HTML and CSS but not at server-side? writers with some programming experience?) but with an MVC framework, you can hand them just the views, and say "work on this part."
I have to say that I don't really see your problem with MVC, since your already using templates anyway. I kind of think of it as the pattern that evolves naturally when you try to add structure to an application.
When people first start developing PHP application, the code is usually one big mess. Presentation logic is mixed with business logic which is mixed with database logic. The next step that people usually take is to start using some kind of templating approach. Whether this involves a specialized template language such as smarty or just separating out the presentation markup into a separate file isn't really important.
After this most of us discovers that it's a good idea to use dedicated functions or classes for the database access logic. This really doesn't have to be any more advanced than creating specialized functions for each commonly executed query and placing all those functions in a common include file.
This all seems very natural to me, and I don't believe that it's very controversial. But, at this point you're basicly already using an MVC approach. Everything beyond this is just more or less sophisticated attempts to eliminate the need to rewrite commonly used code.
I understand that this might not be what to you wanted to hear, but I think you should re-evaluate MVC. There's a countless number of implementations, and if it's really the case that none of them suits your needs, then you could always write your own and more basic implementation.
Look at it this way: Since you're already using a template language you'll typically need to create first a regular PHP file, and then a templare file each time you create a new page. MVC doesn't have to be any more advanced than this, and in many cases it isn't. It might even be that all you really need to do is to investigate more sophisticated approaches for handeling data access and add it to your current system.
The fact that you have to create a new Model and Controller Action when you need a new page I don't think means that your M, V, and C layers are tightly coupled. This is just the separation of concerns and contributes to a decoupled system.
That said, it is quite possible to royally screw up the intent of MVC (and I've worked on an app like this) and make it make the components tightly coupled. For instance, a site might put the 'rendering engine' directly in the Controller layer. This would obviously add more coupling. Instead a good MVC will be designed so that the controller is only aware of the name of the view to use and then pass that name to the separate rendering engine.
Another example of bad design in an MVC is when the views have URLs hard-coded into them. This is the job of the Routing engine. The view should only be aware of the action that needs to be called and the parameter that action needs. The Routing engine will then provide the correct URL.
Zend framework is very loosely coupled and is very good. Check it out:
http://framework.zend.com
This article might be of use too:
http://blog.fedecarg.com/2009/02/22/zend-framework-the-cost-of-flexibility-is-complexity/
You can try code Igniter. Its very easy to learn and does not strictly adopt MVC whilst giving your code good structure.
Code Igniter and Kohana (a CI descendent) are OK, but also loosely MVC. I like the simple php framework. It doesn't get in your way and it provides the important stuff, without forcing a structure or complicated conventions on you.
Ah... good old MVC arguments.
I have to maintain a multi-faceted PHP application, pieces of which are written "MVC" style, but not all. Worse, different parts have different ways of doing MVC, all of which are homegrown. And some pages just do it all themselves.
The main problem is not that there is a diversity in framework code, but that the coders clearly did not understand how to abstract APIs. IMO, ths is the biggest problem with MVC frameworks. Almost all of the code I have to work with uses "models" as places to put functions. It is a nightmare to maintain.
To make this maintainable, IME you need a few things:
A distinct and well-defined data-access layer, the API boundary of which looks after retrieving and storing persistent storage and very little else.
I don't like to use the term "model" for that because that is contentious. Whatever calls that layer should not care how the data is stored, should not even be worrying about things like database handles: that is all the job of the data-access layer.
A dispatcher that is very light and doesn't do any magic outside of just dispatching.
Now you can put everything else in one place that accepts requests and parameters, probably normalised and error checked from the dispatcher, fetches the data (usually as objects) it needs, makes the changes it needs to do, saves the data it needs to, hands the data is needs to display to the view. Two hundred lines of code plodding through the task works for this step. You don't need to hive off bits into functions in another file that are called from nowhere else. You can even put the view on the end of this file! Idealism is nice to aspire to but pragmatism needs a look-in because this is maintainable.
(Okay, rant over... )
PHP's lack of enforcing a framework means that the best frameworks do what PHP does: they stay out of the way. Some of the most maintainable code I've worked on had a single require() statement at the top, did all the data-manipulation with data objects (no SQL in sight), then output HTML surrounded by template functions, with form control being done by a consistent function API.
I'm currently reading up on OO before I embark upon my next major project. To give you some quick background, I'm a PHP developer, working on web applications.
One area that particularly interests me is the User Interface; specifically how to build this and connect it to my OO "model".
I've been doing some reading on this area. One of my favourites is this:
Building user interfaces for object-oriented systems
"All objects must provide their own UI"
Thinking about my problem, I can see this working well. I build my "user" object to represent someone who has logged into my website, for example. One of my methods is then "display_yourself" or similar. I can use this throughout my code. Perhaps to start with this will just be their name. Later, if I need to adjust to show their name+small avatar, I can just update this one method and hey-presto, my app is updated. Or if I need to make their name a link to their profile, hey-presto I can update again easily from one place.
In terms of an OO system; I think this approach works well. Looking on other StackOverflow threads, I found this under "Separation of Concerns":
Soc
"In computer science, separation of
concerns (SoC) is the process of
breaking a computer program into
distinct features that overlap in
functionality as little as possible. A
concern is any piece of interest or
focus in a program. Typically,
concerns are synonymous with features
or behaviors. Progress towards SoC is
traditionally achieved through
modularity and encapsulation, with the
help of information hiding."
To my mind I have achieved this. My user object hides all it's information. I don't have any places in my code where I say $user->get_user_name() before I display it.
However, this seems to go against what other people seem to think of as "best practice".
To quote the "selected" (green one) answer from the same question:
"The separation of concerns is keeping
the code for each of these concerns
separate. Changing the interface
should not require changing the
business logic code, and vice versa.
Model-View-Controller (MVC) design
pattern is an excellent example of
separating these concerns for better
software maintainability."
Why does this make for better software maintainability? Surely with MVC, my View has to know an awful lot about the Model? Read the JavaWorld article for a detailed discussion on this point:
Building user interfaces for object-oriented systems
Anyway... getting to the actual point, finally!
1. Can anyone recommend any books that discuss this in detail? I don't want an MVC book; I'm not sold on MVC. I want a book that discusses OO / UI, the potential issues, potential solutuions etc.. (maybe including MVC)
Arthur Riel's Object-Oriented Design Heuristics
touches on it (and is an excellent book as well!), but I want something that goes into more detail.
2. Can anyone put forward an argument that is as well-explained as Allen Holub's JavaWorld article that explains why MVC is a good idea?
Many thanks for anyone who can help me reach a conclusion on this.
This is a failure in how OOP is often taught, using examples like rectangle.draw() and dinosaur.show() that make absolutely no sense.
You're almost answering your own question when you talk about having a user class that displays itself.
"Later, if I need to adjust to show their name+small avatar, I can just update this one method and hey-presto, my app is updated."
Think about just that little piece for moment. Now take a look at Stack Overflow and notice all of the places that your username appears. Does it look the same in each case? No, at the top you've just got an envelope next to your username followed by your reputation and badges. In a question thread you've got your avatar followed by your username with your reputation and badges below it. Do you think that there is a user object with methods like getUserNameWithAvatarInFrontOfItAndReputationAndBadgesUnderneath() ? Nah.
An object is concerned with the data it represents and methods that act on that data. Your user object will probably have firstName and lastName members, and the necessary getters to retrieve those pieces. It might also have a convenience method like toString() (in Java terms) that would return the user's name in a common format, like the first name followed by a space and then the last name. Aside from that, the user object shouldn't do much else. It is up to the client to decide what it wants to do with the object.
Take the example that you've given us with the user object, and then think about how you would do the following if you built a "UI" into it:
Create a CSV export showing all users, ordered by last name. E.g. Lastname, Firstname.
Provide both a heavyweight GUI and a Web-based interface to work with the user object.
Show an avatar next to the username in one place, but only show the username in another.
Provide an RSS list of users.
Show the username bold in one place, italicized in another, and as a hyperlink in yet another place.
Show the user's middle initial where appropriate.
If you think about these requirements, they all boil down to providing a user object that is only concerned with the data that it should be concerned with. It shouldn't try to be all things to everyone, it should just provide a means to get at user data. It is up to each of the many views you will create to decide how it wants to display the user data.
Your idea about updating code in one place to update your views in many places is a good one. This is still possible without mucking with things at a too low of a level. You could certainly create widget-like classes that would encapsulate your various common views of "stuff", and use them throughout your view code.
Here's the approach I take when creating websites in PHP using an MVC/separation of concerns pattern:
The framework I use has three basic pieces:
Models - PHP Classes. I add methods to them to fetch and save data. Each
model represents a distinct type of entity in the system: users, pages,
blog posts
Views - Smarty templates. This is where the html lives.
Controllers - PHP classes. These are the brains of the application. Typically
urls in the site invoke methods of the class. example.com/user/show/1 would
invoke the $user_controller->show(1) method. The controller fetches data out
of the model and gives it to the view.
Each of these pieces has a specific job or "concern". The model's job is to provide a clean interface to the data. Typically the site's data is stored in a SQL database. I add methods to the model for fetching data out and saving data in.
The view's job is to display data. All HTML markup goes in the view. Logic to handle zebra-striping for a table of data goes in the view. Code to handle the format that a date should be displayed in goes in the view. I like using Smarty templates for views because it offers some nice features to handle things like that.
The controller's job is to act as an intermediary between the user, the model, and the view.
Let's look at an example of how these come together and where the benefits lie:
Imagine a simple blog site. The main piece of data is a post. Also, imagine that the site keeps track of the number of times a post is viewed. We'll create a SQL table for that:
posts
id date_created title body hits
Now suppose you would like to show the 5 most popular posts. Here's what you might see in a non MVC application:
$sql = "SELECT * FROM posts ORDER BY hits DESC LIMIT 5";
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result)) {
echo "$row['title']<br />";
}
This snippet is pretty straightforward and works well if:
It is the only place you want to show the most popular posts
You never want to change how it looks
You never decide to change what a "popular post" is
Imagine that you want to show the 10 most popular posts on the home page and the 5 most popular in a sidebar on subpages. You now need to either duplicate the code above, or put it in an include file with logic to check where it is being displayed.
What if you want to update the markup for the home page to add a "new-post" class to posts that were created today?
Suppose you decide that a post is popular because it has a lot of comments, not hits. The database will change to reflect this. Now, every place in your application that shows popular posts must be updated to reflect the new logic.
You are starting to see a snowball of complexity form. It's easy to see how things can become increasingly difficult to maintain over the course of a project. Also, consider the complexity when multiple developers are working on a project. Should the designer have to consult with the database developer when adding a class to the output?
Taking an MVC approach and enforcing a separation of concerns within your application can mitigate these issues. Ideally we want to separate it out into three areas:
data logic
application logic
and display logic
Let's see how to do this:
We'll start with the model. We'll have a $post_model class and give it a method called get_popular(). This method will return an array of posts. Additionally we'll give it a parameter to specify the number of posts to return:
post_model.php
class post_model {
public function get_popular($number) {
$sql = "SELECT * FROM posts ORDER BY hits DESC LIMIT $number";
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
$array[] = $row;
}
return $array;
}
}
Now for the homepage we have a controller, we'll call it "home". Let's imagine that we have a url routing scheme that invokes our controller when the home page is requested. It's job is to get the popular posts and give them to the correct view:
home_controller.php
class home_controller {
$post_model = new post_model();
$popular_posts = $post_model->get_popular(10);
// This is the smarty syntax for assigning data and displaying
// a template. The important concept is that we are handing over the
// array of popular posts to a template file which will use them
// to generate an html page
$smarty->assign('posts', $popular_posts);
$smarty->view('homepage.tpl');
}
Now let's see what the view would look like:
homepage.tpl
{include file="header.tpl"}
// This loops through the posts we assigned in the controller
{foreach from='posts' item='post'}
{$post.title}
{/foreach}
{include file="footer.tpl"}
Now we have the basic pieces of our application and can see the separation of concerns.
The model is concerned with getting the data. It knows about the database, it knows about SQL queries and LIMIT statements. It knows that it should hand back a nice array.
The controller knows about the user's request, that they are looking at the homepage. It knows that the homepage should show 10 popular posts. It gets the data from the model and gives it to the view.
The view knows that an array of posts should be displayed as a series of achor tags with break tags after them. It knows that a post has a title and an id. It knows that a post's title should be used for the anchor text and that the posts id should be used in the href. The view also knows that there should be a header and footer shown on the page.
It's also important to mention what each piece doesn't know.
The model doesn't know that the popular posts are shown on the homepage.
The controller and the view don't know that posts are stored in a SQL database.
The controller and the model don't know that every link to a post on the homepage should have a break tag after it.
So, in this state we have established a clear separation of concerns between data logic (the model), application logic (the controller), and display logic (the view). So now what? We took a short simple PHP snippet and broke it into three confusing files. What does this give us?
Let's look at how having a separation of concerns can help us with the issues mentioned above. To reiterate, we want to:
Show popular posts in a sidebar on subpages
Highlight new posts with an additional css class
Change the underlying definition of a "popular post"
To show the popular posts in a sidebar we'll add two files our subpage:
A subpage controller...
subpage_controller.php
class subpage_controller {
$post_model = new post_model();
$popular_posts = $post_model->get_popular(5);
$smarty->assign('posts', $popular_posts);
$smarty->view('subpage.tpl');
}
...and a subpage template:
subpage.tpl
{include file="header.tpl"}
<div id="sidebar">
{foreach from='posts' item='post'}
{$post.title}
{/foreach}
</div>
{include file="footer.tpl"}
The new subpage controller knows that the subpage should only show 5 popular posts. The subpage view knows that subpages should put the list of posts inside a sidebar div.
Now, on the homepage we want to highlight new posts. We can achieve this by modifying the homepage.tpl.
{include file="header.tpl"}
{foreach from='posts' item='post'}
{if $post.date_created == $smarty.now}
<a class="new-post" href="post.php?id={$post.id}">{$post.title}</a>
{else}
{$post.title}
{/if}
{/foreach}
{include file="footer.tpl"}
Here the view handles all of the new logic for displaying popular posts. The controller and the model didn't need to know anything about that change. It's purely display logic. The subpage list continues to show up as it did before.
Finally, we'd like to change what a popular post is. Instead of being based on the number of hits a page got, we'd like it to be based on the number of comments a post got. We can apply that change to the model:
post_model.php
class post_model {
public function get_popular($number) {
$sql = "SELECT * , COUNT(comments.id) as comment_count
FROM posts
INNER JOIN comments ON comments.post_id = posts.id
ORDER BY comment_count DESC
LIMIT $number";
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
$array[] = $row;
}
return $array;
}
}
We have increased the complexity of the "popular post" logic. However, once we've made this change in the model, in one place, the new logic is applied everywhere. The homepage and the subpage, with no other modifications, will now display popular posts based on comments. Our designer didn't need to be involved in this. The markup is not affected.
Hopefully, this provides a compelling example of how separating the concerns of data logic, application logic, and display logic, can make developing your application easier. Changes in one area tend to have less of an impact on other areas.
Following this convention isn't a magic bullet that will automatically make your code perfect. And you will undoubtedly come across issues where it is far less clear where the separation should be. In the end, it's all about managing complexity within the application.
You should give plenty of thought to how you construct your models. What sort of interfaces will they provide (see Gregory's answer regarding contracts)? What data format does the controller and view expect to work with? Thinking about these things ahead of time will make things easier down the road.
Also, there can be some overhead when starting a project to get all of these pieces working together nicely. There are many frameworks that provide the building blocks for models, controllers, templating engines, url routing, and more. See many other posts on SO for suggestions on PHP MVC frameworks. These frameworks will get you up and running but you as the developer are in charge of managing complexity and enforcing a separation of concerns.
I will also note that the code snippets above are just simplified examples. They may (most likely) have bugs. However, they are very similar in structure to the code I use in my own projects.
I am not sure I can lead you to the water you wat to drink, but I think I can answer some of your concerns.
First, in MVC, the model and the view do have some interplay, but the view is really coupled to contract and not to implementation. You can shift out to other models that adhere to the same contract and still be able to use the view. And, if you think about it, it makes sense. A user has a first name and last name. He probably also has a logon name and a password, although you might or might not tie this to the "contract" of what a user is. The point is, once you determine what a user is, it is unlikely to change much. You might add something to it, but it is unlikely you are going to take away that often.
In the view, you have pointers to the model that adheres to that contract, but I can use a simple object:
public class User
{
public string FirstName;
public string LastName;
}
Yes, I realize public fields are bad. :-) I can also use a DataTable as a model, as long as it exposes FirstName and LastName. That may not be the best example, but the point is the model is not tied to the view. The view is tied to a contract and the particular model adheres to that contract.
I have not heard of every object must have its own UI. There are essentially two types of objects: state and behavior. I have seen examples that have both state and behavior, but they generally are in systems that are not very testable, which I am not fond of. Ultimately, every state object should be exposed to some form of UI to avoid forcing IT people to handle all the updates directly in a data store, perhaps, but have their own UI? I would have to see that written in an explanation to try to understand what the user is doing.
As for SoC, the reasaon to package things distinctly is the ability to switch out layers/tiers without rewriting the entire system. In general, the app is really located in the business tier, so that part cannot as easily be switched out. The data and UI should be fairly easy to switch out in a well designed system.
As far as books on understanding OOP, I tend to like books on patterns, as they are more practical ways of understanding the concepts. You can find the primer material on the web. If you want a language agnostic pattern book, and think a bit geeky, the Gang of Four book is a good place to start. For more creative types, I would say Heads Up Design Patterns.
The problem with the idea that all your objects know how to display themselves is that each object can only be displayed in one way. What happens if you want to provide a detail view of a user, and a summary view. What happens if you want to display a view that merges a number of objects (users and their associated addresses for example). If you seperate your business objects (users) from the things that know how to display them then you have no more code to write, you just seperate it into different places.
This makes software more maintainable because if a user object is behaving incorrectly, you know it is the user, if it is not displaying properly, you know it is the view. In the situation where you need to provide a new interface to your application (say you decide to provide a new look and feel for mobile browsers), then you dont need to change your user object at all, you add a new object that knows how to render the user object for a mobile browser.
SOLID principles provide some good reasoning for this, here is a relatively concise look at these. I am afraid that I dont have a book to hand that sums it up well, but experience has taught me that it is easier to write new code than it is to update old code, and so designs that favour small modular classes that plug together to achieve what is needed, while harder to design up front, are far easier to maintain in the long run. It is great to be able to write a new renderer for a user object, without ever having to delve into the internals of that object.
Can anyone put forward an argument [...] that explains why MVC is a good idea?
It keeps you sane by helping you remember what your code does because they are isolated from each other.
Consider the amount of code that
would go into that single class, if
you want to expose the same info not
only as Html on the UI, but as part
of an RSS, a JSON, a rest service
with XML, [insert something else].
It is a leaky abstraction, meaning it tries to give you the sense that it will be the only piece that will ever know that data, but that can't be entirely truth. Lets say you want to provide a service that will integrate with several external third parties. You will have a really hard time forcing them to use your specific language to integrate with your service (as it is The class the only piece that can ever the data it is using), or if in the other hand you expose some of its data you are not hiding the data from those third parties systems.
Update 1: I gave an overall look at the whole article, and being an old article (99), it isn't really about MVC as we know it today vs. object oriented, nor has arguments that are against the SRP.
You could perfectly be in line with what he said, and handle the above scenario I mentioned with specific classes responsible to translate the object's public contract to the different formats: the main concern was that we didn't have a clear place to handle the changes and also that we didn't want the information to be repeated all over. So, on the html case, you could perfectly have a control that renders the info, or a class that transform it to html or [insert reuse mecanism here].
Btw, I had a flash back with the RMI bit. Anyway, in that example you can see he is tied to a communication mecanism. That said, each method call is remotely handled. I think he was also really concerned on developers having code that instead of getting a single object and operating on the info returned, had lots of small Get calls to get tons of different pieces of information.
Ps. I suggest you read info about DDD and Solid, which as I said for the SRP I wouldn't say it is the type of things the author was complaning about
I don't know any good books on the MVC subject, but from my own experience. In web development for example, many times you work with designers and sometimes dbas. Separating the logic from the presentation allows you to work with people with different skill sets better because the designer doesn't need to much about coding and vice versa. Also, for the concept of DRY, you can make your code less repetitive and easier to maintain. Your code will be more reusable and make your job a lot easier. It will also make you a better developer because you will become more organized and think of programming in a different way. So even if you have to work on something that is not MVC, you might have a different approach to architecting the project because you understand the MVC concepts.
I guess the tradeoff with a lot of MVC frameworks for large sites is that it may not be fast enough to handle the load.
My 2c.. another thing you could do besides what was said is to use Decorators of your User objects. This way, you could decorate the user differently depending on the context. So you'd end up with WebUser.class, CVSUser.class, RSSUser.class, etc.
I don't really do it this way, and it could get messy, but it helps in avoiding the client code from having to pull a lot of info out of your User. It might be something interesting to look into ;-)
Why getter and setter methods are evil (JavaWorld)
Decorator pattern