PHP OOP: Encapsulating & Communicating with JavaScript and HTML5

EncapDocCan We Talk?

The initial discussion of the Memento design pattern illustrated how a state could be saved in a different object than the one in which the state originated. A Caretaker object holds the saved state and when requested, it returns the state to the Originator, all without breaking encapsulation. A practical example of employing the Memento that comes to mind is where the user is looking through a list. As she goes through the list, she sees different items (flowers in this case) that she is considering. However, because it’s a long list, she cannot remember which one she likes; so she tags those she is considering. After going through the whole list (all of the different flowers), she can easily recall those that she had tagged–recall them from a Memento. Play the little app and download the source code before going further:
PlayDownload

Communicating with HTML and JavaScript

Working HTML and JavaScript into PHP is no great shakes, and most PHP developers probably have done so at one time or another. However, most of the time I find myself creating horrible mixes of code for a one-off use with nothing encapsulated. The goal here is to see how everything in the application can be encapsulated and at the same time communicate. The purpose here is to find a single state variable that is used by HTML, JavaScript and PHP. Further, that state must be available for placing into a Memento object and stored for later use. (This post simply examines one way to encapsulate everything and have them communicate; however, material from this post will be used in developing a Memento example in a future post.) Also, I wanted to import all of the JavaScript and CSS separately. Figure 1 shows the general plan. (The ‘gardner’ folder contains the flower JPEG images.)

Figure 1: Encapsulating JavaScript, CSS and HTML into EncapDoc PHP class

Figure 1: Encapsulating JavaScript, CSS and HTML into EncapDoc PHP class

The CSS is just the stylesheet and it contained no functionality that you often find when it is used in conjunction with jQuery. I needed the JavaScript for clicking through the images. Had I swapped images using PHP I’d probably have to reload an HTML page with every swap and that seem prohibitively expensive. So I wrote the most simple JavaScript swap program I could think of with two functions for swapping and an added JavaScript function to get the initial starting picture (an integer value) passed from PHP. The following JavaScript listings shows how simple the script is:

The following listing is saved in the file, flowers.js.

?View Code JAVASCRIPT
//Strings for image url
var head="gardener/flower";
var tail =".jpg";
//JavaScript value 'n' initialized
var n;
 
//Moves to higher value 'n' in img element
function pictureNext()
{
    if(n<=9)
    {
	n++;
    }
    document.getElementById("flowerPot").src=head + n + tail;
}
 
//Moves to lower value 'n'
function pictureBack()
{
    if(n>=2)
    {
	n--;
    }
    document.getElementById("flowerPot").src=head + n + tail;
}
 
//Initial 'n' value from PHP via HTML5 element
function startHere()
{
    n=document.getElementsByName("starter")[0].value;
}

The pictureNext() and pictureBack() functions are for clicking through the flower images without reloading the HTML document. All of this is done by changing the variable ‘n‘. It represents the current state of the images. The images are named flower1.jpg to flower10.jpg. (You could probably accomplish the same thing a lot easier using an array, but I wanted to keep everything pretty basic.) The startHere() function is to communicate with PHP through an HTML element, a hidden input text box. To see how this works; consider the following story:

Sasha wants to meet Catarina. However, Catarina’s father forbids Sasha to contact his daughter; so Sasha leaves a note with Catarina’s best friend, Ambu. He tells her not to read the note or change it in anyway. Everyone knows that Ambu can be trusted, and she holds the note until Catarina asks for it.

In this story

  • Sasha is PHP
  • Ambu is HTML
  • Catarina is JavaScript

So in looking at the same story (given the encapsulated nature of the elements), it can be told again as it relates to element communication within an object:

A Client requests PHP to pass a value to JavaScript. However, PHP cannot directly communicate with JavaScript; so it places a value in an HTML element, named ‘starter’. When the page loads, JavaScript gets the message from ‘starter’ and uses it to navigate to the next or previous image in the numbered sequence of images.

As noted at the outset, everything needs to be encapsulated; so now we turn to the objects containing the encapsulated objects.

Encapsulate or Die!

Relax, no one’s going to die in this post. Encapsulating HTML and JavaScript is as simple as placing them inside of a private property.

Private visibility is the easiest way to encapsulate a property or method

The trick is setting them and getting them. In this case I used a public setter that is made by a Client class. The setter passes the value to a private property. The getter method is private and returns a private property. Likewise, the HTML page is created using a heredoc string and placed into a private property.

 <?php
class EncapDoc
{
	//Encapsulated properties
	private $imgNum;
	private $pageNow;
 
	public function getPage()
	{
		//HEREDOC string 
		$this->pageNow=<<<ENCAPHTML
		<!doctype html>
		<html>
		<head>
		<meta charset="UTF-8">
		<!--JavaScript link-->
		<script src="flowers.js"></script>
		<!--CSS link-->
		<link rel="stylesheet" type="text/css" href="flowers.css" >
		<title>FlowerShow</title>
		</head>
 
		<!--JavaScript method 'starterHere()' loads value from 'starter' element-->
		<body onload="startHere()">
 
		<!--Store PHP value in 'starter' element-->
		<input type="hidden" name="starter" value={$this->numGetter()}>
 
		<h2>Flower Picker</h2>
		<img id="flowerPot" width="300" height="400" src={$this->getImage()}></img>
		<p>
			<input type="button" id="back" value="Back" onclick="pictureBack()">
			<input type="button" id="next" value="Next" onclick="pictureNext()">
		</p>
		<p/>Spring Flowers & Blossoms
		</body>
		</html>
ENCAPHTML;
	//Send the page back to the client
	return $this->pageNow;
	}
 
	//Client sets value
	public function imageSetter($n)
	{
		$this->imgNum=$n;
	}
 
	//Encapsulated method for getting image number
	private function numGetter()
	{
		return $this->imgNum;
	}
 
	//Encapsulated method for initial image display
	private function getImage()
	{
		$head="gardener/flower";
		$tail=".jpg";
		//Get the content for the page
		$pix=$head . $this->numGetter() . $tail;
		return $pix;	
	}
}
?>

The JavaScript is encapsulated along with the HTML in the private property $pageNow. I found that importing the JavaScript from an external file made communication between JavaScript and PHP more difficult. Had it been part of the heredoc string (ENCAPHTML) rather than imported, PHP properties and method could be placed directly in the code, as it was with the HTML.

At this point in time, I use a numeric literal in the Client class for setting the the value in an EncapDoc object. The purpose is more to illustrate passing values between a PHP object and JavaScript/HTML elements within the object than anything else at this point. As you can see in the Client class, the request is made through the imageSetter(n) method:

<?php
error_reporting(E_ALL | E_STRICT);
ini_set("display_errors", 1);
function __autoload($class_name) 
{
    include $class_name . '.php';
}
class Client
{
    //constructor function
    public function __construct()
    {
       $flower=new EncapDoc();
       $flower->imageSetter(5);
       echo $flower->getPage();
    } 
}
$worker=new Client();
?>

After setting what image will appear first (effectively passing an ‘n’ value to be used by JavaScript), the HTML page, encapsulated in the EncapDoc() object named $flower, is retrieved and sent to the screen using an echo statement.

Getting Data from JavaScript passed to PHP

Before we can create a PHP Memento design pattern, we need to have a way to get data passed from JavaScript to PHP without breaking encapsulation. That task will be covered in the next post. As you have seen, PHP can pass data in an encapsulated context to JavaScript. In large part, that was because JavaScript had a function that pulled data from an HTML element. How can we go the other way and pass values store in JavaScript back to PHP to be placed in a Memento object and stored in a Caretaker object? As always, I would be very interested in hearing any ideas you have.

Share

Copyright © 2014 William Sanders. All Rights Reserved.

0 Responses to “PHP OOP: Encapsulating & Communicating with JavaScript and HTML5”


  • No Comments

Leave a Reply