Jump to content

Why Use Oop?


computermax2328

Recommended Posts

It's great if you plan on doing multiple projects. Then if you get more advanced and can build your own framework you can whip out the backbone of sites instantly without going through the painstaking process of starting from scratch. All the meat rests in your code. For instance, my projects typically involve lots of tables of data. So I created a table class... and instead of having to do all the looping through data and building the html... I can do this.

 

$data = DB::returnArray("SELECT id,mid,description,tenrox_id FROM modules");

$tbl->packets(
   Array('key.mid','right','w.15','title.MID','class.testClass')
   ,Array('key.description','w.65','title.Description')
   ,Array('key.tenrox_id','title.Tenrox ID')
);

$tbl->loadData($data);

$this->vars['tblHTML'] = $tbl->Buffer();

 

That right there is a basic example but builds the entire table, loops through the data, pulls the data from my database class and stores it in a variable for later use where I insert it in to my templates. And if I ever need to change something up in my tables for a project, I just have to go to the class and make one change... rather than going to every file that has a table and making the change. It's not necessary at all, but once you learn the power of it, it becomes something you can't live with out. It makes everything more efficient, manageable, and useful. Your clode becomes cleaner, you can automate a lot of uncessary typing and you can link your entire system up that makes it very easy to add pages and manage pages.

 

It seems useless at first because you can get by with just using functions and coding yourself, but trust me... once you go OOP you will never go back.

Link to comment
Share on other sites

Personally, I never understood the benefits of OOP by having someone explain them to me, something just 'clicked' one day and I 'got it', but I'll have a go

 

1) Encapsulation (hide the implementation, expose the interface)

 

This basically means, hiding away the 'implementation' and exposing an interface to that behaviour, take a lock for example, you don't need to know how a lock works, but generally, locks have a universal interface, so most people know how to unlock one (i.e. you don't have to know that when you put a key in a yale lock, that it pushes back the pins to compress the springs underneath, until the pin is completely removed from the cylinder, then when you turn the key, it also turns the catch, allowing the door to be opened, knowing the public interface is, in effect, having the key)

 

<?php
interface Lock {
 public function insertKey();
 public function releaseKey();
 public function turnKey($degrees, $direction);
 public function isUnlocked();
}

class YaleLock implements Lock {
 /*
  * @var array $_pins Array of pin lengths
  */
 protected $_pins = array();
 /*
  * @var array $_pinPositions Array containing current pin positions in milimeters
  */
 protected $_pinPositions = array();
 /*
  * @var integer $_catchPosition Current position of the catch in degrees
  */
 protected $_catchPosition = 0;
 /*
  * @param array $length_of_pins Array containing length of pins
  */
 public function __construct(array $length_of_pins) {
   $this->_pins = $length_of_pins;
   $this->_pinPositions = $length_of_pins;
 }
 public function insertKey() {
   $this->_pushBackThePins();
   return $this;
 }
 public function releaseKey() {
   $this->_releaseThePins();
   return $this;
 }
 public function turnKey($degrees, $direction) {
   if ( !$this->isCorrectKey() )
     throw new Exception('Incorrect key');
   $degrees = $direction == 'left' ? -$degrees : $degrees;
   $this->_catchPosition += $degrees;
   while ( $this->_catchPosition < 0 ) $this->_catchPosition += 360;
   while ( $this->_catchPosition > 360 ) $this->_catchPosition -= 360;
   return $this;
 }
 public function isUnlocked() {
   return $this->_isCorrectKey() && $this->isCatchReleased();
 }
 protected function isCorrectKey() {
   $positions = array_unique($this->_catchPosition);
   return count($positions) == 1 && $positions[0] == 0;
 }
 protected function isCatchReleased() {
   return $this->_catchPosition > 90 && $this->_catchPosition < 100;
 }
 protected function _pushBackThePins() {
   foreach($this->_pins as $pinKey => $pinLength) {
     $this->_movePin($pinKey, -$pinLength);
   }
 }
 protected function _releaseThePins() {
   foreach($this->_pins as $pinKey => $pinLength) {
     $this->_movePin($pinKey, $pinLength);
   }
 }
 protected function _movePin($which_pin, $number_of_milimeters) {
   $this->_pinPositions[$which_pin] += $number_of_milimeters);
 }
}
$Lock = new YaleLock(array(3, 7, 4, 5, 2));
$Lock->insertKey()->turnKey(90, 'right');
if ( $Lock->isUnlocked() ) {
 echo 'The door is unlocked';
} else {
 echo 'The door is locked';
}
$Lock->turnKey(90, 'left')->releaseKey();
if ( $Lock->isUnlocked() ) {
 echo 'The door is unlocked';
} else {
 echo 'The door is locked';
}

 

So now using all of these functions enforced to be defined by the interface, we know we can operate a lock properly. We could create many different locks that implement this interface (see below), and anyone who knows the interface can operate the lock, you only need know the encapsulated functionality if you're a locksmith (hacker, extending a lock's functionality) or a thief (cracker).

 

 

class MorticeLock implements Lock {
 // the juciy bit
}

We can now unlock a mortice lock using the same interface as a yale lock, a 'universal interface' to the underlying functionality.

 

2) Code re-use

 

If you make code generic enough, it should be easy to extend on that code for use in the same project, or plug that code into another project (or both).

 

I.e. Lets say someone installed an intercom to allow this lock to be unlocked electronically. To do this we need to encapsulate some functionality to be re-used programmatically.

 

<?php
interface Lock {
 public function insertKey();
 public function releaseKey();
 public function turnKey($degrees, $direction);

 protected function _lock();
 protected function _unlock();
}

class YaleLock implements Lock {
 /*
  * @var array $_pins Array of pin lengths
  */
 protected $_pins = array();
 /*
  * @var array $_pinPositions Array containing current pin positions in milimeters
  */
 protected $_pinPositions = array();
 /*
  * @var integer $_catchPosition Current position of the catch in degrees
  */
 protected $_catchPosition = 0;
 /*
  * @param array $length_of_pins Array containing length of pins
  */
 public function __construct(array $length_of_pins) {
   $this->_pins = $length_of_pins;
   $this->_pinPositions = $length_of_pins;
 }
 public function insertKey() {
   $this->_pushBackThePins();
   return $this;
 }
 public function releaseKey() {
   $this->_releaseThePins();
   return $this;
 }
 public function turnKey($degrees, $direction) {
   if ( !$this->isCorrectKey() )
     throw new Exception('Incorrect key');
   $degrees = $direction == 'left' ? -$degrees : $degrees;
   $this->_catchPosition += $degrees;
   while ( $this->_catchPosition < 0 ) $this->_catchPosition += 360;
   while ( $this->_catchPosition > 360 ) $this->_catchPosition -= 360;
   return $this;
 }
 public function isUnlocked() {
   return $this->_isCorrectKey() && $this->isCatchReleased();
 }
 protected function _lock() {
   $this->_pushBackThePins();
   $this->turnKey(90, 'right');
 }
 protected function _unlock() {
   $this->_releaseThePins();
   $this->turnKey(90, 'left');
 }
 protected function isCorrectKey() {
   $positions = array_unique($this->_catchPosition);
   return count($positions) == 1 && $positions[0] == 0;
 }
 protected function isCatchReleased() {
   return $this->_catchPosition > 90 && $this->_catchPosition < 100;
 }
 protected function _pushBackThePins() {
   foreach($this->_pins as $pinKey => $pinLength) {
     $this->_movePin($pinKey, -$pinLength);
   }
 }
 protected function _releaseThePins() {
   foreach($this->_pins as $pinKey => $pinLength) {
     $this->_movePin($pinKey, $pinLength);
   }
 }
 protected function _movePin($which_pin, $number_of_milimeters) {
   $this->_pinPositions[$which_pin] += $number_of_milimeters);
 }
}
interface ElectronicLock {
 public function pushTheButton();
}
class ElectronicYaleLock extends YaleLock implements ElectronicLock {
 public function pushTheButton() {
   $this->unlock();
 }
}

 

Now we can extend any lock to allow for it to be electronically unlocked, and by implementing ElectronicLock, we also encapsulate this behaviour.

 

As well as these advantages, lets say you have a project with say, 9000 lines of code, if this is programmed in a procedurally, you may have 450 instances of:

 

echo htmlspecialchars($variable);

 

But now you decide you don't want to use htmlspecialchars, you want to use htmlentities instead, you have to change 450 instances of that function call, now, lets say you programmed your project in OO PHP:

 

class Sanitize {
 public static function html($variable) {
   return htmlspecialchars($variable);
 }
}

 

Now you have 450 instances of

 

Sanitize::html($variable);

 

now, implementing this change is simple, just change the method body:

 

class Sanitize {
 public static function html($variable = '', $ent = ENT_QUOTES, $charset = 'utf8') {
   return htmlentities($variable, $ent, $charset);
 }
}

 

Now I know you can just use a function to do this in procedural code, but I believe it is a lot cleaner to use the OO method, this way you can group all of your sanitization methods into one class, and you know if you need to re-use your sanitization class, it's just a case of dropping that file into another project.

 

There's also the advantage of autoloading:

 

<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'lib' . PATH_SEPARATOR . 'models');
spl_autoload_register(function($class) {
 include str_replace('\\', '/', $class) .'.class.php';
});

 

Now if you stick to a naming convention with your classes, files and locations, you shouldn't really have to use include(_once) or require(_once) in the entire lifespan of your project.

 

The above code expects a naming convention of - namespaces map to a folder in root_directory/lib or root_directory/models, files containing class definitions should be saved as class name the .class.php extension i.e.

 

// root_directory/lib/ORM/DataMapper.class.php
namespace ORM;

class DataMapper {

}

 

Hope that helps.

Edited by Andy-H
Link to comment
Share on other sites

That's a very big question! Perhaps reading beginner articles about object-oriented programming in general (not specific to PHP) would help you understand the benefits of it. Understanding how will help you understand why I believe. Anyways, I think some of the main keywords are flexibility and maintainability. It's so much easier to change and maintain objected-oriented code for many reasons; one essential reason for this is that your IDE will be able to help you much more because it has more static information to use. It will also make your code less error prone because your IDE can catch many mistakes that are probably not detected until executed (and who knows if all code paths are executed?). I also find object-oriented code much easier to understand if I am reading someone else's code because it is more structured.

 

Things such as interfaces, abstract classes and inheritance are also essential for making your code flexible to future changes. Sure, this will increase development time a bit but will save you so much time and so many headaches when changing your code in the future. I have had discussions similar to the below countless of times with other developers.

 

Silly developer: "I'm lazy and it's easier to do like this"

Me: "But what if you have to do X in two months?"

Silly developer: "I won't"

Me: "How do you know? What if you do?"

Silly developer: "I won't"

 

Two months later the boss is asking me to change X, and a minor change that would usually take 10 minutes could easily take hours and include hacky workarounds. As a result, the code gets more and more spaghetti like resulting in errors in Y when you change X. In no time, projects can turn into a nightmare. Code bases grow; don't expect projects to stay like originally intended for forever.

 

The thing is that they cannot predict what their boss is going to ask them to do in two months. Business requirements change and the code has to change accordingly. Business agility is a hot topic and businesses want to rapidly change to remain competitive in a changing market. If you build code to support exactly one thing, then even small changes can take many, many hours. Trust me, I have seen this many times. You just don't know how you will have to change your code in the future, so you better make it flexible from the beginning. Even if you are developing a personal project and you are the only one involved, who knows what bright idea you will have in the future?

 

There are many, many benefits of OOP, but it has been written many times before. I just wrote a few benefits that I find essential, but surely there are many others.

Edited by Andy123
Link to comment
Share on other sites

Alright, so overall storing and reusing code that you are going to need over and over again in a website. The tables example was a good example and I appreciate your extended explanation.

 

Another question I have about it is can you store your html in it?? For example say I want to save the html of my banner, nav bar and footer, so that I can just reuse them over and over again on each individual page. The method I was taught was to use save that code in an php file and include or require it on the pages that you need it in.

 

include('includes/header.php');

Link to comment
Share on other sites

Alright, so overall storing and reusing code that you are going to need over and over again in a website. The tables example was a good example and I appreciate your extended explanation.

 

Another question I have about it is can you store your html in it?? For example say I want to save the html of my banner, nav bar and footer, so that I can just reuse them over and over again on each individual page. The method I was taught was to use save that code in an php file and include or require it on the pages that you need it in.

 

include('includes/header.php');

 

That's a good point actually, OOP is commonly used in conjunction with MVC (Model View Controller), which is about separation of control flow logic, business logic (or model logic) and view logic, generally you would have a main template containing your page layout, and insert a yield into an appropriate place in that page.

 

This also couples with re-usable models, as the data a model interfaces to, can be applied across many views.

 

The controllers responsibility is basically to take a request URL (often aided by a router), and control what models are used, what data is returned and what views are invoked to return the content to the browser.

 

mvc-architecture.gif

 

I would checkout the Github repositories of some open source frameworks, such as Zend Framework, Yii or Rails (for Ruby) and start hacking away at them to learn about how they work.

 

I haven't read this as I'm at work at the moment, it's just the first organic google result when searching MVC principles:

 

http://www.htmlgoodies.com/beyond/php/article.php/3912211/Principles-Of-MVC-for-PHP-Developers.htm

Link to comment
Share on other sites

So where does MYSQL Queries play in this?

 

A lot of people (particularly in web development) like to put this data access logic in the model layer. I strongly disagree with this because business logic should not be concerned with how the data is stored and accessed. For small projects this may be easier, but it is not good practice. You should use a Data Access Layer (DAL) as an abstraction instead for several reasons. Firstly, your model layer is only concerned with business logic, which makes it more portable and also easier to understand. Secondly, if you are changing the way your data is stored, you know where to look because it's centralized. As long as your DAL uses the same interfaces, then the rest of your application will remain unaffected by a change of your data source. This means that the application is more flexible, easier to maintain and the various layers are easier to reuse in other contexts. These are the main reasons that I can think of off the top of my head.

Link to comment
Share on other sites

So where does MYSQL Queries play in this?

 

I personally use a query building class to build dynamic query strings and a static database class to execute my queries. As you saw in the example I gave you, that is what the "DB::returnArray()" is.

 

I don't know all the super programming jargon for these concepts, but I will try to explain them the best I can. What I do, that has worked for me the past 2+ years, is to kind of build a maze with a prize at the end (the display). And then pretend you are the user. What is the first thing you need to do when a user comes to the door to enter the maze? And remember there is only one door. In this ridiculous analogy that door for me is index.php (most of the time). I do not set up the site where it has .com/file1/file2/lastFile.php. I use GET variables to do my file finding for me. So for instance this would be index.php?firstPage=file1&secondPage=file2&display=lastFile. Of course that's not my actuall GET keys and logic... but you get the picture. This way there is only one entrance to your site. And if you ever need to change the code for what you need to do when a user enters the site, there is only one location to have to do this. And if anyone tries to enter a hidden door to the site, you make sure they are punished!! I do this by setting a constant in the index.php that only gets created if they enter that door. Then every file checks to make sure this constant is set. If it is not, I know they are trying to break through a trap door.

 

So then I check the users authentication, set up the sessions, get all the necessary backend logic done before the user starts his path. Then I give that user a class (I call it the Brains). As the user goes through the maze, I gather information and store it in this class (well there isn't really a different class for each user, it's the same class, but you get the point). So if the user goes to the Admin door. Before they can enter, they have to go through another security checkpoint. So pretend they are trying to get to the accounts section to change a users e-mail address. This accounts section is within the admin controller. So my url for example would look something like this .com/index.php?c=admin&b=accounts. C is what I consider the controller, and b is the brain or logic within that controller. So I first go to the admin.controller.php file. That is the one door to get in to the admin section. There is only one file for this. So if that file contains a header or a navigation panel... I throw it in to my brains class storing it as a template. I also populate the variables that are needed for this navigation panel. Say you permissions set up where certain users can only access certain doors within the admin section. Then I store those variables, and move on to the next logic portion. That would be the accounts section. I do the same thing here.

 

Then if everything checks out, all the security checkpoints pass, the path leads to the finish line. I then take all the information I gathered during that path and create the final display. There is no including html files during the maze. That happens at the very end once you KNOW that the user has a chance to see this.

 

This is just a simple analogy, but you get the picture. During this process you can handle all sorts of different errors, relay messages to the user, etc, etc. So that is one benefit of OOP is that you can store things across files. So when I load up the accounts file. I do something like

 

$this->loader('brains.accounts');

//Now, then the brains class includes this file within the class. So now I can use everything I've gathered already within the accounts file.

//So the accounts.brains.php file I can use
$this->auth->doSomething();

//or
$this->get('post.postKey');

 

So it really makes life a lot easier when there is only one path the user can go through and you collect all the data throughout that path before you use that data to create the actually display of your site. Now that I reread this, I realize it's a pretty bad analogy... but I'm going to post it anyway, lol. Good luck.

Edited by akphidelt2007
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.