PHP OOP: Back to Basics

beginBack to Basics

Whenever I venture outside of PHP, which has become more regular as I’m working on app development in both iOS and Android. The former is Objective C and the latter, Java. Both languages are embedded in OOP and design patterns. It is during these ventures abroad (so to speak) that I’m reminded of some core issues in good OOP. I usually notice them when I realize that I’m not exactly paying attention to them myself.

Don’t Have the Constructor Function Do Any Real Work

When I first came across the admonition not to have the constructor function do any real work, I was reading Miško Hevery’s article on a testability flaw due to having the constructor doing real work. More recently, I was reviewing some materials in the second edition of Head First Java, where the user is encouraged to,

Quick! Get out of main!

For some Java and lots of C programmers “main” is the name for a constructor function, but I like PHP’s __construct() function as the preferred name since it is pretty self-describing. “Main” is a terrible name because the real main is in the program made up of interacting classes.

In both cases, the warning about minimizing the work of the constructor function is to focus on true object oriented applications where you need objects talking to one another. Think of this as a series of requests where a group of people are all cooperatively working together, each from a separate (encapsulated) cubicle, to accomplish a task. By having the constructor function do very little, you’re forcing yourself (as a programmer) to use collaborative classes. Play the example and download the code to get started:
PlayDownload

A General Model for PHP OOP

As a nice simple starting place for PHP OOP, I’ve borrowed from the ASP.NET/C# relationship. ASP.NET provides the forms and UI, and C# is the engine. As an OOP jump-off point, we can substitute HTML for ASP.NET and PHP for C#. The Client class is the “requester” class. The UI (HTML) sends a request to the Client, and the Client farms out the request to the appropriate class. Figure 2 shows this simple relationship.

Figure 1: A Simple OOP PHP Model

Figure 1: A Simple OOP PHP Model

If you stop and think about it, OOP is simply a way to divide up a request into different specializations.

Avoid Conditional Statements if Possible

Figure 2: Requests begins with a UI built in HTML

Figure 2: Requests begins with a UI built in HTML

If you avoid conditional statements, and this includes switch statements, I think you can become a lot better programmer. In the example I built for this post, the user chooses from two different types of requests (classes), and each request has a refined request (method) that provides either of two different kinds of math calculations or display options. Figure 2 shows the UI (HTML) for the example. If the user selects “Do a Calculation” it sends the request to the Calculate class, but if the user selects “Display a story”, the request is handled by the Display class. Further, not only must the right class be selected, the right method in that class must be selected as well. The obvious answer is to get information from the UI and using a switch or set of conditional statements work out in the Client how to handle each request. You could even use (shudder) nested conditional statements. That approach could work, but when you start piling up conditional statements, you’re more likely to introduce errors, and when you make changes, you’re even more likely to make errors. The only good thing about conditionals is that you don’t have to tax your brain to use them.

Suppose for a second that all of your conditional statements were taken away. How, using the information sent from the HTML UI to the Client class can the selections be made without conditional statements? (Think about this for a moment.)

Think, pensez, pense, думайте, piense, 생각하십시오, denken Sie, 考えなさい, pensi, 认为, σκεφτείτε, , denk

Like all things that seem complex, the solution is pretty simple. (Aren’t they all once you know the answer.) Both classes were given the value of their class name in their respective radio button input tags. Likewise, the methods were given the value of their method names. With two radio button sets (request and method), only two values would be passed to the Client class. So all the Client had to do was to use the request string as a class name to instantiate an instance of the class, and employ the following built-in function:

call_user_func(array(object, method));

That generates a request like the following:

$myObject->myMethod;

In other words, it acts just like any other request for a class method. By coordinating the Client with the HTML UI, that was possible without using a single conditional statement. In this next section, we’ll now look at the code.

The following two listings show the HTML for the UI and the Client class code. Note the relationship between the UI and the Client. Like everything else in OOP, you start with relationships.

UI

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>User Interface</title>
    <link rel="stylesheet" href="basicoop.css">
    <script src="basicoop.js"></script>
</head>
<body>
<h3>What Request Do You Have?</h3>
<form name="classNow" action="Client.php" method="post" target ="feedback">
  <input type="radio" name="request" value="Calculate" onclick="handleCalc(this);" checked="true">
  Do a Calculation<br />
  <input type="text" name="first" size="6" value="1">
  &nbsp;First number<br />
  <input type="text" name="second" size="6" value="1">
  &nbsp;Second number<br />
  <blockquote>
    <input type="radio" name="method" value="doMultiply" checked="true" onclick="useCalc(this);">
    Multiply Two Numbers<br />
    <input type="radio" name="method" value="doDivide" onclick="useCalc(this);">
    Divide Two Numbers (first by second)<br />
  </blockquote>
  <input type="radio" name="request" value="Display" onclick="handleDisplay(this);">
  Display a story<br />
  <blockquote>
    <input type="radio" name="method" value="displayWhiteBlack" onclick="useDisplay(this);">
    White Background<br />
    <input type="radio" name="method" value="displayBlackWhite" onclick="useDisplay(this);">
    Black Background
    <p />
    <textarea name="story" cols="24" rows="5">Tell story: </textarea>
  </blockquote>
  <input type="submit" value="Send Request">
  <p />
  <iframe name="feedback" width="250" height="250">Feedback</iframe>
</form>
</body>
</html>

Client

<?php
function __autoload($class_name) 
{
    include $class_name . '.php';
}
class Client
{
    private $classNow;
    private $requestMethod;
    private $requestObject;
 
    //constructor function
    public function __construct()
    {
       $this->makeRequest();
    }
 
    private function makeRequest()
    {
      $this->classNow=$_POST['request'];
      $this->requestMethod=$_POST['method'];
      $this->requestObject = new $this->classNow();
      echo call_user_func(array($this->requestObject, $this->requestMethod));
    }
}
$worker=new Client();
?>

By having a single function [call_user_func()] to call both the class object and method, the Client can easily pass the request to the appropriate class and method.

Everything is an Object: Encapsulate HTML in PHP

One of the more disturbing practices in PHP (that we’re all guilty of at one time or another) is to slap a PHP start and finish tag on an HTML document and call it a “PHP document.” Talk about putting lipstick on a pig! The UI in this example is HTML5 with no pretense at all to being PHP. It is a UI, pure and simple; just like ASP.NET is a UI to C#. Even worse are these PHP files with a little PHP, a little HTML, all mixed up like a running with the bulls melee in Pamplona, Spain.

However, there will be times when you need to place HTML in a PHP class–not a PHP file, but a PHP class. Doing so is not difficult, and the HTML document can be an encapsulated object and not some patch-work code. Fortunately, the Display class that generated two little Web pages in the iframe does exactly that. Take a look at the code:

Display

<?php
class Display
{
   private $msg;
   private $document;
   private $bgColor;
   private $txtColor;
   private $story;
   private $sendStory;
 
   public function displayWhiteBlack()
   {
      $this->bgColor="#fff";
      $this->txtColor="#000";
      $this->sendStory=$this->displaySetup();
      return $this->sendStory;
   }
 
   public function displayBlackWhite()
   {
      $this->bgColor="#000";
      $this->txtColor="#fff";
      $this->sendStory=$this->displaySetup();
      return $this->sendStory;
   }
 
   private function displaySetup()
   {
      $this->story=$_POST['story'];
      $this->document = <<<DISPLAY
      <!DOCTYPE html>
      <html>
	 <head>
	 <style type="text/css">
	 body
	 {
	    font-family:Verdana, Helvetica, Arial, sans-serif;
	    color:$this->txtColor;
	    background-color:$this->bgColor;
	 }
	 h3
	 {
	    font-family:Impact, "Arial Black", sans-serif;
	    color:$this->bgColor;
	    background-color:$this->txtColor;
	    text-indent:1em;
	 }
	 </style>
	 <title>Display Page</title>
	 </head>
	 <body>
	 <h3>Here's the story</h3>
	 $this->story
	 </body>
      </html>
DISPLAY;
      return $this->document;
   }
}
?>

As you can see, the private variable $this->document encapsulates the HTML using the heredoc string structure. (The heredoc string begins with <<<DISPLAY and ends with DISPLAY; on the far left side of the listing.) So now, instead of having a wild hare in the form of HTML niblets, the program has an object that happens to be an HTML page. Further, it can use dynamically all of the PHP properties used by the class.

Use Return in Method Requests

All of the methods in these examples use the return statement to deliver the objects back to the requesting class, Client. Sometimes you will see a call to a method in a class, and that method sends the results of the request to the screen instead of returning them, but a generally good practice is to use return with methods. Take a look at the final class used in this post, and we’ll see why.

Calculate

<?php
class Calculate
{
   private $calc, $a, $b;
   public function doMultiply()
   {
      $this->setValues();
      $this->calc = $this->a * $this->b;
      return "Your results are: " . $this->calc;
   }
 
   public function doDivide()
   {
      $this->setValues();
      $this->calc = $this->a / $this->b;
      return "Your results are: " . $this->calc;
   }
 
   private function setValues()
   {
      $this->a=$_POST['first'];
      $this->b=$_POST['second'];
   }
}
?>

In this example, the return object ($this->calc) has been concatenated with a string, but suppose that you want only numeric values. Then, several classes working together can form a set of objects to be used (and reused) to create complex formulas for a single statistic as was done with the t-test in a previous post on this blog. One class handled determining the mean and another class, using the mean, calculated the standard deviation. For most applications, all you want your methods to do is to fulfill a request and return the results to the requester.

Conclusion

To use and understand OOP in PHP (or any other language), you need to drop sequential thinking and engage in relationship thinking. By breaking down tasks into simpler units, your code is easier to debug and to re-use. By arranging classes, each with a single responsibility, you can then focus on what you need to accomplish by making requests from the objects (classes) that specialize in getting done what you need in your project. With OOP, simple is better and by relating simple tasks you can achieve great things.

Share

Copyright © 2014 William Sanders. All Rights Reserved.

0 Responses to “PHP OOP: Back to Basics”


  • No Comments

Leave a Reply