Archive for the 'Scope and Visibility' Category

PHP Class Origins: An OOP Job for the HTML UI

couchPotatoPutting HTML to Work

At some point in OOP development with PHP, I quit putting little PHP code snippets in HTML. I either left all PHP out of HTML or encapsulated HTML in a PHP heredoc string inside a class. In that way, all PHP would be part of an OOP order without any loose ends. That may seem overly fussy, but it avoids the slippery slope of degenerating back into sequential programming——patchwork quilt programming.

However, such a practice should not disallow HTML from helping out in an OOP project. A lot of times, I found myself sifting through class and method options using more conditional statements than I wanted in the Client. I realized that I could just pass the class name directly to the Client from a superglobal with origins in an HTML input form. Likewise, I could do the same for methods, and this has become a useful standard operating procedure.

To better illustrate using the HTML UI in launching a selected class object, the following application uses the color and number input elements with both class and method information stored in HTML element values. Both are trivial, but help illustrate the point: (Use Firefox, Chrome or Opera–neither Safari nor Internet Explorer implemented the HTML5 standard color input element.)
PlayDownload

It’s odd in a way that PHP developers (myself included) are so used to using HTML UIs for data input into MySql databases or making other choices, but few use the UI for calling classes and methods. However, it’s both easy and practical.

Where to Put the OOP in HTML?

You can place class and method names as values anywhere in form inputs that you’d put any data passed to PHP as superglobals. One input form I found useful is the hidden one. It’s out of the way, and you can build forms around the class with other superglobal inputs as methods. Using radio button inputs is another nice option because you can use them either for calling classes or methods with the mutual exclusivity assurance of knowing that not more than one will be called from a given group. To get started, take a look at the HTML:

?View Code HTML
< !DOCTYPE html>


    
    Unsetting Superglobals with Classes and Methods

 

    

Classes and Methods

Choose color from the color window:

Divide or modulo the following two numbers:
First:    Second:   
 Divide the second by the first
 Modulo the second by the first

The code has two forms, alpha and beta, and you can think of them as I/O for two different classes. The feedback is returned to the iframe named feedback. Both forms have the action calls to Client.php. So the general plan is:

Client → Class->method()

In the alpha form, the class is ColorClass and the method is doColor()—both in hidden input elements. The name for the class element is “class” and the name for the method element is “method.” All the user does is to choose a color that is passed through the superglobal associated with the color input element.

In the beta form, the class is MathClass placed in a hidden input element. The user chooses either a division or modulo operation from the two radio input elements where the names of the appropriate methods are stored. Once again, the name for the class element is “class” and with mutually exclusive choices the radio button elements for selecting the method, the name is “method.” In this way, whatever superglobal named “class” will fire the correct class and call the correct method with the superglobal named “method.”

The Client

As usual, the Client is the launching pad for the operations. If your application uses different client classes depending on user choices, it’s an easy matter to have unique client names for different forms. In this particular case, the Client class doesn’t care about the form of origin for the request. It just takes the class superglobal and method superglobal names and generates a call to the appropriate class and method.

As an aside, the Client in OOP should not be as rare as some perceive it to be. In one way or another, users (or non-human request mechanisms) employ some way to request that the software do something. The Client, as a participant in a structure, is in virtually every design pattern in one way or another. Even when the Client is not directly or implicitly in a design pattern, The Gang of Four reference it as related to one of the participants in the pattern. So while this example does not use a design pattern, the Client works perfectly well in any OOP program.

< ?php
/*
 * Set up error reporting and
 * class auto-loading
*/
error_reporting(E_ALL | E_STRICT);
ini_set("display_errors", 1);
// Autoload given function name.
function includeAll($className)
{
    include_once($className . '.php');
}
//Register
spl_autoload_register('includeAll');
 
//Class definition
class Client
{
    private static $object, $method;
    //client request
    public static function request()
    {  
        self::doSuper();
        $operation = new self::$object();
        echo $operation->{self::$method}();
    }
 
    private static function doSuper()
    {
        self::$object = $_POST['class'];
        self::$method=$_POST['method'];
        unset($_POST['class']);
        unset($_POST['method']);
    }
}
Client::request();
?>

The Client file first takes care of error reporting and automatically calling classes. One experienced developer told me that adding an error-reporting function was unnecessary because it could be automatically turned on in the php.ini file. That’s true, but since I work with many different PHP environments where I have no control over the php.ini file, I’ve found it to be a good practice. You only have to put it in once place, and it takes care of error reporting for the entire program. Besides, I found that one safeguard against easy hacking is to turn off error reporting so that hackers cannot see the names of the classes involved in the application. For this blog, though, I leave the error reporting on because there’s nothing on this blog I want to hide. (Change the init_set from “1” to “0” to turn off all error-reporting.)

No Returns from Constructor Functions

The first incarnation of this application used the same two forms, but the alpha form only had the class name with the results planned to be sent back for output using a return statement. I kept getting errors, and then I learned that constructor functions (those using the __construct() method) have no returns. All they do is to instantiate the class. If you do not use the __construct() method, there’s an invisible automatic constructor function that does that for your as soon as you call new ClassName().
Continue reading ‘PHP Class Origins: An OOP Job for the HTML UI’

PHP Introduction to OOP: UI-Client-Request

clientBasicAn Easy Start

A lot of starting concepts in OOP seem designed to confuse and warn off developers who want to move up to OOP from sequential and procedural programming. This post is to give you a bit of what was presented at the NE PHP & UX Conference and to provide a simple yet clear introduction to OOP applied to PHP.

The easiest way (and least confusing) is to begin with the idea of “objects” and communication between objects. As you may know, objects are made up of classes containing “properties” and “methods.” Properties look a lot like PHP variables and methods like functions. So, think of properties as things a car has–like headlights, a steering wheel and bumpers, and think of actions your car can take, like turning left and right or going forward and reverse as methods.

The “blueprint” for an object is a class, and when a class is instantiated in a variable, it becomes an object. Objects communicate with one another by access to public properties and methods.

At the 2014 NE PHP & UX Conference in Boston, I told those at my session that I’d have some materials for them, and so you can download them here. One is a folder full of examples from my session and the other is an introductory book (in draft form) for getting started in OOP for PHP users. Also, the Play buttons runs the little example program for this post.
PlayconfFilesoopBook

A Request-Fulfill Model

At the heart of OOP is some system of communication. The simplest way to think about communication between objects is a request-fulfill model. A client makes a request to an object to get something. The request can originate in the user UI, and it is passed to a client who finds the correct class and method to fulfill the request. Figure 1 shows a file diagram with an overview of this model:

Figure 1: Object communication

Figure 1: Object communication

In Figure 1, you can see that the only non-object is the CSS file (request.css), and so in a way, you’re used to making requests for an external operation if you’ve used CSS files. However, CSS files are not objects but rather depositories. Likewise, external JavaScript (.js) files can be called from HTML documents for use with Web pages, but they too are not objects.

Encapsulating HTML in a Class

With PHP, the UI is handled by HTML, but that does not mean that it cannot be encapsulated in a PHP object. Encapsulation is not accomplished by simply adding a .php extension to the file name, but rather, fully wrapping the HTML in a PHP class. The easiest way to do that is with a heredoc string. The following example shows how a fully formed HTML5 document is encapsulated:

Listing #1:

< ?php
class RequestUI
{
    private $ui;
 
    public function request()
    {
        //Heredoc wrapper
        $this->ui=< <<UI
        DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="request.css"/>
    <title>Requesttitle>
head>
 
<body>
    <h3>Mathster Mind:<br /> The UI Class & Method Requesterh3>
<form name='require' action='Client.php' method='post' target='feedback'>
    <input type='hidden' name='class' value='MathsterMind'/>&nbsp;MathsterMind Class<br />
    <input type='text' name='num' size='6'/>&nbsp;Enter value <br />
 
    <fieldset>
        <legend>Methodslegend>
    <input type='radio' name='method' value='doSquare'/>&nbsp;Square the value<br />
    <input type='radio' name='method' value='doSquareRoot'/>&nbsp;Find the squareroot of the value<br />
    fieldset><br />
    <input type='submit' name='send' value='Make Request'/>  
form>
<iframe name='feedback'>Feedbackiframe>
 
body>
html>
UI;
    echo $this->ui;
    }  
}
//Instantiate an object from the class
$worker=new RequestUI;
//Call the public method from the instantiated object
$worker->request();
?>

The key aspect of encapsulating HTML in a class is the heredoc wrapper:

//Heredoc wrapper
$this->ui=<< //HTML Code
UI;

A heredoc string begins with three less-than symbols (they look like chevrons laid on their side), the name you give the heredoc string and it ends with heredoc string name fully on the left side of the source code and terminated with a semi-colon. Typically, the heredoc string is assigned to a variable ($this->ui). The great thing about using heredoc, is that you can develop and debug your HTML document, and once it’s all ready, you just paste it into a heredoc wrapper. Now, instead of a free range chicken running around with snippets of PHP code, you have a fully encapsulated object. Thus, your UI is a PHP class with all of the possibilities and security of a well formed class. (Click below to see how requests are “caught” by a PHP client.)
Continue reading ‘PHP Introduction to OOP: UI-Client-Request’

Design Patterns, Scope, Globals and Superglobals in PHP

localGlobalThe Problem with Globals

Earlier this summer I completed a course through Rice University on Python. It was an introduction to making games with Python, and the four professors who taught it, did so brilliantly. One of the nagging issues that came up early was the use of global variables. In a clear explanation of the difference between local and global variables, virtually identical to PHP, we went through several game development exercises. At the very end of the class, however, we were admonished not to use global variables.

Online, you will find plenty of reasons to avoid globals in every computer language, but the main reason is one of maintainability. Because globals are accessible to all functions, their state can be changed by all functions. As a result, you may get unexpected outcomes that can be very difficult to track down, especially in larger programs. It’s like having a wild hare running through your program.

Encapsulation and Global Variables

Let’s start off with a simple example of global troubles. The following two programs represent sequential/procedural listings with a global.

Simple Global


$gvar = "Hello everyone!";
function showOff()
{
    echo $GLOBALS['gvar'];
}
showOff();
?>

Global With Changes


$gvar = "Hello everyone!";
function showOff()
{
    echo $GLOBALS['gvar'];
}
function fixUp()
{
    $GLOBALS['gvar']="If it weren't for treats, dogs would rule the world.";
}
fixUp();
showOff();
?>

The ouput is wholly different for these two programs when the function showOff() is called:

  • Hello everyone!
  • If it weren’t for treats, dogs would rule the world.

As programs grow in size and complexity, the problem of globals grows proportionately. (If multiple programmers are involved, the problem grows exponentially!).

Now let’s look at the same issue in a class with a global variable.


class Alpha
{
    public $gvar = "Hello everyone!";
 
    public function __construct()
    {
        echo $GLOBALS['gvar'];
    }
}
$worker1 = new Alpha();

It throws an error:

    Notice: Undefined index: gvar in ….

Rather than trying to find a clever way to get globals into classes, using either the keyword global or the associative array $GLOBALS, let’s just say that a focus on visibility in classes will better serve further discussion of global scope when it comes to OOP encapsulation. (Visibility will be discussed in an upcoming post.)

Local Variables in Classes and Methods

Local variables work with methods in the same way as they do in unstructured functions. The locality of the variable does not matter in terms of return to a call or request. As with all other visibility, that depends on the method. The following example shows a local variable named $local in multiple methods with different content and different visibility. The Client class has a local variable in the constructor function, $runner. The following listing shows a request from within a class and by an external client.


ini_set("display_errors","1");
ERROR_REPORTING( E_ALL | E_STRICT );
 
class LocalReport
{  
    public function __construct()
    {
        echo $this->showOff1() . "
"
; echo $this->showOff2() . "
"
; } private function showOff1() { $local = "All good things come to pass."; return $local; }   private function showOff2() { $local = "Fatal assumptions: He will change; she won't change."; return $local; }   public function showOff3() { $local = "We serve the public (visibility)!"; return $local; }   }   class Client { public function __construct() { $runner=new LocalReport(); echo $runner->showOff3(); } }   $worker = new Client(); ?>

The output is:

    All good things come to pass.
    Fatal assumptions: He will change; she won’t change.
    We serve the public (visibility)!

Whether to use local variables or class properties in OOP development depends on the purpose of the application under development. I tend to go for private properties to better insure encapsulation, but local variables can be handy in certain types of implementations. In either case, neither is subject to the problems associated with global variables.
superglobalman250
Superglobals

Superglobals in PHP are automatic predefined global variables available in all scopes throughout a script. Most PHP developers are familiar with $_GET and $_POST, but other superglobals such as $_COOKIE, $_SESSION and $_SERVER are commonly used as well. Elsewhere on this blog, injection attacks through superglobals have been discussed, but here I want to look at the relationship between OOP/Design Patterns and superglobals.

To get a good idea of the “superness” of superglobals, consider a typical OOP program where the requesting class is a client. It calls a class that uses a superglobal. Also, to acknowledge Brazil’s 2014 World Cup hosting, and the publication of Learning PHP Design Patterns in Portuguese (Padrões de Projeto em PHP), I thought I’d create the UI in Portuguese as shown in Figure 1:

Figure 1: Data input module

Figure 1: Data input module

The HTML data entry is a simple one, asking for the user’s favorite team and favorite sport. They are saved in the super global elements, ‘team’ and ‘sport’ and then sent off using the post method. The following HTML code was used:

DataEntry.html

?View Code HTML



    
    
    Data Entry

 

    

Exame dos Esportes

Dê entrada com o nome da equipe e do esporte em umas caixas de texto apropriadas:

Equipe de esportes favorita
Esporte favorito

You’ll have to excuse my poor Portuguese. In English it asks to enter your favorite team and sport. (As a long-suffering Chargers fan, you can see the sample entry in Figure 1.) Also, it needs some CSS, lest you think me a total savage:

brazil.css

@charset "UTF-8";
/* CSS Document */
/* 06794e (green), f8d902 (yellow), 1b3c83 (blue), ffffff */
body
{
        font-family:Verdana, Geneva, sans-serif;
        color:#06794e;
        background-color: #f8d902;
}
h2
{
        font-family: "Kilroy WF", "Arial Black", Geneva, sans-serif;
        color: #ffffff;
        background-color: #1b3c83;
        text-align: center;
 
}
img
{
        display: block;
        margin-left: auto;
        margin-right: auto;
}

The client class (SuperClient) is little more than a trigger to call a class to process the superglobals. However, the client has no superglobals itself. This is significant in that SuperClient.php is called by the HTML document (DataEntry.html).

SuperClient.php


include_once('SuperGlobal.php');
 
class SuperClient
{  
    private $superGlobal;
 
    public function __construct()
    {
        $this->superGlobal = new SuperGlobal();
    }
}
$worker=new SuperClient();
?>

So the question is,

Will the super global $_POST be accessible to the SuperGlobal class called by the client?

Let’s see.

SuperGlobal.php


class SuperGlobal
{  
    private $favoriteTeam;
    private $favoriteSport;
 
    public function __construct()
    {
        $this->favoriteTeam = $_POST['team'];
        $this->favoriteSport = $_POST['sport'];
        echo "Minha equipe favorita é $this->favoriteTeam. 
"
; echo "Meu esporte favorito é $this->favoriteSport.
"
; } } ?>

When you run the program, your output will look something like the following:

    Minha equipe favorita é Chargers.
    Meu esporte favorito é football.

That shows that a superglobal can be accessed from even the most encapsulated environment. In the sense that the HTML Document called the SuperClient and yet the superglobals were available in the SuperGlobal object should tell you (and show you) that once launched from an HTML document a superglobal can be accessed from any PHP file communicating directly or indirectly with the originating HTML document.

Can Superglobals Cause Global Trouble?

For superglobals to be a problem, they need to change unexpectedly within a program.

So the first question, we need to ask is, Can superglobals be changed once they are sent from an HTML document?

We showed that superglobals can get inside an encapsulated object, but can they be changed or do they maintain the values set by the HTML document? The following is a test to find out. With a slight change to the SuperGlobal class and a couple more objects, we can find out.

Step 1: Change the SuperGlobal class to the following:

SuperGlobal.php


//Include new class
include_once('GlobalChanger.php');
 
class SuperGlobal
{  
    private $favoriteTeam;
    private $favoriteSport;
 
    public function __construct()
    {
        $this->favoriteTeam = $_POST['team'];
        $this->favoriteSport = $_POST['sport'];
        echo "Minha equipe favorita é $this->favoriteTeam. 
"
; echo "Meu esporte favorito é $this->favoriteSport.
"
;   //Add a new line $caller = new GlobalChanger(); } } ?>

Step 2: We need a class to change the values of the superglobals and call another object to display the changes in the same super global.

My friend Sudhir Kumar at PandaWeb.in from Chennai, India is a cricket fan; so I decided to use his favorite team and sport to replace whatever team and sport is entered.

GlobalChanger.php


include_once('SuperChanged.php');
 
class GlobalChanger
{   
    public function __construct()
    {
        $_POST['team']="Team India";
        $_POST['sport']= "cricket";
        $caller = new SuperChanged();
    }  
}
?>

Step 3: Finally, we need to see if the new team and sport has been changed in the application.

SuperChanged.php


class SuperChanged
{  
    private $newTeam;
    private $newSport;
 
    public function __construct()
    {
        $this->newTeam=$_POST['team'];
        $this->newSport=$_POST['sport'];
 
        echo "
Now my favorite team is $this->newTeam.
"
; echo "And my very favorite sport is $this->newSport.
"
; } } ?>

Starting with the same html document initially used, we can now see that indeed the superglobal values have been changed, and they are quite available throughout the program.

    Minha equipe favorita é Chargers.
    Meu esporte favorito é football.

    Now my favorite team is Team India.
    And my very favorite sport is cricket.

As you can see, the GlobalChanger object changed the original values. Furthermore, it is clear that we were using the same superglobal array in the SuperChanged class when the $_POST values were passed to private variables and displayed using the echo statement.

Obviously, a PHP programmer cannot simply drop superglobals. Further, even though we can change their values, that doesn’t mean we should change them or even have an occasion to do so. But, we need to be aware of the problems with global variables. After all, superglobals are global variables, even in an encapsulated environment.

Conclusion

Two important points need to be emphasized here:

  1. Don’t use global variables.
  2. Where you have to use superglobals, don’t change their values dynamically in PHP.

Like everything else in programming there are exceptions, but remember that globals, while having a purpose, often loose that purpose in OOP programs and structured design patterns. When using superglobals, keep in mind that they are true globals and they can be changed, but only if the developer assigns them different values after they’ve been assigned values in HTML. As true globals, they can cause the same kinds of problems that any other globals can. So treat them more like constants, and let their originally assigned values from the HTML form stay put.