Tag Archive for 'CMS'

Sandlight CMS III: PHP Abstract Factory

abfacNote: This is the third in a series for developing a CMS for Sandlight Productions. Drop by the Sandlight site to see the progress so far, and be sure to check your country’s flag count!

Now that the CMS has a filter for different devices, it now needs a pattern to take care of those devices and different types of content that they will display. Previous posts on this blog used the Bridge pattern and the Factory Method pattern. However, another pattern might be more useful for all of the different things that a Content Management System (CMS) might do. A review of the series of posts on this blog for how to select a design pattern, shows the different criteria to consider. The CMS has to create different elements of a Web page for different devices and that fact must be the focal point of the consideration. The section head for Creational Patterns in Learning PHP Design Patterns, lists the Abstract Factory pattern as a creational one, but that pattern was not discussed in the book nor on this blog. It would appear to be just what this CMS needs.

The Abstract Factory Design Pattern

The Abstract Factory pattern has features for families of factories and products instead of individual factories as does the Factory Method pattern. In comparing the relatively simple Factory Method pattern with the Abstract Factory, the Abstract Factory has multiple abstract product interfaces with multiple concrete factories for the families of the products.

Figure 1 shows the the Abstract Factory class diagram, and when you look at it, try to focus on the fact that the pattern has two types of interfaces: Factory and Product. So, if you understand the Factory Method pattern, you have a starting point for appreciating the Abstract Factory:

Figure 1: Abstract Factory class diagram

Figure 1: Abstract Factory class diagram

Unlike the Factory Method pattern, the Abstract Factory includes a Client class as an integral part of the pattern. Further, the Client holds an association between both the AbstractFactory (AbsFactory) and the two AbstractProduct classes. So while it shares some of the basic Factory Method characteristics, it is clearly a different pattern than the Factory Method.

Since the Abstract Factory may appear to be daunting, the color-coded the product instantiations (dashed lines) in the file diagram (appearing in the Play window) help show where each concrete factory method calls. Experiment with different combinations of factories (devices) and products (page parts) and look at the diagram so that you can see the path. Phone instantiations are in green, Tablet in red, and Desktop in blue. Experiment with the different single products first, and then click the bottom button to see what different “pages” each device factory displays.

Implementing the Abstract Factory in PHP

To see how this implementation of the Abstract Factory design pattern works, click the Play button. You will see both the interactive Abstract Pattern tester and the of the file diagram of this implementation of the Abstract Factory for the evolving Sandlight CMS. Click the Download button to see all of the files in the diagram. For this particular post, downloading all of the files is more important than usual because there are lots of them, and rather than having listings for all in this write-up, I’ve just selected representative ones.
PlayDownload

In addition to the Abstract Factory file diagram (viewed when you click the Play button), the following quick overview of the participants’ roles and how the CMS implements the Abstract Factory explain how this implementation works:

Client client: Only uses interfaces declared by IAbFactory (interface) and IProducts (abstract classes IHeaderProduct, IImageProduct and ITextProduct.) This means that the Client can only use the classes and methods implemented from those two interface types—factory or products. In other words, it should not directly implement a product (a page element) by directly using a product independent of the factory and product interfaces. Figure 2 illustrates this point:

Figure 2: Client works through Abstract Factory implementations

Figure 2: Client works through Abstract Factory implementations

In going over the other participants below, keep in mind that the Client can only implement concrete implementations of the IAbFactory to request products (page parts for different devices.)

IAbFactory interface: Establishes the methods for the concrete factories.

  • PhoneFactory implements operations to create phone products
  • TabletFactory implements operations to create tablet products
  • DesktopFactory implements operations to create desktop products

IHeaderProduct: abstract class Establishes the method for concrete header products and adds protected property for returning completed product.

  • PhoneHeader defines phone object to be created by the PhoneFactory and
    implements the IHeaderProduct interface
  • TabletHeader defines tablet object to be created by the Tabletactory and
    implements the IHeaderProduct interface
  • DesktopHeader defines desktop object to be created by the DesktopFactory and
    implements the IHeaderProduct interface

IImageProduct: abstract class Establishes the method for concrete image and/or video products and adds protected property for returning completed product.

  • PhoneImage defines phone object to be created by the PhoneFactory and
    implements the IImageProduct interface
  • TabletImage defines tablet object to be created by the Tabletactory and
    implements the IImageProduct interface
  • DesktopImage defines desktop object to be created by the DesktopFactory and
    implements the IImageProduct interface

ITextProduct: abstract class Establishes the method for concrete text products and adds protected property for returning completed product.

  • PhoneText defines phone object to be created by the PhoneFactory and
    implements the ITextProduct interface
  • TabletText defines tablet object to be created by the Tabletactory and
    implements the ITextProduct interface
  • DesktopText defines desktop object to be created by the DesktopFactory and
    implements the ITextProduct interface

Comparing the above outline with the Abstract Factory file diagram (seen when you click the Play button) shows that the Abstract Factory is bound to the idea of a factory implementing a product. The specific classes (products) requested are never directly referenced by the Client; rather it is through a factory. The CMS application requires factories for the different device categories; Phone, Tablet and Desktop. Each factory should be able to build the necessary parts (products) for each device. In this case (and for this example) the products are a Header, Graphic and Text. Each factory can build its own version of the products; so requesting a header, for example, is through a concrete factory, and depending on which concrete factory the clients requests, it builds the appropriate product.
Continue reading ‘Sandlight CMS III: PHP Abstract Factory’

Share

PHP CMS Project Part IV: La Petite Blog

cms4Bring in the MySql

At this stage there is still no design pattern in the project. You will see that re-use is starting to creep in, and we’re getting to the point where some decisions can be made about what design pattern would best fit this project. In Part V, you will see how a design pattern pulls everything together and why one is helpful to PHP programming.

In Part III of this series, you saw how external data from text files can be placed into an array and used by the DocHere class to populate a web page. In this installment, the same process shows how this can be done using data from a MySql database.

From Data Input to Web Page Display

The whole point of a CMS is to make updating a web site or blog easy. For the time being, I’m going to treat the web page example as a little blog–La Petite Blog. Figures 1 and 2 show how the data are to be entered and the end result pulled out of a database and displayed in the web page.

Figure 1: HTML form to send data to MySql database

Figure 1: HTML form to send data to MySql database

Figure 1 shows that the same categories of data used throughout the project are still in use. Even the CSS file is the same. The form is a simple HTML5 one. (Click View Code to see listing.)

< !doctype html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="heredoc.css"/>
    <meta charset="UTF-8"/>
    <title>Blogette Data Entry</title>
</head>
<body>
<h1>La Petite Blog</h1>
<h2>&nbsp;Enter data to update your blogette</h2>
<div>
    <form name = "content" action="InsertBlog.php" method="post">
        <input type="text" name="css" value="heredoc.css"/>&nbsp;CSS file
        <input type="text" name="title" />&nbsp;Title
        <input type="text" name="header1" />&nbsp;Header 1
        <input type="text" name="header2" />&nbsp;Header 2
        <textarea rows="5" cols="80" name="body1" >&nbsp;Add body text here</textarea>
        <textarea rows="5" cols="80" name="body2" >&nbsp;Add body text here</textarea>
        <input type="text" name="image1" />&nbsp;Image 1 file name
        <input type="text" name="image2"/>&nbsp;Image 2 file name
        <input type="text" name="caption1" />&nbsp;Caption for Image 1
        <input type="text" name="caption2"/>&nbsp;Caption for Image 2
        <input type="submit" value="Store data"/>
    </form>
</div>
</body>
</html>

The “entry” for the system is the class RetrieveBlog. It is almost identical to the Content class in Part III, and it generates the required results as shown in Figure 2.

Figure 2: Page content from database.

Figure 2: Page content from database.

Getting from the HTML5 data input to the PHP-generated web page takes a bit of doing, and so to get started, download the necessary files:
Download

From Data Input to Web View

The whole point of a CMS is to regularly update a web page easily. By the end of this stage, the only thing you’ll need with an FTP client for is to upload graphics. (Uploading graphic files from a web page using PHP is handled up an upcoming post apart from this series.) For now, though, you will be able to update all text in a web page as well as graphics are have already been placed in an image folder. Here’s what we’ll need:

  1. An HTML form for data entry (see above)
  2. A PHP class to create a MySQL Table to store data
  3. A PHP class to take the data from the HTML form and store it in the MySQL table
  4. A PHP class to retrieve the data from the and make it available to the web page

We’ll start with the table.
Continue reading ‘PHP CMS Project Part IV: La Petite Blog’

Share

A PHP CMS Project: Part I

cmsWeb Pages in Classes

One of the more difficult styles of programming for me that most PHP programmers use is mixing in HTML and PHP. It certainly gets the job done, and for most that’s all that counts. However, with certain types of projects, mixing HTML is difficult to maintain and re-use. So, I thought that a good starting point for making a CMS is using a HEREDOC string inside a class. Once the basic structure is in place, data could be updated using external data without having to change the basic structure of a Web page or re-writing the HTML. Figure 1 shows the final results of an HTML page created with a PHP class. The “external data” at this point is “stored” in a class method. The page is very simple based on a typical Web page with headers, body text and captioned images. Figure 1 shows the results:

Figure 1: Page with data added

Figure 1: Page with data added

To get an idea of how to use this, and see it live on a Web page use these buttons to play it and download the files:
PlayDownload

(Depending on what you’re using to view this page, the two images are going to be more or less distanced from one another in the browser. You can jiggle the CSS to make any adjustments you want, but I just re-sized the browser. Likewise, the two header fonts may need some adjustment as well since I downloaded two non-standard art deco fonts.)

HEREDOC: A Web Page in a String in a Class

The first thing I did was to use PHP’s HEREDOC syntax. (You can find out about using HEREDOC in the manual.) I’ve come to reference HEREDOC in all caps since after the <<< operator the HEREDOC name is in all caps. Essentially, this approach places the entire Web page in a string. You have to be careful when using HEREDOC to place the closing HEREDOC name on the far left of the script with nothing more than a semi-colon after it.

You may be thinking that such an approach is very limiting because the entire Web page is contained within a single string. However, the Web page in the HEREDOC string is actually a template for what you may want to add. Just like using an external link to get your CSS, all of the content for the page is from external sources. In this initial example, the “external” source is simple a private method (getContent()) within the DocHere class as can be seen in the following listing:

//DocHere.php
<?php
class DocHere
{
    private $document;
    private $css;
    private $title;
    private $header1;
    private $header2;
    private $header3;
    private $body1;
    private $image1;
    private $image2;
    private $caption1;
    private $caption2;
 
    function __construct()
    {
        $this->getContent();
        $this->document = <<<CMSTEMPLATE
        <!DOCTYPE html>
        <html>
        <head>
        <link rel="stylesheet" type="text/css" href=$this->css>
        <meta charset="UTF-8">
        <title>$this->title</title>
        </head>
        <body>
        <header>
            <h1>$this->header1</h1>
        </header>
            <article>
                <header>
                <h2>$this->header2</h2>
                </header>
                $this->body1
                <section class="doRight" >
                    <img src=$this->image1>
                    <caption ><span class="pixcaption">$this->caption1</span> </caption>
                </section>
                <section class="doLeft">
                    <img src=$this->image2>
                    <caption><span class="pixcaption">$this->caption2 </span> </caption>
                </section>
            </article>
        </body>
        </html>
 
CMSTEMPLATE;
    echo $this->document;
    }
 
    private function getContent()
    {
        $this->css = "heredoc.css";
        $this->title = "Here's Doc!";
        $this->header1 = "The Main Section";
        $this->header2 = "This is a Section Header";
        $this->body1 = "<p>Here is whatever has to be said, thought, discussed or just chatter.";
        $this->body1 .= " You can tell the reader as much or as little as you like.</p>";
        $this->image1 = "images/rose.png";
        $this->caption1="<br /> Lady with flowers and the moon.<br /> ";
        $this->image2 = "images/poland.png";
        $this->caption2="<br /> I really want to visit Poland.<br /> ";
 
    }
}
?>

In looking at the class, think of it in three parts:

  1. Set of variables declared for use in the Web page
  2. The HEREDOC string containing the Web page template
  3. Content for the page

By placing all of the variables in a private visibility, you can quickly and easily encapsulate data that actually goes into the Web page. The variables provide a clear outline of what is available to change in the page. Keeping in mind that his is a Web page to be updated with external data, the private visibility helps to limit what kind of external data gets to be on the page. (It must be assigned to a private variable through some kind of public access.)

The HEREDOC string just makes it easy to drop in a Web page without a lot of string concatenation. In fact, you can create and test a standard HTML page and copy and paste it into the HEREDOC variable ($document.) Just remember to replace the content with the set of private variables.

Finally, the getContent() method is just a place-holder for whatever kind of data resource you want to use. As we develop this into a useful CMS application, we will want to keep in mind the decomposition process where we keep all of the parts separate and simple.

Finishing Touches

Before finishing up this first part, take a look at an external data source used in the program: the CSS file.

@charset "UTF-8";
/* heredoc.css */
/* CSS Document */
/*468966,FFF0A5,FFB03B,B64926,8E2800 */
body {
	background-color: #FFF0A5;
	color: #8E2800;
	font-family: Georgia, "Times New Roman", Times, serif;
}
h1 {
	font-family: "Raconteur NF", futura, fantasy;
	background-color: #468966;
	color: #FFB03B;
	text-align: center;
}
h2 {
	font-family: NITECLUB, fantasy;
	color: #468966;
}
.pixcaption {
	font-style: italic;
	font-size: 11px;
	color: #B64926;
}
.doRight {
	float: right;
	padding-left: 10px;
}
.doLeft {
	float: left;
	padding-right: 10px;
}

As noted, the CSS style sheet is simple, and you may want to make adjustments to your own taste or requirements in an external style sheet. If you use jQuery tools in your HTML pages, you will find that they can fit in the current format quite easily.

A little trigger script launches the DocHere object (class):

<?php
//calldoc.php
include_once('DocHere.php');
$worker = new DocHere();
?>

The external trigger script is a temporary stand-in for a Client class to be developed later for making specific requests. Be sure to place the calldoc.php file in the same directory as the DocHere.php file.

External Data Options

In developing a CMS, even a simple one such as the one in this series of posts, you need to begin thinking about how data are to be updated. In the next installment in this series, we’ll try out some externally supplied data and start thinking about what kind of design pattern would help to maintain a Web site through a PHP CMS.

Share