SlideShare a Scribd company logo
Learning Php Design Patterns William Sanders
download
https://ebookbell.com/product/learning-php-design-patterns-
william-sanders-4068572
Explore and download more ebooks at ebookbell.com
Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Learning Php Design Patterns William Sanders
https://ebookbell.com/product/learning-php-design-patterns-william-
sanders-52557034
Learning Php Design Patterns 1st Ed Sanders William B
https://ebookbell.com/product/learning-php-design-patterns-1st-ed-
sanders-william-b-11939214
Learning Php Mysql Javascript Css Html5 A Stepbystep Guide To Creating
Dynamic Websites Robin Nixon
https://ebookbell.com/product/learning-php-mysql-javascript-css-
html5-a-stepbystep-guide-to-creating-dynamic-websites-robin-
nixon-50195330
Learning Php Mysql Javascript 7th Edition Early Release Robin Nixon
https://ebookbell.com/product/learning-php-mysql-javascript-7th-
edition-early-release-robin-nixon-54117148
Learning Php Mysql Stepbystep Guide To Creating Databasedriven Web
Sites Second Edition Michele E Davis
https://ebookbell.com/product/learning-php-mysql-stepbystep-guide-to-
creating-databasedriven-web-sites-second-edition-michele-e-
davis-2411356
Learning Php Mysql Javascript Early Release 6th Edition Robin Nixon
https://ebookbell.com/product/learning-php-mysql-javascript-early-
release-6th-edition-robin-nixon-24129590
Learning Php Mysql And Javascript 1st Edition Robin Nixon
https://ebookbell.com/product/learning-php-mysql-and-javascript-1st-
edition-robin-nixon-2503448
Learning Php Mysql Javascript And Css 2nd Edition Robin Nixon
https://ebookbell.com/product/learning-php-mysql-javascript-and-
css-2nd-edition-robin-nixon-2618790
Learning Php Mysql Javascript A Stepbystep Guide To Creating Dynamic
Websites 6th Edition Robin Nixon
https://ebookbell.com/product/learning-php-mysql-javascript-a-
stepbystep-guide-to-creating-dynamic-websites-6th-edition-robin-
nixon-34241976
Learning Php Design Patterns William Sanders
Learning Php Design Patterns William Sanders
Learning Php Design Patterns William Sanders
William Sanders
Learning PHP Design Patterns
ISBN: 978-1-449-34491-7
[LSI]
Learning PHP Design Patterns
by William Sanders
Copyright © 2013 William B. Sanders. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are
alsoavailableformosttitles(http://my.safaribooksonline.com).Formoreinformation,contactourcorporate/
institutional sales department: 800-998-9938 or corporate@oreilly.com.
Editors: Maria Gulick and Rachel Roumeliotis
Production Editor: Melanie Yarbrough
Copyeditor: Jasmine Kwityn
Proofreader: Becca Freed
Indexer: Fred Brown
Cover Designer: Karen Montgomery
Interior Designer: David Futato
Illustrator: Rebecca Demarest
February 2013: First Edition
Revision History for the First Edition:
2013-02-08 First release
See http://oreilly.com/catalog/errata.csp?isbn=9781449344917 for release details.
Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly
Media, Inc. Learning PHP Design Patterns, the cover image of an Alaska plaice, and related trade dress are
trademarks of O’Reilly Media, Inc.
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as
trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trade‐
mark claim, the designations have been printed in caps or initial caps.
While every precaution has been taken in the preparation of this book, the publisher and author assume no
responsibility for errors or omissions, or for damages resulting from the use of the information contained
herein.
In memory of my father, William B. Sanders (1917–2012).
Learning Php Design Patterns William Sanders
Table of Contents
Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Part I. Easing into the Fundamentals of Design Patterns
1. PHP and Object-Oriented Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Entering into Intermediate and Advanced Programming 5
Why Object-Oriented Programming? 6
Making Problem Solving Easier 6
Modularization 7
Classes and Objects 8
Single Responsibility Principle 8
Constructor Functions in PHP 9
The Client as a Requester Class 9
What About Speed? 13
The Speed of Development and Change 13
The Speed of Teams 14
What’s Wrong with Sequential and Procedural Programming? 14
Sequential Programming 14
Procedural Programming 15
Pay Me Now or Pay Me Later 16
2. Basic Concepts in OOP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Abstraction 19
Abstract Classes 20
Abstract Properties and Methods 22
Interfaces 23
Interfaces and Constants 25
Type Hinting: Almost Data Typing 26
Encapsulation 29
v
Everyday Encapsulation 29
Protecting Encapsulation through Visibility 30
Getters and Setters 33
Inheritance 34
Polymorphism 36
One Name with Many Implementations 38
Built-In Polymorphism in Design Patterns 39
Easy Does It 39
3. Basic Design Pattern Concepts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
The MVC Loosens and Refocuses Programming 41
Basic Principles of Design Patterns 43
The First Design Pattern Principle 44
Using Interface Data Types in Code Hinting 45
Abstract Classes and Their Interfaces 46
The Second Design Pattern Principle 49
Basic Composition Using a Client 49
Delegation: The IS-A and HAS-A Difference 53
Design Patterns as a Big Cheat Sheet 54
Organization of Design Patterns 54
Choosing a Design Pattern 55
What Causes Redesign? 55
What Varies? 56
What Is the Difference Between Design Patterns and Frameworks? 57
4. Using UMLs with Design Patterns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Why Unified Modeling Language (UML)? 59
Class Diagrams 60
Participant Symbols 61
Relationship Notations 63
Acquaintance Relations 64
Aggregation Relationship 66
Inheritance and Implementation Relations 68
Creates Relations 70
Multiple Relations 71
Object Diagrams 72
Interaction Diagrams 73
The Role of Diagrams and Notations in Object-Oriented Programming 74
Tools for UMLs 75
vi | Table of Contents
Other UMLs 75
Part II. Creational Design Patterns
5. Factory Method Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
What Is the Factory Method Pattern? 79
When to Use the Factory Method 80
A Minimalist Example 81
Factory Work 81
The Client 84
Accommodating Class Changes 85
Adding Graphic Elements 85
Coordinating Products 87
Changing the Text Product 88
Changing the Graphic Product 89
Adding New Products and Parameterized Requests 89
One Factory and Multiple Products 90
The New Factories 91
The New Products 92
The Client with Parameters 94
Helper Classes 94
File Diagram 96
Product Changes: Leave the Interface Alone! 96
6. Prototype Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
What Is the Prototype Design Pattern? 99
When to Use the Prototype Pattern 100
The Clone Function 101
Constructor Does Not Relaunch with Clone 102
The Constructor Function Should Do No Real Work 103
A Minimalist Prototype Example 104
Studying Fruit Flies 104
Adding OOP to the Prototype 108
The Modern Business Organization 108
Encapsulation in the Interface 109
The Interface Implementations 110
The Organizational Client 113
Making Changes, Adding Features 116
Dynamic Object Instantiation 117
Table of Contents | vii
The Prototype in PHP Land 119
Part III. Structural Design Patterns
7. The Adapter Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
What Is the Adapter Pattern? 123
When to Use the Adapter Pattern 125
The Adapter Pattern Using Inheritance 126
A Minimal Example of a Class Adapter: The Currency Exchange 127
The Adapter Pattern Using Composition 131
From Desktop to Mobile 131
Adapters and Change 140
8. Decorator Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
What Is the Decorator Pattern? 141
When to Use the Decorator Pattern 142
Minimalist Decorator 143
The Component Interface 143
The Decorator Interface 144
Concrete Component 145
Concrete Decorators 146
The Client 148
What About Wrappers? 149
Primitives in Wrappers 149
Built-in Wrappers in PHP 150
Design Pattern Wrappers 151
Decorators with Multiple Components 151
Multiple Concrete Components 152
Concrete Decorators with Multiple States and Values 152
The Developer Dating Service 152
HTML User Interface (UI) 159
The Client Class Passing HTML Data 163
From a Variable Name to an Object Instance 164
Adding a Decoration 165
Part IV. Behavioral Design Patterns
9. The Template Method Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
What Is the Template Method Pattern? 169
When to Use the Template Method 170
Using the Template Method with Images and Captions: A Minimal Example 171
viii | Table of Contents
The Abstract Class 171
The Concrete Class 172
The Client 172
The Hollywood Principle 174
Using the Template Method with Other Design Patterns 175
The Client’s Reduced Workload 176
The Template Method Participants 177
The Factory Method Participants 178
The Hook in the Template Method Design Pattern 181
Setting Up the Hook 184
Implementing the Hook 185
The Client and Tripping the Hook 185
The Small and Mighty Template Method 187
10. The State Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
What Is the State Pattern? 189
When to Use the State Pattern? 190
The State Machine 192
Light On, Light Off: The Minimal State Design Pattern 192
Context Is King 193
The States 196
The Client Request through the Context 197
Adding States 198
Changing the Interface 199
Changing the States 199
Updating the Context Class 202
An Updated Client 203
The Navigator: More Choices and Cells 205
Setting Up a Matrix Statechart 205
Setting Up the Interface 206
The Context 207
The States 209
The Client Picks a Path 215
The State Pattern and PHP 218
Part V. MySQL and PHP Design Patterns
11. A Universal Class for Connections and a Proxy Pattern for Security. . . . . . . . . . . . . . . . 221
A Simple Interface and Class for MySQL 221
The Pregnant Interface 222
Universal MySQL Connection Class and Static Variables 223
Table of Contents | ix
Easy Client 224
The Protection Proxy for Login 225
Setting Up Login Registration 226
Implementing the Login Proxy 230
The Proxy and Real-World Security 237
12. The Flexibility of the Strategy Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Encapsulating Algorithms 239
Differentiating the Strategy from the State Design Pattern 240
No Conditional Statements, Please 241
A Family of Algorithms 242
A Minimalist Strategy Pattern 242
The Client and the Trigger Scripts 244
The Context Class and Strategy Interface 247
The Concrete Strategies 248
Expanded Strategy Pattern with Data Security and Parameterized Algorithms 251
A Data Security Helper Class 251
Adding a Parameter to an Algorithm Method 254
The Survey Table 254
Data Entry Modules 256
The Client Calls for Help 261
The Minor but Major Change in Context Class 262
The Concrete Strategies 263
The Flexible Strategy Pattern 269
13. The Chain of Responsibility Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Passing the Buck 271
The Chain of Responsibility in a MySQL Help Desk 273
Building and Loading the Response Table 273
The Help Desk Chain of Responsibility 278
Automated Chain of Responsibility and Factory Method 284
The Chain of Responsibility and Date-Driven Requests 285
Factory Method Finishes Job 290
Ease of Update 295
14. Building a Multidevice CMS with the Observer Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . 297
Built-In Observer Interfaces 297
When to Use the Observer Pattern 298
Using SPL with the Observer Pattern 300
SplSubject 300
SplObserver 301
SplObjectStorage 301
x | Table of Contents
The SPL Concrete Subject 301
The SPL Concrete Observer 303
The SPL Client 304
Free Range PHP and the Observer Pattern 305
The Abstract Subject Class and ConcreteSubject Implementation 306
Observer and Multiple Concrete Observers 307
The Client 309
Making a Simple CMS 311
CMS Utilities 311
The Multiple Device Observer 316
Thinking OOP 330
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
Table of Contents | xi
Learning Php Design Patterns William Sanders
Preface
As PHP expands to become the server-side program of choice among a significant
portion of programmers, professional techniques and programming structures need to
be incorporated. Design patterns, a concept borrowed from The Timeless Way of Build‐
ing by Christopher Alexander (Oxford University Press), refers to a general reusable
solution to a commonly occurring problem within a given context. In everyday develop‐
ment work, PHP programmers encounter “commonly occurring problems” in a soft‐
ware development context, and the use of PHP design patterns is a set of solutions to
“commonly occurring” PHP programming problems. Pure and simple, PHP design
patterns are tools used to deal with the reality of professional software development.
They are not libraries or templates but rather more general structures that can be used
to solve problems. I like to think of design patterns in the same way as I do the loop
structure. The loop is used when some kind of iteration is required. True, there are other
ways to deal with iteration, but a loop is a flexible tool that saves time in the development
process. (Besides, it’s a lot neater than writing the same line of code 10,000 times!)
Further, I do not feel constrained by design patterns as “canned solutions” any more
than a loop is a “canned solution” to iteration. Besides, I can use the loop structure in a
varietyofwaysinPHPrangingfromfortowhilestatementsandeverythinginbetween.
Likewise, design patterns can be implemented in more than one way depending on the
exact nature of the problem being solved.
The most important reason for incorporating design patterns, though, is that they
provide solutions to complex problems. As one’s programs become larger, they almost
necessarily become more complex. In an object-oriented programming (OOP) envi‐
ronment, such complexity is reduced somewhat, as you are dealing with encapsulated
modules, whereas in sequential or procedural programming, any changes can bring the
program crashing down like a house of cards. Design patterns bring not only solutions
to general programming problems, but they also allow changes to be made in large
complex programs by providing loose coupling between objects. So when a change is
made, instead of having to start programming all over from scratch, you can just add
xiii
the necessary changes and everything keeps chugging along—even in large, complex
programs.
Further, design patterns are meant for reuse. After all, programmers reuse the same
algorithms all the time. Why not use larger structures as well? On the one hand, frame‐
works and templates serve to make reuse practical, but they are often too specific. That’s
where reuse of design-patterned PHP programs comes in, especially in the case of large,
complex programs. Because making changes is easy with design patterns, reuse for
specific problems of the same kind is easy as well. Reducing developmental time and
resourcessavesmoneyandbetterservesyourclients.Theygetwell-structuredprograms
thatdowhattheclientswant,they’reeasyforthedeveloperstochange(customersalways
want change!), and they have strong foundations that are not as likely to fail.
Audience
At some point, all good programmers realize that they need to get out of a sequential
and procedural programming rut. The next logical step is object-oriented program‐
ming, and moving into OOP requires a shift in perspective: instead of seeing program‐
ming as a series of statements, it must be seen as an interaction and communication
between objects. Beyond OOP lie design patterns, where OOP principles are recast into
patterns of reusable code. There you will find the tools of professional programmers.
Because design patterns for programming were developed in cooperation between aca‐
demics and businesses, the concepts both transcend single problems while at the same
time possessing business-like practicality. Learning PHP design patterns is for profes‐
sional programmers who want to optimize their own time in development and rede‐
velopment and provide their clients with high-quality code.
In no small measure, this book is for those who felt a certain delight when programming
was new to them. This is for the developer who thought nothing of working on a pro‐
gram all night long just because it was interesting, staggering off to bed, only to start on
another program as soon as he woke up. When programming is new and every day
promises a new discovery or a bug that challenges the developer to a fight to the death,
and you must use your mind in complex and exciting ways, the experience can be Zen-
like. If you’ve had that experience, you’ll know what I mean. It cannot be spelled out or
explained analytically. (I can’t even explain it to myself, and I have no idea why I enjoy
the kinds of challenges and rewards found in programming.)
Design patterns reintroduce mental challenges, and this book is not for someone who
is new either to PHP or to programming. If you’re learning PHP for the first time, take
a look at Robin Nixon’s book, Learning PHP, MySQL, JavaScript, and CSS, 2nd Edition
(O’Reilly) before tackling PHP design patterns. Likewise, this book (or any decent book
on design patterns) does not promise that you’ll master design patterns quickly and
easily. This kind of learning is a journey, and the wisest counsel is to learn to enjoy the
journey. It takes time and mental effort.
xiv | Preface
Assumptions This Book Makes
This book assumes that you know how to program in PHP and want to take your pro‐
gramming skills to the next couple of levels. In fact, it assumes that you’re a pretty good
PHP programmer and you’ve used MySQL and know how to develop HTML pages and
use CSS. It also assumes that you understand that learning PHP design patterns is not
going to happen in a lazy afternoon. Learning design patterns is akin to a gradual
metamorphosis.
Contents of This Book
This book is organized into five parts.
Part I is an OOP refresher/introduction:
Chapter 1 introduces object-oriented programming (OOP) and how to more easily
handle complex programming problems with modularization.
Chapter 2 discusses basic concepts in OOP such as abstraction, encapsulation, in‐
heritance, and polymorphism, as well as the PHP structures that implement these
concepts.
Chapter 3 moves on to examine the basic concepts in design patterns, their cate‐
gorization, and how specific patterns are selected to handle specific problems.
Chapter 4 introduces Unified Modeling Language (UML) and explains how it will
be employed in this book.
Part II covers creational design patterns:
Chapter 5 examines the Factory Method, which has a creational purpose and a class
scope. Examples include dynamically creating pages that display graphics, body
text, and header text.
Chapter 6 shows how to use the Prototype pattern, which has a creational purpose
and an object scope. The Prototype pattern is used when a single object is created
as a prototype and then cloned to economically create further instances.
Part III explains structural design patterns:
Chapter 7 illustrates how to use the Adapter pattern in both class and object scopes.
Examples show how to take an existing structure and make changes that allow the
developer to add new functionality.
Chapter 8 explains how an existing object can be changed without disrupting a
larger program using the Decorator pattern. You’ll see how to decorate male and
female dating objects with different preferences in a dating site.
Preface | xv
Part IV looks at behavioral design patterns:
Chapter9showshowtousetheTemplateMethodpattern—oneoftheeasiestdesign
patterns to both create and use. In addition, you will see how the famous Hollywood
Principle operates in design pattern programming. As a final feature of the chapter,
two different patterns are combined to solve a single problem.
Chapter 10 presents the State design pattern along with how to use statecharts to
map state processes and changes.
Part V introduces four more behavioral design patterns used in conjunction with
MySQL:
Chapter 11 provides the Universal connection class and the Proxy design pattern
for adding security to usernames and passwords stored in a MySQL database.
Chapter 12 explains how the Strategy design pattern is significantly different from
the State pattern even though they have identical class diagrams. A survey example
illustrates how the Strategy pattern can be used with different MySQL requests.
Chapter 13 has multiple examples of how the Chain of Responsibility pattern can
be used, ranging from a Help Desk to automatically responding to a date timer to
display (in conjunction with the Factory Method pattern) images and text.
Chapter 14 is the first to explore how to use the PHP built-in design pattern inter‐
faces. The Observer design pattern can use interfaces from the Standard PHP Li‐
brary.AnotherexampleusestheObserverdesignpatternwithhand-builtinterfaces
to make a simple content management system (CMS) with PHP and MySQL.
Conventions Used in This Book
The following typographical conventions are used in this book:
Italic
Indicates new terms, URLs, email addresses, filenames, and file extensions.
Constant width
Used for program listings, as well as within paragraphs to refer to program elements
such as variable or function names, databases, data types, environment variables,
statements, and keywords.
Constant width bold
Shows commands or other text that should be typed literally by the user.
Constant width italic
Shows text that should be replaced with user-supplied values or by values deter‐
mined by context.
xvi | Preface
This icon signifies a tip, suggestion, or general note.
This icon indicates a warning or caution.
Using Code Examples
This book is here to help you get your job done. In general, if this book includes code
examples, you may use the code in your programs and documentation. You do not need
to contact us for permission unless you’re reproducing a significant portion of the code.
For example, writing a program that uses several chunks of code from this book does
not require permission. Selling or distributing a CD-ROM of examples from O’Reilly
books does require permission. Answering a question by citing this book and quoting
example code does not require permission. Incorporating a significant amount of ex‐
ample code from this book into your product’s documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title,
author, publisher, and ISBN. For example: “Learning PHP Design Patterns by William
Sanders (O’Reilly). Copyright 2013 William B. Sanders, 978-1-449-34491-7.”
If you feel your use of code examples falls outside fair use or the permission given above,
feel free to contact us at permissions@oreilly.com.
Safari® Books Online
Safari Books Online (www.safaribooksonline.com) is an on-demand
digital library that delivers expert content in both book and video
form from the world’s leading authors in technology and business.
Technology professionals, software developers, web designers, and business and crea‐
tive professionals use Safari Books Online as their primary resource for research, prob‐
lem solving, learning, and certification training.
Safari Books Online offers a range of product mixes and pricing programs for organi‐
zations, government agencies, and individuals. Subscribers have access to thousands of
books, training videos, and prepublication manuscripts in one fully searchable database
from publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley
Professional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John
Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press,
FT Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course
Preface | xvii
Technology, and dozens more. For more information about Safari Books Online, please
visit us online.
How to Contact Us
Please address comments and questions concerning this book to the publisher:
O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (in the United States or Canada)
707-829-0515 (international or local)
707-829-0104 (fax)
We have a web page for this book, where we list errata, examples, and any additional
information. You can access this page at http://oreil.ly/php_design_patterns.
To comment or ask technical questions about this book, send email to bookques
tions@oreilly.com.
For more information about our books, courses, conferences, and news, see our website
at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia
Acknowledgments
I want to thank everyone who helped out in one way or another. My colleagues at the
University of Hartford’s Multimedia Web Design and Development program were al‐
ways helpful when I posed a query of one type or another. Professor John Gray, the
department chair, was encouraging and helpful as always. Dr. Brian Dorn, my office
next-door neighbor, who caught the bulk of my queries, was obliging, knowledgeable,
and patient.
I was fortunate enough to meet Michael Bourque of the Boston PHP group at the in‐
augural Northeast PHP Conference, and appreciate his encouragement for this project.
I look forward to working with Michael and the Boston PHP group more in exploring
advanced PHP programming.
O’Reilly Media provided three capable technical reviewers. Robin Nixon, author of
Learning PHP, MySQL & JavaScript, 2nd Edition (O’Reilly) offered corrections, sug‐
gestions, and several insights into PHP to make the code better in many different ways.
xviii | Preface
Aaron Saray, author of Professional PHP Design Patterns (Wrox) was incredibly detailed
and generous in his suggestions. He has a wonderful editor’s eye for even the slightest
flaw. Aaron and I take very different approaches to design patterns, but such differences
provide a wider view for PHP developers interested in design patterns. Finally, Dmitry
Sheiko acted as a passionate technical reviewer and has his own blog where his take on
PHP design patterns can be found.
Senior Editor Rachel Roumeliotis at O’Reilly Media put all of the many parts together
and moved the project along. Maria Gulick, another capable O’Reilly editor, took care
of the bits and pieces as the project went through revisions. Copyeditor Jasmine Kwityn
found and corrected details I did not know existed—in this galaxy or any other. The
whole process was initiated by Margot Maley Hutchison at Waterside Productions, and
I am grateful to her as ever.
My wife Delia was more understanding than most spouses since she recently had pub‐
lished a book of her own and knew the process. Our Greater Swiss Mountain Dog,
WillDe, could care less about writing processes. As long as he got his treats, he’d go
along with anything.
Preface | xix
Learning Php Design Patterns William Sanders
Allcompromiseisbasedongiveandtake,butthere
can be no give and take on fundamentals. Any
compromise on mere fundamentals is a surrender.
For it is all give and no take.
—Mahatma Gandhi
People talk fundamentals and superlatives and
then make some changes of detail.
—Oliver Wendell Holmes, Jr.
An unfortunate thing about this world is that the
good habits are much easier to give up than
the bad ones.
—W. Somerset Maugham
PART I
Easing into the Fundamentals of
Design Patterns
Programming Habits
For years after I started programming regularly, I developed certain habits that changed
from sequential to procedural programming and just cruised along on a combination
of those two for years. This was due in part to the explorations of different languages.
My first was Fortran II in college, then on to Basic, FORTH, PostScript, and then into
assembly and machine language. I was more interested in learning about different
languages than I was in good programming. Then with the Internet came Java,
JavaScript, PHP, C#, and ActionScript 3.0, among others. Most of these languages were
based (in part) on the kinds of structures found in C++. These were different languages,
but I maintained the same old habits.
Quite by accident, I was introduced to state machines by Dr. Jonathan Kaye. Instead of
thinking in terms of flow of control, he showed me how to think in terms of different
states. Following state machines, I discovered the State design pattern and then Design
Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard
Helm, Ralph Johnson, and John Vlissides (Addison-Wesley). The examples in Design
Patterns were all written in SmallTalk or C++. Knowing no SmallTalk and very little C
++, I was forced to concentrate on the conceptual materials. Oddly, that was one of the
best things that could have happened because I was not stuck with examples in any
particular language. When it came to PHP, it wasn’t a matter of translating from Small‐
Talk to PHP but applying object-oriented programming (OOP) and design pattern
concepts directly to PHP.
Slowly but surely, my programming habits began to change. By adding a little OOP here
and there and incorporating a design pattern now and again, in time, I didn’t want to
program any other way. According to psychologists, a habit is formed over a period of
66 days on average, but in my case, the change took longer and it was more gradual. It
was a very busy development period for me, and when the choice was between getting
aprojectdoneforacustomerandusingOOPanddesignpatterns,timepressuresalways
won out. However, more and more OOP was creeping in my habitual coding practices,
and before I knew it, my customers were getting solid OOP and design pattern-
developed applications. The four chapters in this first section are designed to get you
started on the OOP path:
• PHP and Object-Oriented Programming
• Basic Concepts in OOP
• Basic Design Pattern Concepts
• Using UMLs with Design Patterns
Focus on Substance, Not Style
Most of the good programmers I know have a certain style that points to professional
programming habits. By and large, when you encounter good OOP programming,
you’ll see a certain way of doing everything from naming variables to commenting code.
Variable names are clear, and comments in the code tell the story of the code so that
other programmers know how to connect to their own modules. In this book, the com‐
ments in the code have been kept to a minimum because that job is done by the book’s
text. Further, I have often found that putting in too many comments get in the way of
clearly seeing the structure of the code. So, with the goal of being able to see and sense
objects as complete entities, the code is not fractionalized by long-winded comments.
(In programs not written for books, I subscribe to the idea that substantive commenting
is essential.)
For some reason, PHP seems to be plagued by bad examples of design patterns. By bad,
I’m not talking about dumb examples. I’m referring to design patterns written with
missing parts. For example, a Strategy pattern written without a Context participant is
a bad example. It is simply inaccurate. The same is true for any pattern that has missing
parts. It’s like writing a loop that has no termination condition. The Strategy pattern
requires a Context just like a loop structure requires a termination condition.
In order to keep the focus as accurate as possible, I’ve used the original source of the
design patterns discussed in this book: Design Patterns: Elements of Reusable Object-
Oriented Software (Prentice Hall). Further, the Uniform Modeling Language (UML) is
the one used in Design Patterns. Newer versions of the UML (UML2) have come along
since then, but for learning PHP design patterns, and for understanding ones not dis‐
cussed in this book, learning to use the original will help if you want to learn additional
patterns from the original source.
Learning Php Design Patterns William Sanders
All the forces in the world are not so powerful as
an idea whose time has come.
—Victor Hugo
Do not pray for tasks equal to your powers. Pray
for powers equal to your tasks.
—Phillips Brooks
Immense power is acquired by assuring yourself in
your secret reveries that you were born to
control affairs.
—Andrew Carnegie
Ignorance is the curse of God; knowledge is the
wing wherewith we fly to heaven.
—William Shakespeare
CHAPTER 1
PHP and Object-Oriented Programming
Entering into Intermediate and Advanced Programming
When we first learn to read, the stories, vocabularies, and words tend to be small and
simple. Dealing with small and simple stories requires small and simple tools. However,
when we are more advanced and introduced to the works of William Shakespeare, we
need a more complex, larger, and more sophisticated toolset. If a kindergarten teacher
handed her brood Hamlet, chances are the kids wouldn’t understand it, but if they are
given an incremental set of reading tools over the years, by the time they reach high
school, they can read, understand, and appreciate Hamlet. This book is for developers
who are ready to read the PHP version of Hamlet.
To get what you need from this book, you need to begin with an understanding of and
experience with PHP. Other books in this series, Learning PHP 5 by David Sklar and
Learning PHP, MySQL, and JavaScript, 2nd Edition, by Robin Nixon (O’Reilly) are good
5
places to start if you have no PHP experience. Of course, you may have learned PHP
from any number of other books, courses, or online tutorials. What matters is that you
knowhowtoprograminPHP.Further,we’regoingtobedealingwithPHP5andnothing
earlier, like the last version of PHP 4 (PHP 4.4.9). That’s because just about everything
we need for object-oriented programming (OOP) wasn’t implemented until PHP 5.
Why Object-Oriented Programming?
Although OOP has been around for more than 40 years, it was not until the last 15 years
or so that it’s become more and more important. In large measure, this is due to the
influence of Java, which includes built-in OOP structures. Newer languages associated
with the Internet, such as JavaScript, ActionScript 3.0, and PHP 5, also have incorpo‐
rated OOP in style or structure. In 1998, JavaScript Objects by Alexander Nakhimovsky
and Tom Myers (Wrox), two Colgate University professors, showed that OOP could be
incorporated into JavaScript. So OOP is nothing new, even for those whose main pro‐
gramming has been in the realm of Internet languages, and we can even say that it is a
“tried and proven” method of programming in most languages designed to give in‐
structions to computers.
Spending some time understanding OOP is important because understanding design
patterns relies on understanding OOP. So while you may have substantial experience
programming in PHP 5, if you do not have OOP experience, spend some time in Part I.
Making Problem Solving Easier
Computer programs are designed to solve human problems. A process called dynamic
programming is a technique for breaking down larger problems into smaller ones. The
planistosolveeachsmallerproblemandthenputeverythingbacktogetherintoasingle,
larger solution. Take, for example, planning a trip to Timbuktu. (It doesn’t sound like a
complex problem, but see if you can find a flight from your town to Timbuktu on an
online travel site.) Let’s break it down:
1. Does Timbuktu (aka Tombouctou or Timbuctu) exist? (Yes./No.) Answer = Yes.
2. Does Timbuktu have an airport? (Yes./No.) Answer = Yes, Airport Identifier =
TOM.
3. Are there flights into TOM? (Yes./No.) Answer = Maybe. Flights are available from
both Bamako and Mopti, but Islamist rebels took control of Timbuktu as of July 1,
2012, and flights have been canceled until further notice.
4. Are hostile rebels in control of Timbuktu now? (Yes./No.) If answer = Yes, there are
no flights. If answer = No, there may be flights.
5. If flights are available, is Timbuktu safe for tourism or business? (Yes./No.)
Answer = No.
6 | Chapter 1: PHP and Object-Oriented Programming
6. ArevisasfrommycountryintoMali(countrywhereTimbuktuislocated)available?
(Yes./No.) Answer = Yes.
7. Are vaccinations required? (Yes./No.) Answer = Yes.
As you can see, getting to and from Timbuktu is a complex issue, but the list of simple
questions can all be answered by yes or no. Lots more questions would be included in
the list, but each can be answered in a binary fashion. The “maybe” answer means that
more questions need to be asked to get a yes/no answer.
Modularization
The process of decomposing a problem into small subproblems is the process of mod‐
ularization. Just like the complexities of getting from your home to Timbuktu can be
modularized into a set of yes/no steps, any other complex problem also can be modu‐
larized. Figure 1-1 illustrates this process.
Figure 1-1. Even the most complex problem can be broken into modules
Inlookingatmodularization,youmaybethinkingthatitdoesn’tlooktoodifficult.You’d
be absolutely right. The more complex the problem, the more it makes sense to mod‐
ularize it. So, the initial reasoning in OOP programming, far from being complex, sim‐
plifies the complex. Even the most daunting programming problem can be solved by
this divide-and-conquer strategy.
Why Object-Oriented Programming? | 7
Classes and Objects
Once a problem is modularized, what are you going to do with the modules? As you
saw,breakingdownacomplexproblemcantransformitintomanysimplesubproblems,
but you need a way to organize the modules and work with them in relation to each
other to handle the larger problem being solved. One way to look at a module is as a
collection of related functions. In programming, these modules are called classes.
A class itself is made up of parts called properties and methods. The properties are
different types of data objects like numbers, strings, nulls, and Booleans. Generally, the
data are stored as abstract data types known as variables, constants, and arrays. Meth‐
ods, on the other hand, are functions that operate on the data.
Single Responsibility Principle
One way to think of a class is as a collection of objects with common characteristics.
The “commonness” of characteristics does not mean that they are the same, but instead
they deal with the common problem assigned to the module—the class. Keeping in
mind that the purpose of a module is to solve some aspect of a more complex problem,
we arrive at one of the first principles of object-oriented programming: the single re‐
sponsibility principle, which states that a class should have only a single responsibility.
It’s not that a class cannot have multiple responsibilities, but keep in mind that we broke
down a complex problem into simple modules so that we’d have several easy-to-solve
problems. By limiting a class to a single responsibility, we not only remind ourselves of
why we modularized the problem, but we also have an easier way of organizing the
modules. Let’s look at a class with a single responsibility. Suppose you’re making a web‐
site for a client, and because the site is to be viewed by different devices ranging from
desktops to tablets to smartphones, you want to have some way of determining what
type of device and which browser is used to view your web page. With PHP, it’s easy to
write a class that provides that information using the built-in array $_SERVER and the
related element, HTTP_USER_AGENT. The TellAll class in the following listing demon‐
strates a class with a single responsibility—to provide information about the user agent
viewing the PHP page:
<?php
//Saved as TellAll.php
class TellAll
{
private $userAgent;
public function __construct()
{
$this->userAgent=$_SERVER['HTTP_USER_AGENT'];
echo $this->userAgent;
}
8 | Chapter 1: PHP and Object-Oriented Programming
}
$tellAll=new TellAll();
?>
Loading this class through a Safari browser on an iMac displays the following:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/ 534.57.2 (KHTML,
like Gecko) Version/5.1.7 Safari/534.57.2
When tested on an iPad using an Opera Mini browser, the results are different:
Opera/9.80 (iPad; Opera Mini/7.0.2/28.2051;U;en) Presto/2.8.119 Version/11.10
The class represents a module of a more complex operation, of which the class is only
asinglepart.LikeagoodclassinOOP,ithasasingleresponsibility—findinginformation
about the user agent.
Constructor Functions in PHP
A unique feature of PHP classes is the use of the __construct() statement as a con‐
structor function. Most computer languages use the name of the class as the constructor
function name; however, using the __construct() statement removes all doubt as to
the function’s purpose.
The constructor function in a class automatically launches as soon as the class is in‐
stantiated. In the TellAll class, the results are immediately printed to the screen,
whether you want them there or not. For demonstration purposes, that’s fine, but as a
module, other modules may simply want to use the information about the device and/
or the browser. So, as you will see, not all classes include a constructor function.
The Client as a Requester Class
In the TellAll class, I included a little trigger at the bottom to launch the class. With
the exception of the Client class, self-launching is not recommended. In your experi‐
ence with PHP, you most likely launched a PHP program from HTML using a form tag
something like the following:
<form action="dataMonster.php" method="post">
So, you’re familiar with launching a PHP file from an external source. Similarly, PHP
files containing classes should be used by other modules (classes) and not self-launched.
As we get more into design patterns, you’ll find a class named Client keeps appearing.
The Client has different roles in the larger project, but the primary one is to make
requests from the classes that make up the design pattern. Here, the Client is shown in
relation to a revised version of the TellAll class. This new class used by the Client is
different in several ways from TellAll that are more useful to an overall project and
The Client as a Requester Class | 9
reusable in other projects. The MobileSniffer class begins with the same user agent
information, but the class makes it available in more useful ways with its properties and
methods. Using a Unified Modeling Language (UML) diagram you can see that the
Client instantiates (dashed arrow) the MobileSniffer. Figure 1-2 illustrates a simple
class diagram of the two classes.
Figure 1-2. Client class instantiates MobileSniffer class and can use its properties
and methods
Had a Client class instantiated automatically, the Client would have fewer options for
how to use the MobileSniffer information. Take a look at the following listing to see
how to create the class:
<?php
//User agent as property of object
class MobileSniffer
{
private $userAgent;
private $device;
private $browser;
private $deviceLength;
private $browserLength;
public function __construct()
{
$this->userAgent=$_SERVER['HTTP_USER_AGENT'];
$this->userAgent=strtolower($this->userAgent);
$this->device=array('iphone','ipad','android','silk','blackberry',
'touch');
$this->browser= array('firefox','chrome','opera','msie','safari',
'blackberry','trident');
$this->deviceLength=count($this->device);
$this->browserLength=count($this->browser);
}
public function findDevice()
{
for($uaSniff=0;$uaSniff < $this->deviceLength;$uaSniff ++)
{
if(strstr($this->userAgent,$this->device[$uaSniff]))
{
10 | Chapter 1: PHP and Object-Oriented Programming
return $this->device[$uaSniff];
}
}
}
public function findBrowser()
{
for($uaSniff=0;$uaSniff < $this->browserLength;$uaSniff ++)
{
if(strstr($this->userAgent,$this->browser[$uaSniff]))
{
return $this->browser[$uaSniff];
}
}
}
}
?>
Embedding Error Reporting in the php.ini File
I work in a university environment where the system administrators often are students
(withvaryinglevelsofknowledgeandcompetence),stillhoningtheircraft.Often,they’ll
forget to set the php.ini file to report errors. As a result, I got into the habit of adding
the following lines to the beginning of my code:
ini_set("display_errors","1");
ERROR_REPORTING(E_ALL);
For some, such added lines of code are annoying, but I include them in the Client class
to provide a reminder of how important error reporting is in developing applications
where feedback is essential. Learning OOP and design patterns relies heavily on such
feedback.
InordertousetheMobileSniffer,theClientinstantiatestheclassandusesitsmethods
as shown in the following listing:
<?php
ini_set("display_errors","1");
ERROR_REPORTING(E_ALL);
include_once('MobileSniffer.php');
class Client
{
private $mobSniff;
public function __construct()
{
$this->mobSniff=new MobileSniffer();
echo "Device = " . $this->mobSniff->findDevice() . "<br/>";
echo "Browser = " . $this->mobSniff->findBrowser() . "<br/>";
The Client as a Requester Class | 11
}
}
$trigger=new Client();
?>
Using the Client class provides a way to make the MobileSniffer class more useful.
The MobileSniffer does not have to launch itself, and using a return statement, any
class that calls MobileSniffer just gets the data. The Client can then use that data in
any way it wants. In this case, the Client formats the data to output it to the screen, as
you can see in Figure 1-3.
Figure 1-3. The Client uses the MobileSniffer’s data to send to the screen
We could have formatted the data in the MobileSniffer class, but then it would not
have been as flexible or useful. By allowing the Client to use the data in the most general
way, it could do any number of things with it. For example, instead of formatting the
data for screen output, it could have used the data to call a CSS file that formats for the
particular device and/or browser. Had the data been preformatted in the MobileSniff
er class, using it for identifying a CSS file would require stripping away the unneeded
formatting. Keep in mind that one of the most important features of design patterns is
reuse of the objects.
12 | Chapter 1: PHP and Object-Oriented Programming
Capturing Mobile: Nailing Jelly to a Tree
At the time of this writing, the number and type of mobile devices just keeps growing,
andanycodeyouwriteinPHPisboundtoletsomedevicesand/orbrowsersslipthrough
the net. Even capturing the device may not be enough because some (like the iPad and
the iPad Mini) have different screen resolutions in addition to different screen sizes.
Suffice it to say that if you plan to create web pages for viewing on different devices, you
will want a module in your system that can be updated without breaking your program.
So, no matter what the latest technique is to detect and respond to multiple devices, be
prepared for change. You can plan to start all over from scratch to incorporate new
devices, such as Microsoft’s Surface, or you can be prepared with a module that can be
incorporated into an existing application where changes will not break the system.
At this point, you may be thinking, “I could write a better algorithm for sorting out
devices and browsers.” You probably could, and in fact, you’ll probably have to because
as new devices and browsers are introduced, they will have to be incorporated into a
program that needs to use device/browser information. However, if you preserve the
structure of the two methods, findDevice() and findBrowser(), you can make all the
changes and improvements you want, and the larger program will not crash. You must
imagine a much larger and more complex program and think about making changes.
If you’ve ever had to revise a larger program, you know that a change can worm its way
through the entire program and break it. Then your debugging becomes a nightmare.
OneofthemainfunctionsofOOPanddesignpatternsisthecapacitytochangeamodule
without breaking the entire program.
What About Speed?
Just about every programmer wants a program to run at optimum speed, and to do that,
welookatthebestalgorithms.Fornow,though,weneedtoshiftourattentiontoanother
kind of speed—the amount of time it takes to create and update a program. If a program
cycles through an operation 100 million times, minor speed tweaks of that operation
are important, but trying to squeeze a couple of microseconds from an operation that’s
used only once can be an expensive use of time. Likewise, having to revise an entire
program because of a few lines of added code is an equally expensive use of time.
The Speed of Development and Change
Consider a contract you have to update and maintain a program for a customer. You
have negotiated a set amount for ongoing updates, and you want both to satisfy your
client and to spend a fair but limited amount of time on updates. For example, suppose
your customer has weekly sales on different products requiring ongoing text and image
What About Speed? | 13
updates. One solution may be to set up a weekly update using the time() function, and
then all you have to do is add the most current image URL and text to a database. In
fact, if you had the text and images ahead of time, you could go on vacation and let the
PHP do the work while you’re away. That would be a sweet maintenance deal, and you
could keep several customers happy simultaneously.
Would you ever consider setting up a maintenance system where you had to rewrite the
program every time you had to make a change? Probably not. That would be a very slow
and expensive way of doing things. So where speed of revision is important, your pro‐
gram needs to consider the speed of both operation and development. Algorithms han‐
dle speed of operations, and design patterns handle speed of development.
The Speed of Teams
Another speed issue can be found in working with teams. When dealing with larger and
more complex programs, teams need to agree on and understand a common plan and
goal to effectively and efficiently create and maintain large programs. Among other
things, OOP and design patterns provide a common language to speed along group
work. References to “factories,” “state machines,” and “observers” all mean the same
thing to those who understand OOP and design patterns.
Most importantly, design patterns provide a way of programming so that a team of
programmers can work on separate parts that will go together. Think of an assembly
line making automobiles—each team assembles a different part of the car. To do that,
they need a pattern of development and an understanding of the relationship of one
part to another. In this way, everyone can do their job knowing that someone else’s job
will fit with their work. They don’t have to know the details of another worker’s job.
They just need to know that they’re working from the same plan.
What’s Wrong with Sequential and Procedural
Programming?
“If it ain’t broke, don’t fix it” is a widely believed sentiment, and you may immediately
agree with it if a solution works. However, such a mindset is the antithesis of progress
and improvement. After all, for getting from one place to another, walking works just
fine. However, for getting from one side of the country to the other, flying in a jet works
much better. OOP and design patterns are improvements over sequential and proce‐
dural programming in the same way as flying is to walking.
Sequential Programming
Mostprogrammersbeginprogrammingbywritingonestatementafteranothertocreate
a series of lines that will execute a program. For example, the following is a perfectly
good PHP sequential program that works:
14 | Chapter 1: PHP and Object-Oriented Programming
<?php
$firstNumber=20;
$secondNumber=40;
$total= $firstNumber + $secondNumber;
echo $total;
?>
The variables are abstract data types, and the arithmetic add operator (+) combines the
values of two variables into a third variable. The echo statement prints out the total of
the combined values to the screen.
Adding two numbers is a simple problem for PHP, and as long as you deal with simple
problems, you can use simple solutions.
Procedural Programming
As programmers began to write longer and longer programs with more complex tasks,
the sequences began to be entangled into what was called spaghetti code. A GOTO state‐
ment would allow sequential programmers to jump around in a program to complete
a procedure, and so it was easy to become entangled.
With procedural programming came the function. A function is a little object where an
operation can be called to perform a sequence with a single statement. For example, the
following is a procedural version of the sequential program shown in the previous
listing:
<?php
function addEmUp($first,$second)
{
$total=$first + $second;
echo $total;
}
addEmUp(20,40);
?>
Thefunctions(orprocedures)allowprogrammerstogroupsequencesintomodulesthat
can be reused in a program. Further, by having parameters, the programmer can enter
different arguments into a function so that it can be used with different concrete values.
Like OOP, procedural programming uses modularity and reuse. However, procedural
programming does not provide for classes where programming tasks can be bundled
intoobjects.Classobjects(instancesofclasses)canoperateontheirowndatastructures,
and that cannot be done by functions alone. As a result, procedural programming re‐
quires long sequences to accomplish large tasks. Further, working in teams is more
What’s Wrong with Sequential and Procedural Programming? | 15
difficult with procedural programming because different team members cannot easily
work on independent but interrelated classes, as can be done with OOP.
Pay Me Now or Pay Me Later
A while ago, I published a blog post titled “No Time for OOP and Design Patterns.” The
post was in reaction to a number of developers who said reasonably that they did not
have time to incorporate OOP or design patterns into their work even though they
wanted to do so. They explained that a project would come along with a clear deadline,
and in an effort to get it done on time, they’d cobble together a working program using
sequential and procedural programming. Maybe they’d include a class or two if they
had one that met a particular goal, but that was it.
In learning OOP and design patterns for PHP, you need to remember a couple of points,
which were first made by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlis‐
sides in Design Patterns: Elements of Reusable Object-Oriented Software:
• Designing object-oriented software is hard.
• Designing reusable object-oriented software is even harder.
RatherthanlookingatthosestatementsasreasonsnottolearnOOPanddesignpatterns,
they stand as reasons why OOP and design patterns are so valuable. Knowledge adds
value to any skillset. The more difficult the knowledge is to obtain, the more it is valued.
Don’t expect to pick up OOP and design patterns easily and quickly. Rather, incorporate
them a little at a time into your PHP programming. At some point you will see the value.
Over time, you will develop more skills and understanding, and you will run into a
project where you can reuse most of the program structures from a previous project.
In a recent project, I decided to use a Strategy design pattern. It included a table with
105 fields, and the customer wanted a certain set of functionalities. By using a Strategy
design, each of the strategies was a class with an algorithm to handle a fairly mundane
PHP problem—filtering, updating, and deleting data in a MySQL database. It took a
while to set it up, but once it was configured, it was easy to change (customers always
wantchange!).Sometimelater,Iwasaskedtodoasimilarkindofprojectusingfrontend
and backend PHP with a MySQL database. Rather than starting over from scratch, I
just pulled out the Strategy pattern, changed the algorithms, and had it up and running
in no time. I got paid the same, but having worked smart, my customer got a much
better piece of software than had I worked longer and dumber.
At some point, we have to stop our old habits and upgrade our skills. At this point in
time, many programmers are updating their skills to accommodate mobile devices. If
they do not, they’ll lose out on many opportunities—eventually they may render their
skills obsolete. Over time, we know that we’ll have to update our skills to incorporate
the benefits of the latest PHP release, new technology, or direction the industry takes.
16 | Chapter 1: PHP and Object-Oriented Programming
OOP and design patterns contain concepts that transcend all of these changes, make us
better programmers, and provide our customers with better software. It all starts with
a first step. By taking the time now, you won’t be scrambling for time to get a project
done in the future. Besides, you will come out of the process as a better programmer,
and that in and of itself is reason enough to learn OOP and design patterns.
Above all, learning OOP and design patterns is the pleasure of doing something well.
What’s Wrong with Sequential and Procedural Programming? | 17
Learning Php Design Patterns William Sanders
Two elements are needed to form a truth—a fact
and an abstraction.
—Remy de Gourmont
Beware how you trifle with your marvelous
inheritance, this great land of ordered liberty, for
if we stumble and fall, freedom and civilization
everywhere will go down in ruin.
—Henry Cabot Lodge
Everybody gets everything handed to them. The
rich inherit it. I don’t mean just inheritance of
money. I mean what people take for granted
among the middle and upper classes, which is
nepotism, the old-boy network.
—Toni Morrison
Our normal waking consciousness, rational
consciousness as we call it, is but one special type
of consciousness, whilst all about it, parted from it
by the filmiest of screens, there lie potential forms
of consciousness entirely different.
—William James
CHAPTER 2
Basic Concepts in OOP
Abstraction
If you’re new to OOP, don’t expect everything to make sense right away. As you use OOP
more and more, you’ll experience little “aha!” moments when the pieces begin to come
together. PHP does have important OOP features, and it has its own way of
implementing these features in the language. If you are familiar with other OOP lan‐
guages, you can be assured that PHP is different in places—like allowing constants to
19
be a part of an interface. Understanding abstraction is a cornerstone in both OOP and
design patterns, and the more you use it, the more sense it makes.
The notion of abstraction is so essential to both object-oriented programming and
design patterns that it bears more than a fleeting consideration. The general idea of
abstraction in computing is not unlike the abstractions we use every day in natural
language. For example, the word dog denotes a phenomenon that has dog-like charac‐
teristics. If someone says, “look at the dog,” they use the abstraction of dog (in other
words, the word dog) to indicate a concrete instance of an animal with dog-like features.
By using the words dog and cat, we can differentiate one from the other and point to
lots of different dogs and cats. However, if we use the word “dog” to indicate a cat, we
may be corrected. “That’s not a dog. It’s a cat.” So while abstractions are general, they
are specific enough so that we can differentiate specific instances.
In Object-Oriented Design with Applications, 3rd Edition (Addison-Wesley), Grady
Booch, a pioneer in both OOP and design patterns, has a clear definition of abstrac‐
tion that nicely sums it up:
An abstraction denotes the essential characteristics of an object that distinguish it from
all other kinds of objects and thus provide crisply defined conceptual boundaries relative
to the perspective of the viewer.
Abstraction is important because it allows programmers to group and classify objects.
To some extent, all classes are abstractions of a set of operations on data. Keep the
following in mind about abstractions:
Abstraction is the main tool used to deal with complexity. The more complex a problem,
the more it requires abstractions to solve.
Think about this paradox: abstractions are concrete methods for handling complexity.
We group similarities in reality (abstract concrete likeness) to make them more man‐
ageable to work with. So instead of, “my loyal, bold, furry-faced, tail-wagging, face-
licking, wet-nosed friend whose name is SyntaxError,” I can say, “my dog.”
Abstract Classes
Besides regular classes, PHP also has what are called abstract classes. In OOP and design
patterns,abstractclassesprovideanorganizingmechanismforyourproject.Anabstract
class cannot be instantiated, but rather a concrete class (one you can instantiate) inherits
its interface and any concrete properties from the abstract class.
Before continuing, the term interface needs to be examined. Familiar interfaces include
user interfaces, hardware interfaces, and other kinds of linkages involving computer
hardware and software. Another kind of interface is one that describes the outline of an
object. To begin, consider a simple class with a single method:
20 | Chapter 2: Basic Concepts in OOP
<?php
class OneTrick
{
private $storeHere;
public function trick($whatever)
{
$this->storeHere=$whatever;
return $this->storeHere;
}
}
$doIt=new OneTrick();
$dataNow=$doIt->trick("This is perfect.");
echo $dataNow;
?>
The central part of an interface is made up of all the signatures in the class defined by
its operations (functions). A signature consists of an operation’s name and parameters.
Signatures also include the return data type, but because of the nature of data typing in
PHP, we’ll have to return to this third element of a signature further on in the section
“Type Hinting: Almost Data Typing” (page 26). Figure 2-1 shows the trick() method’s
signature.
Figure 2-1. An operation’s signature in PHP
When you take all of an object’s signatures, it is the interface. For example, the One
Trick class has one operation with one signature made up of the name trick() and a
single parameter, $whatever.
Abstraction | 21
Abstract Properties and Methods
To write the trick() function as an abstract one, include the interface but nothing else:
abstract public function trick($whatever);
If a class has at least one abstract method, it must be an abstract class. However, an
abstract class can have concrete methods as well. For example, the following class is
abstract and includes an abstract method:
<?php
abstract class OneTrickAbstract
{
public $storeHere;
abstract public function trick($whatever);
}
?>
In addition to the abstract method, you can see a single variable, $storeHere. A variable
that is part of a class is a property. In some contexts, a reference to both properties and
methods is simply properties, but for the most part properties refer to variables and
constants (abstract data) and methods refer to functions (operations on the data).
PHP does not have abstract properties as such. You can declare a property with no
assigned value and treat it as an abstract property, but unlike abstract methods, you are
not forced to use them.
If you declare an abstract method in an abstract class, you must implement it in each
child class that inherits the parent. It might help to think about methods in abstract
classes as being like a contract that forces a set of hierarchies for all subclasses, so that
they must all follow the same standards. For now, begin thinking of abstract classes as
you would containers that can be filled with just about anything and placed on ships,
trucks, and trains. The containers, like abstract classes, are part of a larger structure.
A class that inherits from a class is a child class, and the abstract class (or any other class
from which another class has inheritance) is the parent class. The following shows how
to implement the abstract class, OneTrickAbstract:
<?php
include_once('OneTrickAbstract.php');
class OneTrickConcrete extends OneTrickAbstract
{
public function trick($whatever)
{
$this->storeHere="An abstract property";
return $whatever . $this->storeHere;
}
}
22 | Chapter 2: Basic Concepts in OOP
$worker=new OneTrickConcrete();
echo $worker->trick("From an abstract origin...");
?>
Abstract methods can be implemented in any way you want as long as you include the
method’s signature and correct visibility. In this case, that signature includes the name
“trick” and a single parameter, $whatever, and the visibility is public. The following are
all legitimate implementations of the trick() method:
public function trick($whatever)
{
$echo $whatever;
}
Or:
public function trick($whatever)
{
$half=$whatever/2;
return $half;
}
Or:
public function trick($whatever)
{
$this->storehere=25;
$quarter=$whatever * 100;
return ($quarter / $this->storehere);
}
You may wonder what the point is in an abstract method if you can revise it as long as
you maintain the signature and visibility. In the “Inheritance” (page 34) section of this
chapter, you will be able to see more clearly why inheriting the interface is important.
While abstract classes generally have some abstract methods, you can add as many
concrete methods and properties as you want in addition to any abstract methods that
must be implemented. However, an abstract class can consist of nothing but concrete
methods.
PHP 5.4 has a structure called Traits that are mechanisms for code reuse where multiple
inheritance is not allowed. A class may inherit one class and then at the same time use
a Trait that functions something like multiple inheritance. They will not be used in the
examples in this book and are mentioned here in case there may be some pattern ex‐
ample in another language that uses multiple inheritance that you would like to imple‐
ment in PHP.
Interfaces
Another OOP and design pattern building block is an interface. Like most abstract
classes, interfaces have abstract methods. However, you cannot include concrete
Abstraction | 23
methods in an interface or variables as in an abstract class. (In an exception to abstract‐
ness, you can include concrete constants in an interface, but that is a unique feature of
PHP interfaces.) The salient point about interfaces is that they are important structural
elements in OOP and design patterns.
To create an interface, use the interface statement instead of class. As a general con‐
vention, interfaces begin with the letter I or i; in this book, we’ll use a capital I followed
by a capital letter describing the interface. This is followed by abstract methods, but the
abstract statement is not used. The following is a simple interface with three methods:
<?php
interface IMethodHolder
{
public function getInfo($info);
public function sendInfo($info);
public function calculate($first,$second);
}
?>
To implement an interface, use the implements statement instead of extend as is done
with abstract classes. Note that the listing uses the include_once() function to make
the interface available to the class implementing it:
<?php
include_once('IMethodHolder.php');
class ImplementAlpha implements IMethodHolder
{
public function getInfo($info)
{
echo "This is NEWS! " . $info . "<br/>";
}
public function sendInfo($info)
{
return $info;
}
public function calculate($first,$second)
{
$calulated = $first * $second;
return $calulated;
}
public function useMethods()
{
$this->getInfo("The sky is falling...");
echo $this->sendInfo("Vote for Senator Snort!") . "<br/>";
echo "You make $" . $this->calculate(20,15) . " in your part-time
job<br/>";
}
}
$worker=new ImplementAlpha();
24 | Chapter 2: Basic Concepts in OOP
$worker->useMethods();
?>
When you test the program, you should see the following output:
This is NEWS! The sky is falling...
Vote for Senator Snort!
You make $300 in your part-time job
Note that in addition to implementing the three methods in the interface, the Imple
mentAlpha class includes a third method, useMethods(). As long as you implement the
full number of methods in the interface, you can add as many other methods and prop‐
erties as you need.
Interfaces and Constants
While you cannot include variables in interfaces, you can include constants. In order
to use constants, you need the scope resolution operator (::). The double colon operator
can be used to allow access to constants, both in classes and through an interface im‐
plementation. The general format can be seen in the following code samples:
$someVariable= InterfaceName::SOME_CONSTANT;
For example, the following interface has constants used in a MySQL connection:
<?php
interface IConnectInfo
{
const HOST ="localhost";
const UNAME ="phpWorker";
const DBNAME = "dpPatt";
const PW ="easyWay";
function testConnection();
}
?>
Implement the interface just like any other PHP interface. The values of the constants
can then be passed using the scope resolution operator in the implementation:
<?php
include_once('IConnectInfoMethod.php');
class ConSQL implements IConnectInfo
{
//Passing values using scope resolution operator
private $server=IConnectInfo::HOST;
private $currentDB= IConnectInfo::DBNAME;
private $user= IConnectInfo::UNAME;
private $pass= IConnectInfo::PW;
public function testConnection()
{
Abstraction | 25
$hookup=new mysqli($this->server, $this->user, $this->pass,
$this->currentDB);
if (mysqli_connect_error())
{
die('bad mojo');
}
print "You're hooked up Ace! <br />" . $hookup->host_info;
$hookup->close();
}
}
$useConstant = new ConSQL();
$useConstant->testConnection();
?>
The only method is testConnection(), but your interface could be made up of nothing
but constants if you wanted. The values are passed to the class properties (private vari‐
ables in the example) using the name of the interface (IConnectInfo), the scope reso‐
lution operator, and the name of the constant.
Abstract Classes and Interfaces: Two Types of Interfaces
One of the more confusing concepts in OOP and design patterns is differentiating ab‐
stract classes and interfaces. Keep in mind that both have interfaces, general outlines of
methods. The set of all signatures defined by the methods in a class is the interface of
the class (or object). So, you may often find a reference to a pattern’s interface referring
to an abstract class as well as an interface. The reference is to the set of all signatures.
Gamma et al. note that, “An object’s interface characterizes the complete set of requests
that can be sent to the object.” This means that if your Client class is aware of an object’s
interface, it knows what it can request and how to request it. So while both abstract
classes and interfaces have interfaces of their own, abstract classes can have concrete
methods (operations) and properties as well.
Much of understanding design patterns relies on understanding the general use of the
term interface as it applies to the set of signatures in an object (a class).
Type Hinting: Almost Data Typing
One of the important structural elements in the abstraction in OOP and design patterns
istypingdatatoaninterfaceinsteadofanimplementation.Thismeansthatthereference
to the data is through the parent class, typically an interface or abstract class. (In this
context, interface is used to refer to either an interface or abstract class.)
26 | Chapter 2: Basic Concepts in OOP
The basic format for type hinting is as follows:
function doWork(TypeHint $someVar)...
Type hints must be the name of a class or interface. In design pattern work, an abstract
class or interface is preferred because it does not bind the type of an implementation,
just the structure. The following example shows an interface with two implementations
of the interface and a class that uses an interface in type hinting to establish a loose but
clear bind.
Interface
//IProduct.php
<?php
interface IProduct
{
function apples();
function oranges();
}
?>
FruitStore Implementation
//FruitStore.php
<?php
include_once('IProduct.php');
class FruitStore implements IProduct
{
public function apples()
{
return "FruitStore sez--We have apples. <br/>";
}
public function oranges()
{
return "FruitStore sez--We have no citrus fruit.<br/>";
}
}
?>
CitrusStore Implementation
//CitrusStore.php
<?php
include_once('IProduct.php');
class CitrusStore implements IProduct
{
public function apples()
{
return "CitrusStore sez--We do not sell apples. <br/>";
}
Abstraction | 27
public function oranges()
{
return "CitrusStore sez--We have citrus fruit.<br/>";
}
}
?>
Object with type hinting
//UseProducts.php
<?php
include_once('FruitStore.php');
include_once('CitrusStore.php');
class UseProducts
{
public function __construct()
{
$appleSauce=new FruitStore();
$orangeJuice=new CitrusStore();
$this->doInterface($appleSauce);
$this->doInterface($orangeJuice);
}
//IProduct is type hint in doInterface()
function doInterface(IProduct $product)
{
echo $product->apples();
echo $product->oranges();
}
}
$worker=new UseProducts();
?>
When you test the UseProducts class, the output displays the following:
FruitStore sez--We have apples.
FruitStore sez--We have no citrus fruit.
CitrusStore sez--We do not sell apples.
CitrusStore sez--We have citrus fruit.
WhatyouseeonthescreenaredifferentimplementationsoftheIProduct interface.
The crucial feature to note is that in the doInterface() method, the type hint of
IProduct recognizes both of the classes that implemented the IProduct interface.
In other words, instead of recognizing one as a FruitStore instance and the other
as a CitrusStore instance, it recognizes their common interface IProduct.
In practical terms for development, enforcing data types ensures that any object
(class) used in conjunction with a given method where code hinting is used will
have a given interface. Further, if an interface (either an abstract class or interface)
28 | Chapter 2: Basic Concepts in OOP
Another Random Scribd Document
with Unrelated Content
The footsteps had now reached the landing of the first floor and,
after another deathlike pause, commenced to ascend the stairs
which led directly to us.
"Can't you do something, Edward?" whispered my agonized wife,
wringing her hands. "Can't you lock the door?"
It is strange that the fact of the door being unlocked had not
occurred to me before. I rushed to it instantly, and a sigh of intense
relief escaped me at finding the key in the lock. I turned it like
lightning, and we were so far safe. Then my wife flew to the
window, and, throwing it open, began to scream for help--that is to
say, she would have screamed if she had had the power, but her
voice was almost frozen in her throat, and the sounds that issued
from her were of a ravenlike hoarseness, and could have traveled
but a few yards; too short a distance in our lonely situation to be of
any practical value. Soon I added my shouts to her hoarse scream.
They were sent forth to a dead world; to our frantic appeals no
answer was made.
Meanwhile, occupied as I was, I could still pay some attention to
what was passing on the stairs that led to the room. I had indulged
in a faint hope that our cries would alarm those without, and would
induce them to forego their murderous attack upon us, but the
stealthy pat, pat, pat of the footsteps continued, and were now in
the middle of the staircase; there could be but a few more stairs to
ascend. Still another hope remained--that when the footsteps
reached the second landing they would proceed onward to the top
of the house. This last hope, like those which had preceded it, was
not fulfilled. Nearer, nearer, nearer they approached, until they were
close to the door; then there was another pause; no further sounds
were heard.
My impression now was that the villains who had a design against
us--for by this time I entertained no doubt of their diabolical
purpose, and that we were in the direst peril--were making
preparations to carry it into effect. Presently they would try the
handle of the door, and, discovering that it was locked, would burst
it open and spring upon us.
A long and awful silence ensued, during which the agonizing
question occupied my mind, what was being done outside the door?
The torture of the suspense was maddening; the silence was more
harrowing than the footsteps themselves had been. I was soon to
receive an appalling answer to the question.
The door--notwithstanding my firm belief that I had securely
locked it--slowly and noiselessly opened. My heart beat wildly, but I
held myself ready, so far as lay in my poor power, to meet the attack
with which we were threatened. And now the door stood wide open,
and I saw no form of man or woman. But gradually there shaped
itself in the air the outline of a female shape, a shadow, which as I
gazed grew more distinct, and yet was never quite vivid to my sight.
It was the figure of a young girl, poorly dressed, with carpet slippers
on her feet. Her hair was hanging loose, and the tattered remnants
of a cap attached to it was an indication that her station in life was--
or more properly speaking, had been--that of a domestic servant.
Her face was white and wan, and her large gray eyes were fixed
mournfully upon me. There was a dead beauty in their depths which
seemed to speak of glowing hopes of youth prematurely blasted and
destroyed, and, though the features of the apparition were but airy
outlines, I could not fail to perceive that in a bygone time they had
been comely and prepossessing.
More terrible than any form of living man or woman was this
appalling spectacle as it stood, silent and still, upon the threshold.
Had the bell I rang summoned it from the grave? For what purpose
had it come? What did it require of me? It is probable that I should
have mustered courage to ask some such questions as these, and
indeed I was aware that my lips were moving, but no sound issued
from them--my voice was gone; I could not utter an audible sound.
For several minutes, as it seemed to me, though it could not have
been so long, did I continue to gaze upon the figure. I had directed
a brief glance at its feet, but when my eyes traveled up to its face
they became magnetized, as it were. The spell was broken by a
movement on the ground, not proceeding from the apparition of the
girl. I looked down, and there, gliding past the upright spectral
figure, I saw creeping toward me a skeleton cat.
It was veritably a skeleton, and was to my sight as impalpable as
the young girl. Through its skin, almost bare of hair, its bones were
sharply outlined. It was black; its ears were pointed, its eyes were
yellow, its mouth was open, showing its sharp teeth.
This second apparition added to my horror, which grew deeper
and deeper as the cat, with gliding motion, approached me. Had its
paws left upon the ground a bloody imprint I could not have been
more awestricken. It paused a few inches from me, where it
crouched motionless so long as I remained so. When I moved it
accompanied me, and when I stopped it stopped, waiting for a
mandate from me to set it in motion.
Raising my eyes to the door I discovered to my amazement that
the figure of the girl had vanished. Nerving myself to the effort, I
stepped softly into the passage and gazed along and at the
staircases above and below me, but saw no movement of substance
or shadow. Returning to the room I was irresistibly impelled by a
desire to convince myself whether the cat which had accompanied
me to and fro was as palpable to touch as to sight. Kneeling to put
this to the test I found myself kneeling on my wife's dress. So
engrossed had I been in the astounding apparitions that I had paid
no attention to her, and now I saw that she had fainted. Before
devoting myself to her I passed my hand over the cat and came in
contact with nothing in the shape of substance. It was truly a
specter, and I beheld it as clearly as I beheld the body of my wife
lying at my side.
I took my flask from my pocket and bathed my wife's forehead,
and poured a few drops of brandy and water down her throat, and I
was presently relieved by seeing her eyes open. She closed them
again immediately, and said, in a whisper:
"Is it gone?"
Anxious to learn what she had seen--for I inwardly argued that I
might myself be the victim of a strange delusion--I met her inquiry
by asking:
"Is what gone, Maria?"
"The girl," she murmured; "that dreadful figure that came into the
room?"
"Look for yourself," I said.
It was not without apprehension that I made the request, and I
nervously followed the direction of her eyes.
"It is not in the room," she sighed. "But, Edward, who opened the
door?"
"The wind blew it open, most likely."
"You locked it, Edward! I heard you turn the key in the lock."
"I thought I did, but I must have been mistaken. Terrified as we
were, how could we trust the evidence of our senses? And do you
suppose there's a lock in the house in proper order?"
"It must have been my fancy. Did you see nothing?"
How should I answer her? Revive her terror by telling her that she
was under no delusion, but that the spectral figure of the young girl
had really presented itself; or, out of kindness to her, strive to banish
her fears by a pardonable falsehood?
Before I decided how to act I felt it necessary to ascertain
whether the cat lying in full view to me was visible to her.
"Maria," I said, "take the evidence of your senses. Look round the
room--at the door, at the walls, at the ceiling, on the floor--and tell
me what you see."
With timid eyes she obeyed, and glanced in every direction, not
omitting the spot upon which the skeleton cat was lying.
"I don't see anything, Edward."
"Does not that prove that the figure you spoke of was a trick of
the imagination?"
"You actually saw nothing?"
"Nothing."
All this time she had been sitting on the floor, keeping tight hold
of me. I assisted her to her feet; she was so weak that she could
hardly stand.
"For Heaven's sake!" she said "do not let us remain in the house
another minute."
I was as anxious to leave as she was, and had I been alone I
should have rushed downstairs in blind haste, but I had to attend to
my wife. The power of rapid motion had deserted her, and when we
were about to pass through the passage she shrunk back, fearing
that the apparition of the young girl was lurking there. She
experienced the same fear as we descended the stairs, and clung to
me in terror when we approached an open door. I was grateful that
the apparition of the cat--which followed us faithfully down to the
hall--was invisible to her; if it had not been she would have lost her
senses again, and it would have been hard work for me to carry her
out, as she is by no means of a light weight.
The question which now agitated me was whether the cat would
come into the streets with us, or would return to the resting place
which should have been its last. It was soon and plainly answered.
I opened the street door, and stood upon the threshold. The cat
stood there also. I paused to give it the opportunity of returning, but
it evinced no desire to do so. I went down the stone steps to the
front garden; the cat accompanied me. I walked through the front
garden out of the gate, straight into Lamb's Terrace, and thence
across the wretched wastes of ground into more cheerful
thoroughfares; and the skeleton cat was by my side the whole of the
time.
The evidence of civilized life by which we were now surrounded
restored Maria's spirits; she found her tongue.
"Why did you stop on the doorstep, Edward?" she asked.
"I had to lock the street door," I answered.
"We will not take that house, my dear," she said.
"No, we will not take it."
Some unaccustomed note in my voice struck her as strange.
"Is anything the matter with you?" she asked.
"No," I replied, glancing at the cat, "nothing."
"What are you looking at? Why are your eyes wandering so?"
"My dear," I said, with an attempt to speak in a lively tone, and
failing dismally, "I must be a bit unstrung, that is all."
She accepted my explanation as satisfactory.
"No wonder," she said; "I would not go through such another trial
for all the money in the world."
CHAPTER VII.
I MAKE SOME SINGULAR EXPERIMENTS.
For a little while we walked along in silence, and then I asked my
wife whether she would ride or walk home.
"I should prefer to walk," she said; "it is early, and the air is fresh
and reviving. Things look all the brighter now we are out of that
horrible place. A walk will do us good."
I made no demur, though I was curious to see what the skeleton
cat would do when we entered an omnibus full of people. It would
experience a difficulty in finding a place on the floor of the 'bus, and
there would be no room for it to stretch itself comfortably on the
seats. I wished to ascertain, also, whether among a number of
strangers there would be one to whom it would make itself visible. I
peered into the faces of the passers-by with this thought in my
mind, but I saw no expression of surprise in them, notwithstanding
that the cat seemed to touch their legs in brushing past. Again and
again did I turn my eyes away from the apparition; and again and
again, looking down at my feet, I beheld it as clearly as if it were an
actual living example of its species. Once we got into a crowd and I
hoped that I had lost it. No such luck; it evinced no disposition to
leave me.
"Edward," said my wife, "I am sure you are not well. I have tired
you out with this eternal looking over houses to let. You have been
very patient with me"--she pressed my arm affectionately--"and I
will try and make it up to you. I know you never really wished to
move."
"I never wished it, Maria."
"And you have gone through all this for my sake. I don't like to
give up a thing once I have set my mind on it,--you know that of
old, my dear,--but the experiences of this morning will last me a
lifetime; so I will give this up."
"The idea of moving?" I asked in a dull voice. "You give it up
altogether?"
"Yes, altogether. We will remain in our old house."
It is a singular confession to make, but this proclamation of the
victory I had gained afforded me no satisfaction. I had no wish to
move; my earnest desire was to remain where we were; but with
the infernal cat gliding by my side, I could think of nothing but the
haunted house in Lamb's Terrace which we had just quitted. In that
house was the spectral figure of the girl who, by spiritual means,
had opened a door I had locked, and presented herself to me. She
was now alone. I had deprived her of a companion who, for aught I
knew, might have been a solace to her. It was as if I had been guilty
of a crime; as if I had condemned her to solitude. But it was folly to
torment myself with such reflections. What had I to do with the
incidents of this eventful day? I was a passive instrument, and was
being led by unseen hands. More pertinent to ask what was the
portent of the apparitions, and why the supernatural visitation was
inflicted upon me, although to these questions I could expect no
answer. Involuntarily I stooped to assure myself once more that the
cat was but a shadow.
"What are you stooping for?" inquired my wife.
"I thought I had dropped my handkerchief."
"It is here, in your pocket." She took it out and handed it to me.
"I was mistaken," I muttered.
She held up her sunshade and hailed a passing hansom, saying
energetically, and with a troubled look at me, "We will ride home."
I did not object. I think if she had said "We will fly home," I
should have made an attempt to fly, so absolutely was I, for the
time, deprived of the power of deciding my own movements. I did
not see the cat spring into the cab, but directly we were seated,
there it lay crouched in front of us; and when the driver pulled up at
our house there it was waiting for the street door to be opened.
"Lie down and rest yourself for an hour," said my wife, with deep
concern in her voice.
"No," I replied, "I will smoke a pipe in the garden."
With wifely solicitude she filled my pipe for me, and held a lighted
match to the tobacco. I puffed up, thanked her with a look, and
went into the garden accompanied by the cat.
In the part of London in which we live there are pleasant gardens
attached to many of the houses, and our little plot of ground is by
no means to be despised. It is some ninety feet in length, is divided
in the center by a broad graveled space, and has a graveled walk all
around it; and here when the weather permits, my wife and I
frequently sit and enjoy ourselves. I am also the proud possessor of
a greenhouse, which, as well as the borders and beds I have laid
out, is in summer and autumn generally bright with flowers, of which
I am very fond; and into this greenhouse I walked to smoke the
green fly, which was doing its worst for my pelargoniums. There are
a couple of trees in my garden, and birds' nests in them. The birds
were flitting among the branches, and I looked at the cat, wondering
whether it would spring after its feathered victims.
It took no notice of them, nor they of it. I remained in the
greenhouse ten or twelve minutes, and then it occurred to me to
make an experiment. With a swift and sudden motion I left the
greenhouse and pulled the door behind me, shutting the cat inside. I
walked toward the center of the garden, and the animal I thought I
had cunningly imprisoned glided on at my side. Doors shut and
locked, and doubtless stone walls, presented no greater obstacle to
the creature than the air I breathed.
I sat down on the garden seat and smoked and pondered, and
was aroused by a soft purring at my feet, and the contact of a furry
body against my legs. I uttered an exclamation, and, looking down,
saw our own household cat--a tortoise-shell tabby--rubbing against
me. Now, thought I, there will be a fight. But there was nothing of
the kind. I felt convinced that the skeleton cat saw our tortoise-shell
cat, and presently I was quite as convinced that the flesh and blood
reality was unconscious of the presence of the disembodied spirit.
I made another experiment. I went stealthily into the kitchen, and
filled a saucer with milk. This saucer I took into the garden and put
upon the gravel before the two cats.
"You must be hungry," I said aloud to the spectral figure, with a
feeble attempt at jocularity. "Lap up."
It made no movement. With a look of gratitude at me our tabby
lapped up the whole of the milk, and licked the saucer dry.
My wife came out and, seeing what I had done, smiled.
"Are you feeling better?" she asked solicitously.
"There is nothing whatever the matter with me," I said, with an
unreasonable show of irritation.
She wisely made no reply, and I was once more left alone with
my supernatural companion.
Thus passed the day, and I was glad when the hour arrived for
Bob Millet to make his appearance. He came punctually and was
cordially received by my wife.
"You are in time for tea, Mr. Millet," she said, shaking hands with
him. "I want you to feel that you are really welcome here."
"Indeed I do feel so," said Bob, gratified by this reception, which I
fancy he hardly expected.
They made a good meal, but though my wife had thoughtfully
prepared a dish of which I was very fond--a tongue stewed with
raisins--I ate very little.
"No appetite, Ned?" said Bob.
I shook my head gloomily.
"He is out of sorts, Mr. Millet," said my wife, "and I am delighted
you are here to cheer him up. He has me to thank for his low spirits;
it is all because of my stupid wish to leave the house in which we
are as comfortable as we could reasonably hope to be. I have
worried him to death, almost, dragging him about against his will--
though he has never complained--from morning till night for I don't
know how long past. He is not half the man he was; he doesn't eat
well and he doesn't sleep well, and I am to blame for it."
She was ready to cry with remorse, and I felt ashamed of myself
for not having the strength to battle with the delusion which surely
would not torture me forever.
I patted her on the shoulder, and put on a more cheerful
countenance. She brightened up instantly, and then Bob asked
whether we had been to 79 Lamb's Terrace.
"Yes, we have," said my wife, "and I am truly thankful that we got
out of it safely."
"Ah!" said Bob, lifting his eyes.
"You were right, Mr. Millet," said my wife, "the house is haunted."
"Oh," said Bob, "I only told you what I had heard. For my part, I
don't even know where Lamb's Terrace is."
"Take my advice, Mr. Millet, and don't try to know. The less you
see of the place the better it will be for you."
"Why?"
"Because it is haunted," she replied with emphatic shakes of her
head, "and I am much obliged to you for putting us on our guard."
"Then you saw something?"
My wife looked at me.
"Tell him what you fancy you saw," I said.
"It was not fancy," she rejoined; "I have been thinking over it
during the day, and the more I think, the more I am convinced that I
did see--what I saw."
"I should like to hear about it," said Bob.
"You shall."
And she told him all; of our going over the house till we got to the
room on the second floor, of my pulling the bell, of the sounds we
had heard proceeding from the basement and approaching nearer
and nearer till they were outside in the passage, of my locking the
door, of the door opening of its own accord, and of the appearance
on the threshold of the specter of a young girl, and, finally, of her
fainting away.
"It was only my obstinacy," she said, "that took us up to the top
of the house. Edward was quite ready to leave it before we had been
in the place two minutes, but I insisted upon going into all the
rooms, and I was properly punished for it. I was frightened enough,
goodness knows, before I fainted, for I was chilled all over by what I
had already seen, and I ought to have been satisfied; but you know
what women are, Mr. Millet, when they take a fancy into their
heads."
"There, Bob," said I, "there's a confession to make; not many
women would say as much."
Bob smiled, and said, "You are too hard on yourself. We are much
of a muchness--men and women alike; there is nothing to choose
between us."
"You are very good to say so, Mr. Millet."
"When you recovered from your faint," said Bob, "was the figure
still there?"
"No, it was gone."
"And you did not see it again?"
"No, thank God!"
"Did you see it?" asked Bob, turning to me. "He says he didn't,"
said my wife, quickly replying for me, "but----"
"But," I added, "she does not believe me."
"How can I believe you," said my wife reproachfully, "when the
very moment before I swooned away I saw your eyes almost
starting out of your head with fright."
"Oh, well," I said, "I suppose I have as much right to fancy things
as you."
"Of course you have, and it was very considerate of you to deny
that you saw anything. He is the best husband in the world, Mr.
Millet, and if he thinks I don't appreciate him he is mistaken."
"Now, my dear," I said soothingly, "you know I don't think
anything of the sort; if I am the best husband in the world, so are
you the best wife in the world. What do you say to our going in for
the flitch of bacon?"
"It is all very well to make a laughing matter of it," said my wife
seriously. "I will ask Mr. Millet this plain question. He may say, like
you, that it is all fancy; but pray how does he account for the
opening of a locked door?"
"I told you," I interposed before Bob could speak, "that I must
have been mistaken in supposing I had locked it."
"Very good. But the door was shut if it was not locked."
"I don't deny that it was."
"How did it come open, then?"
"I told you that, too," I replied. "The wind."
"What wind?"
"The wind from the window through the broken panes."
She turned to Bob triumphantly. "What do you think of that, Mr.
Millet? When we go into the room the door slams, and my husband
says it slams because of the wind through the window. I accept that
as reasonable, but is it reasonable to suppose that the same wind
that blows a door shut from the inside of a room should blow it open
from the outside?"
"Well, no," said Bob, with a sly look at me; "I should say it was
not reasonable."
I was fairly caught. My wife's logic was too much for me.
"And now," said she, "as I know it will worry him if I go on talking
about it, I will leave you two gentlemen together while I go and look
after some affairs. You will spend the evening with us, Mr. Millet?"
"With much pleasure," he said.
"And I beg your pardon," she said, "for having misjudged you. I
did think that you and my husband were in a plot together to set me
against the house, and I did not think it was nice behavior in a
gentleman who was paying me his first visit. I told my husband as
much last night before we went to sleep, and he stood up for you
like the true friend he is; and now I am glad to say I have found out
my mistake. I hope you will forgive me.
"There is nothing to forgive," said Bob, in the kindest and gentlest
tone imaginable. "All that you have said and thought and done was
most fair and reasonable, and I ought to be thankful for the little
misunderstanding, if it has given you a better opinion of me."
CHAPTER VIII.
I TAKE BOB INTO MY CONFIDENCE.
"A sensible woman," said Bob, gazing after my wife; and then, in
a more serious tone, "Ned, is it all true?"
"Every word of it."
"About the phantom of the girl?"
"Yes, about the phantom of the girl. Frightfully, horribly true!"
"You saw it?"
"I did; and I would swear it was no trick of imagination."
"And the door opened, as your wife has described?"
"It did, and I will swear that that was no trick of the imagination."
We had moved our chairs and were sitting by the open window,
from which stretched the bright prospect of the flowers in my
garden; there was a space of some three feet between our chairs as
we sat facing each other, and on this space lay the skeleton cat.
"There is something more," I said. "Look down here." I pointed to
the cat.
"Well? I am looking."
"What do you see?"
"Nothing."
"Absolutely nothing?"
"Nothing, except the carpet."
"Bob, would you judge me to be a man possessed of a fair
amount of common sense?"
"Certainly."
"Not likely to give way to fads and fancies?"
"Certainly."
"Caring, as a rule, more for the prosaic than the romantic side of
things?"
"I should say that, without doubt."
"And you would say what is true of me, up to the present
moment. I prefer the plain bread-and-butter side of life, and though
I hope I have a proper sympathy for my fellow-creatures, I am not
given to extravagant sentiment. I am putting this description of
myself in very plain words, because I really want you to understand
me as I am."
"I think I do understand you, Ned."
"I have never had a nightmare," I continued, "and, as a rule, my
sleep is dreamless. It is true that my rest has been a little disturbed
lately by my wife's wish to move, but the few restless nights I have
passed from this reason are quite an exception. To sum myself up
briefly and concisely, I claim to be considered a healthy human being
in mind and body."
"It is not I, Ned, who would dispute that claim."
"I have told you that the spectral figure of the girl appeared to
me. A doctor would at once declare it to be a delusion of the senses.
If my wife informed the doctor that she also saw it, he would reply
that she also was suffering under a delusion, and he would attempt
to explain it away on the ground of sympathy between us. But the
opening of the door could be no delusion; it was tight shut, and the
key was incontestibly turned in the lock; and yet it opened to admit
the specter. The doctor would smile at this, and ask incredulously, 'Is
it necessary for the entrance of an apparition, that a door should be
open, when it possesses the power of passing through material
obstacles?' It does possess such a power, Bob; I have tested and
proved it. Now, what I have been coming to is this. My wife saw one
apparition; I saw two."
"Two?" exclaimed Bob, regarding me more intently.
"Yes, two. One, the girl, vanished; the other, the cat, remained."
"In Heaven's name what are you talking about?"
"I am relating an absolute fact. By the side of the girl appeared
the apparition of a skeleton cat, which accompanied me from the
house, which glided along the streets at my side, which entered my
own house with me, and which now lies here, on this little space of
carpet between us, on which you see--nothing. Now, Bob, tell me at
once that I am mad."
"I shall tell you nothing of the kind; I must have a little time to
consider. What kind of reading do you indulge in? Sensation stories?"
"I chiefly read the newspapers."
"Digestion good, Ned?"
"In perfect condition; for the last ten years I have not had a day's
bad health."
"All that is in your favor."
"Thank you. I see that you are taking a medical view of my case."
"Indeed, I am not; I only want to think it out for myself. You can
actually see the cat?"
"There it lies, its yellow eyes fixed on my face."
"Touch it."
I stretched forth my hand and passed it over and through the
apparition.
"Does it reply by any sign?"
"By none."
"And yet it moves?"
"When I move. Otherwise it remains motionless, in a state of
expectation, as it appears to me.
"I don't quite understand, Ned."
"It is difficult to understand, but it seems to be waiting for
something in the near or distant future. It relieves me to unburden
my mind to you, Bob. I do not intend to confide in my wife; it would
frighten her out of her life, and in the kindness of her heart she
would try to make me disbelieve the evidence of my own senses.
Therefore not a word about this to her. I hear her singing; she is
coming back to us, and she is singing to make me cheerful. Why,
Maria," I said, as she entered the room, "what have you got your hat
on for? Are you going out for a walk?"
"I am," she replied briskly, "and you two gentlemen are coming
with me. It is now half-past seven, and if you will be so good as not
to raise any objection I propose to treat you to the theater."
"A good idea," said Bob Millet, in a tone as lively as her own.
"No tragedies," she continued, "a play that we can have a good
laugh over; we have had enough of tragedies to-day, and I don't
intend they shall get the best of me. We will go to the Criterion,
where you always get a proper return for your money, and I hope
you won't object to the pit, Mr. Millet?"
"I assure you," said Bob, with grave humor, "that when I sit in the
pit I shall consider myself one of the aristocracy. Your wife is a
capital doctor, Ned."
Very willingly I fell in with the thoughtful proposition, and as
Maria insisted upon paying all the expenses out of her private purse
I allowed her to do so, knowing that it would give her pleasure.
We arrived at the Criterion before the raising of the curtain and
we saw a laughable comedy most admirably acted, which afforded
us great enjoyment. I may say that the circumstance of the skeleton
cat not accompanying us was the mainspring of my enjoyment.
Could it have been, after all, an illusion? Was it really possible that
the apparitions I had seen were the creations of my fancy? Bob
whispered to me once:
"Has it accompanied us?"
"No," I whispered back, "I see nothing of it."
When we were outside the theater, and were ready to depart our
separate ways, Bob said:
"Will you come and spend an hour with me to-morrow evening,
Ned?"
"Yes, he will," said my wife; "it will do him good. It does not do,
Mr. Millet, for a man to mope too much at home."
So I consented, and we shook hands, and wished each other
good-night.
CHAPTER IX.
I PAY BOB MILLET A VISIT.
I was naturally curious when I arrived home to see if the cat was
there. It was. It did not meet me at the street door, but it lay on the
spot on which I had left it a few hours previously. Of course this
distressed me, but I did not betray my uneasiness to my wife. I had
at least cause for thankfulness in the silent announcement made by
the apparition that it was not its intention to accompany me to every
place I visited.
We had our supper and went to bed; and it was an additional
comfort to me when I found that it did not follow us to our bedroom.
It was not likely, after such an exciting day, that I should pass a
good night. My rest was greatly disturbed; and at about three
o'clock I was wide awake. My wife was sleeping soundly. I rose
quietly, thrust my feet in my slippers, and went downstairs to the
dining-room. There lay the cat with its eyes wide open.
"You infernal creature," I cried, holding the candle so that its light
fell upon the specter, "what are you here for? What do you want me
to do? Why do you not go back to your grave and leave me in
peace?"
I asked these questions slowly, and paused between each, with
an insane notion that an answer might be given to them. No answer
was vouchsafed, and I recognized the folly of my expectation. The
peculiarity of the apparition was that its eyes never seemed to be
closed, as the eyes of other cats are when they are in repose. It
appeared to be ever on the watch, but what it was watching for was
a sealed mystery to me. In a moment of exasperation I raised my
hand against it threateningly; it did not move. I went no further than
this, feeling that it would be cowardly to strike at a shadow. I
returned to my bedroom, and after tossing about for an hour fell
into a disturbed sleep.
Bob lived at Canonbury, and had given me directions to take a
North London train, his station being about half a mile from his
lodgings.
All the day the cat had remained in the dining-room, but when I
was leaving the house on my visit to Bob, it rose and followed me.
"Do you intend to favor me with your company?" I asked. "Very
well, come along."
And come along it did, to the train I took, got into the carriage
with me, and emerged from it at the Canonbury station, where I
found Bob waiting for me on the platform.
"I have brought another visitor with me, Bob," I said, "but I can
assure you it has accompanied me without any invitation."
"Is it here, then?" he asked, following the direction of my eyes.
"Yes, Bob, it is here." And as we walked to the old-fashioned
house in which he rented one room at the top, I remarked, "Is it not
singular that it did not come to the theater with me last night, and
that it should accompany me now upon this friendly visit to you?"
Bob nodded. "I am beginning to have theories about it," I continued,
"and one is, that something will occur to-night in connection with
the haunted house in Lamb's Terrace."
"Do not get too many fancies into your head, old fellow," said
Bob.
"I will not get more than I can help, but ideas come without any
active prompting or wish of my own; I am like a man who is being
driven, or led."
Bob's one room was by no means uncomfortable; it served at
once for his living and bedroom, but the bed he occupied being a
folding bed, and the washstand he used being inclosed, it did not
present the appearance of a bedroom. There were shelves on the
walls containing a large number of books; four or five of these were
on the table.
"Now, sir or madam," said I to the cat, "what do you think of
Bob's residence, and what can we do to make you comfortable?"
The cat glided to the hearthrug and stretched itself upon it; I
wrested my attention from the unpleasant object.
"I am very well off here," said Bob; "the landlady cooks my meals
for me, and allows me to have them downstairs. I am at the top of
the house, and there is a fine view from the roof; I often smoke for
an hour there. You see that door in the corner; it is a closet, with a
fixed flight of steps leading to the roof; in case of fire I should be
safe. Sit in the armchair, Ned, and let us reason out things. I have
been thinking a great deal about you to-day, and talking about you,
too."
"That was scarcely right, Bob."
"Don't be afraid; you were not mentioned by name, and the
gentleman I conversed with is blind. That is the reason, very likely,
why he believes in what he does not see."
"A friend of yours?"
"A dear friend; a poor gentleman who has suffered, and who
bears his sufferings with a resignation which can only spring from
faith. I told you yesterday that I had been married and that I lost my
wife. The gentleman I speak of is the son of my dead wife's sister,
who is herself a widow. My wife's family were gentlefolk, who had
fallen from affluence, not exactly into poverty, but into very poor
circumstances. Ronald Elsdale--the name of my nephew--is a tutor;
he was not born blind; the affliction came upon him gradually, and
was accelerated by over study in his boyish days. Four years ago he
could see, and when blindness came upon him he was fortunately
armed, and able to obtain a fair living for himself and his widowed
mother by tutoring. He is an accomplished musician, and frequently
obtains remunerative engagements to play. He speaks modern
languages fluently, is well up in the sciences, has read deeply, and is
altogether as noble and sweet a gentleman as moves upon the
earth."
Bob spoke with enthusiasm, and it was easy to perceive that he
had a sincere love for Mr. Ronald Elsdale.
"In every way so accomplished and admirable," I said, "and with
such a misfortune hanging over him, he needs a wife to look after
him."
"His mother does that," Bob replied, "with tender devotion, and
Ronald will never marry unless--but thereby hangs a tale, as
Shakspere says. He is not the only man who cherishes delusions."
"Ah! he has delusions. I hope they are more agreeable than mine.
How is it, Bob, that you have had time for so much talk to-day with
your nephew?"
"This is Thursday, and Mr. Gascoigne closes his office on
Thursdays at two o'clock, so I have had a few hours at my disposal,
which have been partly employed in talking with Ronald and partly in
studying your case."
"Explain."
"I have been looking up apparitions," said Bob, pointing to the
books upon the table.
I did not trouble myself to examine them; it did not seem to me
that the books would be of much service in my case; the facts
themselves were sufficiently strong and stern, and I mentally
scouted the idea that printed matter would enable me to get rid of
the apparition that haunted me.
"It is clear to me," I said, "that you think I am laboring under
some hallucination, and that I see the specter, now lying on the
hearthrug, with my mental and not my actual vision. Very well, Bob;
a difference of opinion will not alter the facts."
"The awkward part of it is," said Bob, "that all evidence is against
you."
I nodded toward the books on the table, and said, "All such
evidence as that."
"Yes, but you must not forget that cleverer heads than ours have
occupied years of their lives in sifting these matters to the bottom."
"In trying to sift them, Bob."
"Well, in trying to sift them; but they give reasons for the
conclusions they arrive at which it would be difficult, if not
impossible, for men like ourselves to argue away."
"There are two strong witnesses on my side," I remarked; "one is
myself, the other is my wife. Bear in mind that we both saw the
apparition of the girl; there was no collusion between us beforehand,
and if, in our fright, our imaginations were already prepared to
conjure up a phantom of the air, it is hardly possible that that
phantom should, without previous concert, assume exactly the same
form and shape; nor was there any after conspiracy between us as
to the manner in which this phantom was to be dressed. Now, my
wife has described to me the dress of the girl, the shreds of a cap
sticking to her hair, the frock of faded pink, the carpet slippers, the
black stockings, and I recognize the faithfulness of these details,
which presented themselves to me exactly as they did to her.
Granted that one mind may be laboring under a delusion, it is hardly
possible that two minds can simultaneously be thus imposed upon.
Answer that, Bob."
"Sympathy," he replied.
"The word I used yesterday evening, when I was imagining what
the doctors would say upon my case; it is an easy way to get out of
it, but it does not satisfy me. I suppose you have come across some
curious cases in looking up apparitions?"
"Some very curious cases. Here is one in which a door, not only
locked but bolted, plays a part. A great Scotch physician relates how
a person of high rank complains to him that he is in the habit of
being visited by a hideous old woman at six o'clock every evening;
that she rushes upon him with a crutch in her hand, and strikes him
a blow so severe that he falls down in a swoon. The gentleman
informs the physician that on the previous evening, at a quarter to
six o'clock, he carefully locked and double bolted the door of the
room, and that then he sat down in his chair and waited. Exactly as
the clock strikes six the door flies wide open--as the door in Lamb's
Terrace did, Ned--and the old woman rushes in and deals him a
harder blow than she was in the habit of doing, and down he falls
insensible. 'How many times has this occurred?' asks the physician.
'Several times,' is the reply. 'On any one of these occasions,' says the
physician, 'have you had a companion with you?' 'No,' the gentleman
replies, 'I have been quite alone.' The physician then inquires at
what hour the gentleman dines, and he answers, five o'clock, and
the physician proposes that they shall dine the next day in the room
in which the old woman makes her appearance. The gentleman
gladly consents; they dine together as agreed upon, and the
physician--who is an agreeable talker--succeeds apparently in
making his host forget all about the apparition. Suddenly, the clock
on the mantelpiece is heard striking six. 'Here she is, here she is!'
cries the gentleman, and a moment afterward falls down in a fit."
"Very curious," I said, "and how does the wise physician account
for the delusion?"
"By the gentleman having a tendency to apoplexy."
"There is, generally," I observed, "a weak spot or two in this kind
of story. Does it say in the account that the door was locked and
bolted when the gentleman and the physician dined together, and
that the door flew open upon the appearance of the old lady?"
"No, it does not say that."
"The omission of the precaution to lock the door," I said, "is fatal,
for the absence of that visible and material manifestation deprives
the physician of the one strong argument he could have brought
forward. Had the door been locked and bolted, and had the old
woman appeared without its flying open, the physician could have
said to the gentleman, 'You see, the door remains fastened, as we
fastened it before we sat down to dinner; you imagined that it flew
open, and there it remains shut, a clear proof that the old woman
and her crutch is but a fevered fancy.' That would have disposed of
this gentleman at once."
"Quite so," said Bob.
"You will, I suppose, admit that if the locked door had opened in
the physician's presence, it would have been a sign that some
spiritual power had been exercised for which he could not so readily
have accounted?"
"Yes, I should admit that."
"Admit, then, that as my wife and I--two witnesses, each
uninfluenced by the other--saw the locked door in Lamb's Terrace fly
open, that that is an evidence of the exercise of a spiritual power."
Bob laughed a little awkwardly. "You have made me give evidence
against myself," he said.
Here there came a knock at the door, and Bob calling "Come in,"
the landlady of the house made her appearance.
"Mr. Elsdale is downstairs," she said, "and was coming up, when I
told him you had a friend with you, and he sent me to ask whether
he would be intruding."
Bob looked at me inquiringly.
"Not so far as I am concerned," I said; "I should very much like to
make your nephew's acquaintance."
"Ask Mr. Elsdale to come up," said Bob; and the landlady
departed.
"I have more than a passing fancy to see your nephew," I said;
"you tell me he has delusions; what he says in our discussion, which
I don't propose to drop when he joins us, may be of interest."
As I spoke Ronald Elsdale entered the room.
"My nephew, Ronald Elsdale," said Bob, introducing us. "My old
friend, Mr. Emery."
As we shook hands my attention was diverted to an incident
which, insignificant as it might appear, struck me as very singular;
the skeleton cat had risen from the hearthrug and was now standing
at Ronald Elsdale's feet, looking up into his face.
CHAPTER X.
RONALD ELSDALE GIVES OPINIONS.
Something more singular than this next attracted my attention.
Ronald Elsdale, blind as he was, inclined his head to the ground and
seemed to be returning the gaze of the cat. "Can it be possible," I
thought, "that this man, physically blind, and this cat, invisible to all
eyes but mine, are conscious of each other's presence?" I put this to
the test.
"You appear to be listening for something," I said.
"Did you bring a dog with you?" he asked. "My uncle, I know,
keeps neither cat nor dog."
"No," I replied, "I brought no dog."
"Then I must be mistaken," he said, and he felt his way to the
seat he was in the habit of occupying in Bob's room. The cat lay at
his feet.
I was prepossessed in the young man's favor the moment I set
eyes upon him. He was tall and fair, a true Saxon in feature and
complexion. There was an engaging frankness in his manner, and his
bearing was that of a gentleman. He aroused my curiosity by a habit
he had of closing his eyes when any earnest subject occupied his
mind. He closed them now as he sat upon his chair, and when he
opened them he said, in a singularly gentle voice, "My uncle has told
you I am blind, Mr. Emery?"
"Yes," I replied; "I sincerely sympathize with you.
"Thank you. It is a great misfortune; but there are
compensations. There are always compensations, Mr. Emery, even
for the worst that can happen to a man."
"It is good if one can think so," I remarked. “As a rule men are
not patient when things are not as they wish."
"It is not only useless to repine," was his reply, "it is foolish, and
morally weak. For, admitting that there is such a principle as divine
justice, we must also admit a divine interposition even in the small
matters of human life. I should not speak so freely if my uncle had
not told me of his early association with you, and of the friendly and
affectionate greeting he received from you after a separation of
nearly forty years. I look upon you already as a friend."
"I am glad to hear you say so; we will seal the compact."
I pressed his hand once more, and he responded as I would have
wished him to respond.
"I knew you would like each other," said Bob.
"When I closed my eyes just now," resumed Ronald Elsdale, "it
was because of the impression I had that there was some other
living creature in the room beside ourselves."
Bob and I exchanged glances, and Bob said:
"We three are the only living creatures within these four walls of
mine."
"Of course, of course. Mr. Emery said so, and it is not likely he
would deceive me. Blind people, Mr. Emery, are generally very
suspicious; it follows naturally upon their affliction. Seeing nothing,
they doubt much, and are ever in fear that they are being imposed
upon and deceived. I am happy to say this is not the case with me;
where I have not a fixed opinion I generally believe what is told me."
A pang of self-reproach shot through me as he spoke. Here was I,
in my very first interview with this frank and ingenuous young
gentleman, deliberately deceiving him. Bob, also, did not seem quite
at his ease. He was playing with his lower lip, always an indication in
him of mental disturbance.
"You said something just now," I observed, with a wish to change
the subject, "about compensations for misfortune, and I infer that
you have compensations for yours. But it must cause you regret?"
"It does, but I do not fret, I do not take it to heart; I accept the
inevitable. The proper use of the higher intelligence with which we
are gifted is to reason calmly upon all human and worldly matters
which touch us nearly. Those who can thus reason have cause for
gratitude; and I have cause. Compensations? Yes, I have them.
Difficult to describe, perhaps, because they are spiritual; inspired by
faith or self-delusion, which stern materialists declare are one and
the same thing."
"Your uncle and I," I said, "were having a discussion upon
delusions when you entered."
"In continuation"--he turned to Bob; he seemed to know always
where the person he was addressing was standing or sitting--"in
continuation of the discussion we were having this afternoon?"
"Yes," said Bob, "and we do not quite agree."
"My uncle is a skeptic," said Ronald, "he does not believe in
miracles."
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com

More Related Content

PDF
Design patterns illustrated-2015-03
PDF
Design patterns illustrated 010PHP
PDF
Your first 5 PHP design patterns - ThatConference 2012
PPT
Design Pattern with Actionscript
PPT
5 Design Patterns Explained
PPTX
Design patterns - The Good, the Bad, and the Anti-Pattern
PPT
Design Patterns and Usage
DOCX
Patterns (contd)Software Development ProcessDesign patte.docx
Design patterns illustrated-2015-03
Design patterns illustrated 010PHP
Your first 5 PHP design patterns - ThatConference 2012
Design Pattern with Actionscript
5 Design Patterns Explained
Design patterns - The Good, the Bad, and the Anti-Pattern
Design Patterns and Usage
Patterns (contd)Software Development ProcessDesign patte.docx

Similar to Learning Php Design Patterns William Sanders (20)

PDF
How I ignored, discovered then loved design patterns - Abdelkader Bouadjadja
PPT
Software Architecture and Project Management module III : PATTERN OF ENTERPRISE
PPT
Design Pattern Zoology
PDF
Beyond design patterns phpnw14
PDF
Design patterns for fun & profit - CoderCruise 2018
PPT
10-DesignPatterns.ppt
PPT
Design patterns represent the best practices used by experienced object-orien...
PDF
10 PHP Design Patterns #burningkeyboards
PPTX
Sofwear deasign and need of design pattern
PPTX
Software System Architecture-Lecture 6.pptx
PPS
Design Patterns For 70% Of Programmers In The World
PDF
DECORATOR PATTERN IN WEB APPLICATION Design
PDF
DECORATOR PATTERN IN WEB APPLICATION
PDF
Oo aand d-overview
PPTX
Go f designpatterns 130116024923-phpapp02
PDF
Design patterns by example
PPTX
PDF
software engineering Design Patterns.pdf
PPT
Software Design Patterns
PPT
Software Design Patterns
How I ignored, discovered then loved design patterns - Abdelkader Bouadjadja
Software Architecture and Project Management module III : PATTERN OF ENTERPRISE
Design Pattern Zoology
Beyond design patterns phpnw14
Design patterns for fun & profit - CoderCruise 2018
10-DesignPatterns.ppt
Design patterns represent the best practices used by experienced object-orien...
10 PHP Design Patterns #burningkeyboards
Sofwear deasign and need of design pattern
Software System Architecture-Lecture 6.pptx
Design Patterns For 70% Of Programmers In The World
DECORATOR PATTERN IN WEB APPLICATION Design
DECORATOR PATTERN IN WEB APPLICATION
Oo aand d-overview
Go f designpatterns 130116024923-phpapp02
Design patterns by example
software engineering Design Patterns.pdf
Software Design Patterns
Software Design Patterns
Ad

Recently uploaded (20)

PPTX
Cell Types and Its function , kingdom of life
PDF
RMMM.pdf make it easy to upload and study
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
PPTX
Final Presentation General Medicine 03-08-2024.pptx
PDF
Abdominal Access Techniques with Prof. Dr. R K Mishra
PPTX
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
PPTX
Cell Structure & Organelles in detailed.
PDF
Anesthesia in Laparoscopic Surgery in India
PDF
102 student loan defaulters named and shamed – Is someone you know on the list?
PDF
TR - Agricultural Crops Production NC III.pdf
PPTX
master seminar digital applications in india
PDF
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
PDF
Complications of Minimal Access Surgery at WLH
PPTX
Lesson notes of climatology university.
PPTX
Pharmacology of Heart Failure /Pharmacotherapy of CHF
PDF
Pre independence Education in Inndia.pdf
PPTX
Pharma ospi slides which help in ospi learning
PPTX
Renaissance Architecture: A Journey from Faith to Humanism
PDF
Microbial disease of the cardiovascular and lymphatic systems
Cell Types and Its function , kingdom of life
RMMM.pdf make it easy to upload and study
O7-L3 Supply Chain Operations - ICLT Program
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
Final Presentation General Medicine 03-08-2024.pptx
Abdominal Access Techniques with Prof. Dr. R K Mishra
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
Cell Structure & Organelles in detailed.
Anesthesia in Laparoscopic Surgery in India
102 student loan defaulters named and shamed – Is someone you know on the list?
TR - Agricultural Crops Production NC III.pdf
master seminar digital applications in india
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
Complications of Minimal Access Surgery at WLH
Lesson notes of climatology university.
Pharmacology of Heart Failure /Pharmacotherapy of CHF
Pre independence Education in Inndia.pdf
Pharma ospi slides which help in ospi learning
Renaissance Architecture: A Journey from Faith to Humanism
Microbial disease of the cardiovascular and lymphatic systems
Ad

Learning Php Design Patterns William Sanders

  • 1. Learning Php Design Patterns William Sanders download https://ebookbell.com/product/learning-php-design-patterns- william-sanders-4068572 Explore and download more ebooks at ebookbell.com
  • 2. Here are some recommended products that we believe you will be interested in. You can click the link to download. Learning Php Design Patterns William Sanders https://ebookbell.com/product/learning-php-design-patterns-william- sanders-52557034 Learning Php Design Patterns 1st Ed Sanders William B https://ebookbell.com/product/learning-php-design-patterns-1st-ed- sanders-william-b-11939214 Learning Php Mysql Javascript Css Html5 A Stepbystep Guide To Creating Dynamic Websites Robin Nixon https://ebookbell.com/product/learning-php-mysql-javascript-css- html5-a-stepbystep-guide-to-creating-dynamic-websites-robin- nixon-50195330 Learning Php Mysql Javascript 7th Edition Early Release Robin Nixon https://ebookbell.com/product/learning-php-mysql-javascript-7th- edition-early-release-robin-nixon-54117148
  • 3. Learning Php Mysql Stepbystep Guide To Creating Databasedriven Web Sites Second Edition Michele E Davis https://ebookbell.com/product/learning-php-mysql-stepbystep-guide-to- creating-databasedriven-web-sites-second-edition-michele-e- davis-2411356 Learning Php Mysql Javascript Early Release 6th Edition Robin Nixon https://ebookbell.com/product/learning-php-mysql-javascript-early- release-6th-edition-robin-nixon-24129590 Learning Php Mysql And Javascript 1st Edition Robin Nixon https://ebookbell.com/product/learning-php-mysql-and-javascript-1st- edition-robin-nixon-2503448 Learning Php Mysql Javascript And Css 2nd Edition Robin Nixon https://ebookbell.com/product/learning-php-mysql-javascript-and- css-2nd-edition-robin-nixon-2618790 Learning Php Mysql Javascript A Stepbystep Guide To Creating Dynamic Websites 6th Edition Robin Nixon https://ebookbell.com/product/learning-php-mysql-javascript-a- stepbystep-guide-to-creating-dynamic-websites-6th-edition-robin- nixon-34241976
  • 8. ISBN: 978-1-449-34491-7 [LSI] Learning PHP Design Patterns by William Sanders Copyright © 2013 William B. Sanders. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are alsoavailableformosttitles(http://my.safaribooksonline.com).Formoreinformation,contactourcorporate/ institutional sales department: 800-998-9938 or corporate@oreilly.com. Editors: Maria Gulick and Rachel Roumeliotis Production Editor: Melanie Yarbrough Copyeditor: Jasmine Kwityn Proofreader: Becca Freed Indexer: Fred Brown Cover Designer: Karen Montgomery Interior Designer: David Futato Illustrator: Rebecca Demarest February 2013: First Edition Revision History for the First Edition: 2013-02-08 First release See http://oreilly.com/catalog/errata.csp?isbn=9781449344917 for release details. Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. Learning PHP Design Patterns, the cover image of an Alaska plaice, and related trade dress are trademarks of O’Reilly Media, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trade‐ mark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
  • 9. In memory of my father, William B. Sanders (1917–2012).
  • 11. Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii Part I. Easing into the Fundamentals of Design Patterns 1. PHP and Object-Oriented Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Entering into Intermediate and Advanced Programming 5 Why Object-Oriented Programming? 6 Making Problem Solving Easier 6 Modularization 7 Classes and Objects 8 Single Responsibility Principle 8 Constructor Functions in PHP 9 The Client as a Requester Class 9 What About Speed? 13 The Speed of Development and Change 13 The Speed of Teams 14 What’s Wrong with Sequential and Procedural Programming? 14 Sequential Programming 14 Procedural Programming 15 Pay Me Now or Pay Me Later 16 2. Basic Concepts in OOP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Abstraction 19 Abstract Classes 20 Abstract Properties and Methods 22 Interfaces 23 Interfaces and Constants 25 Type Hinting: Almost Data Typing 26 Encapsulation 29 v
  • 12. Everyday Encapsulation 29 Protecting Encapsulation through Visibility 30 Getters and Setters 33 Inheritance 34 Polymorphism 36 One Name with Many Implementations 38 Built-In Polymorphism in Design Patterns 39 Easy Does It 39 3. Basic Design Pattern Concepts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 The MVC Loosens and Refocuses Programming 41 Basic Principles of Design Patterns 43 The First Design Pattern Principle 44 Using Interface Data Types in Code Hinting 45 Abstract Classes and Their Interfaces 46 The Second Design Pattern Principle 49 Basic Composition Using a Client 49 Delegation: The IS-A and HAS-A Difference 53 Design Patterns as a Big Cheat Sheet 54 Organization of Design Patterns 54 Choosing a Design Pattern 55 What Causes Redesign? 55 What Varies? 56 What Is the Difference Between Design Patterns and Frameworks? 57 4. Using UMLs with Design Patterns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Why Unified Modeling Language (UML)? 59 Class Diagrams 60 Participant Symbols 61 Relationship Notations 63 Acquaintance Relations 64 Aggregation Relationship 66 Inheritance and Implementation Relations 68 Creates Relations 70 Multiple Relations 71 Object Diagrams 72 Interaction Diagrams 73 The Role of Diagrams and Notations in Object-Oriented Programming 74 Tools for UMLs 75 vi | Table of Contents
  • 13. Other UMLs 75 Part II. Creational Design Patterns 5. Factory Method Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 What Is the Factory Method Pattern? 79 When to Use the Factory Method 80 A Minimalist Example 81 Factory Work 81 The Client 84 Accommodating Class Changes 85 Adding Graphic Elements 85 Coordinating Products 87 Changing the Text Product 88 Changing the Graphic Product 89 Adding New Products and Parameterized Requests 89 One Factory and Multiple Products 90 The New Factories 91 The New Products 92 The Client with Parameters 94 Helper Classes 94 File Diagram 96 Product Changes: Leave the Interface Alone! 96 6. Prototype Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 What Is the Prototype Design Pattern? 99 When to Use the Prototype Pattern 100 The Clone Function 101 Constructor Does Not Relaunch with Clone 102 The Constructor Function Should Do No Real Work 103 A Minimalist Prototype Example 104 Studying Fruit Flies 104 Adding OOP to the Prototype 108 The Modern Business Organization 108 Encapsulation in the Interface 109 The Interface Implementations 110 The Organizational Client 113 Making Changes, Adding Features 116 Dynamic Object Instantiation 117 Table of Contents | vii
  • 14. The Prototype in PHP Land 119 Part III. Structural Design Patterns 7. The Adapter Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 What Is the Adapter Pattern? 123 When to Use the Adapter Pattern 125 The Adapter Pattern Using Inheritance 126 A Minimal Example of a Class Adapter: The Currency Exchange 127 The Adapter Pattern Using Composition 131 From Desktop to Mobile 131 Adapters and Change 140 8. Decorator Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 What Is the Decorator Pattern? 141 When to Use the Decorator Pattern 142 Minimalist Decorator 143 The Component Interface 143 The Decorator Interface 144 Concrete Component 145 Concrete Decorators 146 The Client 148 What About Wrappers? 149 Primitives in Wrappers 149 Built-in Wrappers in PHP 150 Design Pattern Wrappers 151 Decorators with Multiple Components 151 Multiple Concrete Components 152 Concrete Decorators with Multiple States and Values 152 The Developer Dating Service 152 HTML User Interface (UI) 159 The Client Class Passing HTML Data 163 From a Variable Name to an Object Instance 164 Adding a Decoration 165 Part IV. Behavioral Design Patterns 9. The Template Method Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 What Is the Template Method Pattern? 169 When to Use the Template Method 170 Using the Template Method with Images and Captions: A Minimal Example 171 viii | Table of Contents
  • 15. The Abstract Class 171 The Concrete Class 172 The Client 172 The Hollywood Principle 174 Using the Template Method with Other Design Patterns 175 The Client’s Reduced Workload 176 The Template Method Participants 177 The Factory Method Participants 178 The Hook in the Template Method Design Pattern 181 Setting Up the Hook 184 Implementing the Hook 185 The Client and Tripping the Hook 185 The Small and Mighty Template Method 187 10. The State Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 What Is the State Pattern? 189 When to Use the State Pattern? 190 The State Machine 192 Light On, Light Off: The Minimal State Design Pattern 192 Context Is King 193 The States 196 The Client Request through the Context 197 Adding States 198 Changing the Interface 199 Changing the States 199 Updating the Context Class 202 An Updated Client 203 The Navigator: More Choices and Cells 205 Setting Up a Matrix Statechart 205 Setting Up the Interface 206 The Context 207 The States 209 The Client Picks a Path 215 The State Pattern and PHP 218 Part V. MySQL and PHP Design Patterns 11. A Universal Class for Connections and a Proxy Pattern for Security. . . . . . . . . . . . . . . . 221 A Simple Interface and Class for MySQL 221 The Pregnant Interface 222 Universal MySQL Connection Class and Static Variables 223 Table of Contents | ix
  • 16. Easy Client 224 The Protection Proxy for Login 225 Setting Up Login Registration 226 Implementing the Login Proxy 230 The Proxy and Real-World Security 237 12. The Flexibility of the Strategy Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Encapsulating Algorithms 239 Differentiating the Strategy from the State Design Pattern 240 No Conditional Statements, Please 241 A Family of Algorithms 242 A Minimalist Strategy Pattern 242 The Client and the Trigger Scripts 244 The Context Class and Strategy Interface 247 The Concrete Strategies 248 Expanded Strategy Pattern with Data Security and Parameterized Algorithms 251 A Data Security Helper Class 251 Adding a Parameter to an Algorithm Method 254 The Survey Table 254 Data Entry Modules 256 The Client Calls for Help 261 The Minor but Major Change in Context Class 262 The Concrete Strategies 263 The Flexible Strategy Pattern 269 13. The Chain of Responsibility Design Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Passing the Buck 271 The Chain of Responsibility in a MySQL Help Desk 273 Building and Loading the Response Table 273 The Help Desk Chain of Responsibility 278 Automated Chain of Responsibility and Factory Method 284 The Chain of Responsibility and Date-Driven Requests 285 Factory Method Finishes Job 290 Ease of Update 295 14. Building a Multidevice CMS with the Observer Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . 297 Built-In Observer Interfaces 297 When to Use the Observer Pattern 298 Using SPL with the Observer Pattern 300 SplSubject 300 SplObserver 301 SplObjectStorage 301 x | Table of Contents
  • 17. The SPL Concrete Subject 301 The SPL Concrete Observer 303 The SPL Client 304 Free Range PHP and the Observer Pattern 305 The Abstract Subject Class and ConcreteSubject Implementation 306 Observer and Multiple Concrete Observers 307 The Client 309 Making a Simple CMS 311 CMS Utilities 311 The Multiple Device Observer 316 Thinking OOP 330 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Table of Contents | xi
  • 19. Preface As PHP expands to become the server-side program of choice among a significant portion of programmers, professional techniques and programming structures need to be incorporated. Design patterns, a concept borrowed from The Timeless Way of Build‐ ing by Christopher Alexander (Oxford University Press), refers to a general reusable solution to a commonly occurring problem within a given context. In everyday develop‐ ment work, PHP programmers encounter “commonly occurring problems” in a soft‐ ware development context, and the use of PHP design patterns is a set of solutions to “commonly occurring” PHP programming problems. Pure and simple, PHP design patterns are tools used to deal with the reality of professional software development. They are not libraries or templates but rather more general structures that can be used to solve problems. I like to think of design patterns in the same way as I do the loop structure. The loop is used when some kind of iteration is required. True, there are other ways to deal with iteration, but a loop is a flexible tool that saves time in the development process. (Besides, it’s a lot neater than writing the same line of code 10,000 times!) Further, I do not feel constrained by design patterns as “canned solutions” any more than a loop is a “canned solution” to iteration. Besides, I can use the loop structure in a varietyofwaysinPHPrangingfromfortowhilestatementsandeverythinginbetween. Likewise, design patterns can be implemented in more than one way depending on the exact nature of the problem being solved. The most important reason for incorporating design patterns, though, is that they provide solutions to complex problems. As one’s programs become larger, they almost necessarily become more complex. In an object-oriented programming (OOP) envi‐ ronment, such complexity is reduced somewhat, as you are dealing with encapsulated modules, whereas in sequential or procedural programming, any changes can bring the program crashing down like a house of cards. Design patterns bring not only solutions to general programming problems, but they also allow changes to be made in large complex programs by providing loose coupling between objects. So when a change is made, instead of having to start programming all over from scratch, you can just add xiii
  • 20. the necessary changes and everything keeps chugging along—even in large, complex programs. Further, design patterns are meant for reuse. After all, programmers reuse the same algorithms all the time. Why not use larger structures as well? On the one hand, frame‐ works and templates serve to make reuse practical, but they are often too specific. That’s where reuse of design-patterned PHP programs comes in, especially in the case of large, complex programs. Because making changes is easy with design patterns, reuse for specific problems of the same kind is easy as well. Reducing developmental time and resourcessavesmoneyandbetterservesyourclients.Theygetwell-structuredprograms thatdowhattheclientswant,they’reeasyforthedeveloperstochange(customersalways want change!), and they have strong foundations that are not as likely to fail. Audience At some point, all good programmers realize that they need to get out of a sequential and procedural programming rut. The next logical step is object-oriented program‐ ming, and moving into OOP requires a shift in perspective: instead of seeing program‐ ming as a series of statements, it must be seen as an interaction and communication between objects. Beyond OOP lie design patterns, where OOP principles are recast into patterns of reusable code. There you will find the tools of professional programmers. Because design patterns for programming were developed in cooperation between aca‐ demics and businesses, the concepts both transcend single problems while at the same time possessing business-like practicality. Learning PHP design patterns is for profes‐ sional programmers who want to optimize their own time in development and rede‐ velopment and provide their clients with high-quality code. In no small measure, this book is for those who felt a certain delight when programming was new to them. This is for the developer who thought nothing of working on a pro‐ gram all night long just because it was interesting, staggering off to bed, only to start on another program as soon as he woke up. When programming is new and every day promises a new discovery or a bug that challenges the developer to a fight to the death, and you must use your mind in complex and exciting ways, the experience can be Zen- like. If you’ve had that experience, you’ll know what I mean. It cannot be spelled out or explained analytically. (I can’t even explain it to myself, and I have no idea why I enjoy the kinds of challenges and rewards found in programming.) Design patterns reintroduce mental challenges, and this book is not for someone who is new either to PHP or to programming. If you’re learning PHP for the first time, take a look at Robin Nixon’s book, Learning PHP, MySQL, JavaScript, and CSS, 2nd Edition (O’Reilly) before tackling PHP design patterns. Likewise, this book (or any decent book on design patterns) does not promise that you’ll master design patterns quickly and easily. This kind of learning is a journey, and the wisest counsel is to learn to enjoy the journey. It takes time and mental effort. xiv | Preface
  • 21. Assumptions This Book Makes This book assumes that you know how to program in PHP and want to take your pro‐ gramming skills to the next couple of levels. In fact, it assumes that you’re a pretty good PHP programmer and you’ve used MySQL and know how to develop HTML pages and use CSS. It also assumes that you understand that learning PHP design patterns is not going to happen in a lazy afternoon. Learning design patterns is akin to a gradual metamorphosis. Contents of This Book This book is organized into five parts. Part I is an OOP refresher/introduction: Chapter 1 introduces object-oriented programming (OOP) and how to more easily handle complex programming problems with modularization. Chapter 2 discusses basic concepts in OOP such as abstraction, encapsulation, in‐ heritance, and polymorphism, as well as the PHP structures that implement these concepts. Chapter 3 moves on to examine the basic concepts in design patterns, their cate‐ gorization, and how specific patterns are selected to handle specific problems. Chapter 4 introduces Unified Modeling Language (UML) and explains how it will be employed in this book. Part II covers creational design patterns: Chapter 5 examines the Factory Method, which has a creational purpose and a class scope. Examples include dynamically creating pages that display graphics, body text, and header text. Chapter 6 shows how to use the Prototype pattern, which has a creational purpose and an object scope. The Prototype pattern is used when a single object is created as a prototype and then cloned to economically create further instances. Part III explains structural design patterns: Chapter 7 illustrates how to use the Adapter pattern in both class and object scopes. Examples show how to take an existing structure and make changes that allow the developer to add new functionality. Chapter 8 explains how an existing object can be changed without disrupting a larger program using the Decorator pattern. You’ll see how to decorate male and female dating objects with different preferences in a dating site. Preface | xv
  • 22. Part IV looks at behavioral design patterns: Chapter9showshowtousetheTemplateMethodpattern—oneoftheeasiestdesign patterns to both create and use. In addition, you will see how the famous Hollywood Principle operates in design pattern programming. As a final feature of the chapter, two different patterns are combined to solve a single problem. Chapter 10 presents the State design pattern along with how to use statecharts to map state processes and changes. Part V introduces four more behavioral design patterns used in conjunction with MySQL: Chapter 11 provides the Universal connection class and the Proxy design pattern for adding security to usernames and passwords stored in a MySQL database. Chapter 12 explains how the Strategy design pattern is significantly different from the State pattern even though they have identical class diagrams. A survey example illustrates how the Strategy pattern can be used with different MySQL requests. Chapter 13 has multiple examples of how the Chain of Responsibility pattern can be used, ranging from a Help Desk to automatically responding to a date timer to display (in conjunction with the Factory Method pattern) images and text. Chapter 14 is the first to explore how to use the PHP built-in design pattern inter‐ faces. The Observer design pattern can use interfaces from the Standard PHP Li‐ brary.AnotherexampleusestheObserverdesignpatternwithhand-builtinterfaces to make a simple content management system (CMS) with PHP and MySQL. Conventions Used in This Book The following typographical conventions are used in this book: Italic Indicates new terms, URLs, email addresses, filenames, and file extensions. Constant width Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords. Constant width bold Shows commands or other text that should be typed literally by the user. Constant width italic Shows text that should be replaced with user-supplied values or by values deter‐ mined by context. xvi | Preface
  • 23. This icon signifies a tip, suggestion, or general note. This icon indicates a warning or caution. Using Code Examples This book is here to help you get your job done. In general, if this book includes code examples, you may use the code in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of ex‐ ample code from this book into your product’s documentation does require permission. We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Learning PHP Design Patterns by William Sanders (O’Reilly). Copyright 2013 William B. Sanders, 978-1-449-34491-7.” If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at permissions@oreilly.com. Safari® Books Online Safari Books Online (www.safaribooksonline.com) is an on-demand digital library that delivers expert content in both book and video form from the world’s leading authors in technology and business. Technology professionals, software developers, web designers, and business and crea‐ tive professionals use Safari Books Online as their primary resource for research, prob‐ lem solving, learning, and certification training. Safari Books Online offers a range of product mixes and pricing programs for organi‐ zations, government agencies, and individuals. Subscribers have access to thousands of books, training videos, and prepublication manuscripts in one fully searchable database from publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley Professional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Preface | xvii
  • 24. Technology, and dozens more. For more information about Safari Books Online, please visit us online. How to Contact Us Please address comments and questions concerning this book to the publisher: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-998-9938 (in the United States or Canada) 707-829-0515 (international or local) 707-829-0104 (fax) We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at http://oreil.ly/php_design_patterns. To comment or ask technical questions about this book, send email to bookques tions@oreilly.com. For more information about our books, courses, conferences, and news, see our website at http://www.oreilly.com. Find us on Facebook: http://facebook.com/oreilly Follow us on Twitter: http://twitter.com/oreillymedia Watch us on YouTube: http://www.youtube.com/oreillymedia Acknowledgments I want to thank everyone who helped out in one way or another. My colleagues at the University of Hartford’s Multimedia Web Design and Development program were al‐ ways helpful when I posed a query of one type or another. Professor John Gray, the department chair, was encouraging and helpful as always. Dr. Brian Dorn, my office next-door neighbor, who caught the bulk of my queries, was obliging, knowledgeable, and patient. I was fortunate enough to meet Michael Bourque of the Boston PHP group at the in‐ augural Northeast PHP Conference, and appreciate his encouragement for this project. I look forward to working with Michael and the Boston PHP group more in exploring advanced PHP programming. O’Reilly Media provided three capable technical reviewers. Robin Nixon, author of Learning PHP, MySQL & JavaScript, 2nd Edition (O’Reilly) offered corrections, sug‐ gestions, and several insights into PHP to make the code better in many different ways. xviii | Preface
  • 25. Aaron Saray, author of Professional PHP Design Patterns (Wrox) was incredibly detailed and generous in his suggestions. He has a wonderful editor’s eye for even the slightest flaw. Aaron and I take very different approaches to design patterns, but such differences provide a wider view for PHP developers interested in design patterns. Finally, Dmitry Sheiko acted as a passionate technical reviewer and has his own blog where his take on PHP design patterns can be found. Senior Editor Rachel Roumeliotis at O’Reilly Media put all of the many parts together and moved the project along. Maria Gulick, another capable O’Reilly editor, took care of the bits and pieces as the project went through revisions. Copyeditor Jasmine Kwityn found and corrected details I did not know existed—in this galaxy or any other. The whole process was initiated by Margot Maley Hutchison at Waterside Productions, and I am grateful to her as ever. My wife Delia was more understanding than most spouses since she recently had pub‐ lished a book of her own and knew the process. Our Greater Swiss Mountain Dog, WillDe, could care less about writing processes. As long as he got his treats, he’d go along with anything. Preface | xix
  • 27. Allcompromiseisbasedongiveandtake,butthere can be no give and take on fundamentals. Any compromise on mere fundamentals is a surrender. For it is all give and no take. —Mahatma Gandhi People talk fundamentals and superlatives and then make some changes of detail. —Oliver Wendell Holmes, Jr. An unfortunate thing about this world is that the good habits are much easier to give up than the bad ones. —W. Somerset Maugham PART I Easing into the Fundamentals of Design Patterns Programming Habits For years after I started programming regularly, I developed certain habits that changed from sequential to procedural programming and just cruised along on a combination of those two for years. This was due in part to the explorations of different languages. My first was Fortran II in college, then on to Basic, FORTH, PostScript, and then into assembly and machine language. I was more interested in learning about different languages than I was in good programming. Then with the Internet came Java, JavaScript, PHP, C#, and ActionScript 3.0, among others. Most of these languages were
  • 28. based (in part) on the kinds of structures found in C++. These were different languages, but I maintained the same old habits. Quite by accident, I was introduced to state machines by Dr. Jonathan Kaye. Instead of thinking in terms of flow of control, he showed me how to think in terms of different states. Following state machines, I discovered the State design pattern and then Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley). The examples in Design Patterns were all written in SmallTalk or C++. Knowing no SmallTalk and very little C ++, I was forced to concentrate on the conceptual materials. Oddly, that was one of the best things that could have happened because I was not stuck with examples in any particular language. When it came to PHP, it wasn’t a matter of translating from Small‐ Talk to PHP but applying object-oriented programming (OOP) and design pattern concepts directly to PHP. Slowly but surely, my programming habits began to change. By adding a little OOP here and there and incorporating a design pattern now and again, in time, I didn’t want to program any other way. According to psychologists, a habit is formed over a period of 66 days on average, but in my case, the change took longer and it was more gradual. It was a very busy development period for me, and when the choice was between getting aprojectdoneforacustomerandusingOOPanddesignpatterns,timepressuresalways won out. However, more and more OOP was creeping in my habitual coding practices, and before I knew it, my customers were getting solid OOP and design pattern- developed applications. The four chapters in this first section are designed to get you started on the OOP path: • PHP and Object-Oriented Programming • Basic Concepts in OOP • Basic Design Pattern Concepts • Using UMLs with Design Patterns Focus on Substance, Not Style Most of the good programmers I know have a certain style that points to professional programming habits. By and large, when you encounter good OOP programming, you’ll see a certain way of doing everything from naming variables to commenting code. Variable names are clear, and comments in the code tell the story of the code so that other programmers know how to connect to their own modules. In this book, the com‐ ments in the code have been kept to a minimum because that job is done by the book’s text. Further, I have often found that putting in too many comments get in the way of clearly seeing the structure of the code. So, with the goal of being able to see and sense objects as complete entities, the code is not fractionalized by long-winded comments.
  • 29. (In programs not written for books, I subscribe to the idea that substantive commenting is essential.) For some reason, PHP seems to be plagued by bad examples of design patterns. By bad, I’m not talking about dumb examples. I’m referring to design patterns written with missing parts. For example, a Strategy pattern written without a Context participant is a bad example. It is simply inaccurate. The same is true for any pattern that has missing parts. It’s like writing a loop that has no termination condition. The Strategy pattern requires a Context just like a loop structure requires a termination condition. In order to keep the focus as accurate as possible, I’ve used the original source of the design patterns discussed in this book: Design Patterns: Elements of Reusable Object- Oriented Software (Prentice Hall). Further, the Uniform Modeling Language (UML) is the one used in Design Patterns. Newer versions of the UML (UML2) have come along since then, but for learning PHP design patterns, and for understanding ones not dis‐ cussed in this book, learning to use the original will help if you want to learn additional patterns from the original source.
  • 31. All the forces in the world are not so powerful as an idea whose time has come. —Victor Hugo Do not pray for tasks equal to your powers. Pray for powers equal to your tasks. —Phillips Brooks Immense power is acquired by assuring yourself in your secret reveries that you were born to control affairs. —Andrew Carnegie Ignorance is the curse of God; knowledge is the wing wherewith we fly to heaven. —William Shakespeare CHAPTER 1 PHP and Object-Oriented Programming Entering into Intermediate and Advanced Programming When we first learn to read, the stories, vocabularies, and words tend to be small and simple. Dealing with small and simple stories requires small and simple tools. However, when we are more advanced and introduced to the works of William Shakespeare, we need a more complex, larger, and more sophisticated toolset. If a kindergarten teacher handed her brood Hamlet, chances are the kids wouldn’t understand it, but if they are given an incremental set of reading tools over the years, by the time they reach high school, they can read, understand, and appreciate Hamlet. This book is for developers who are ready to read the PHP version of Hamlet. To get what you need from this book, you need to begin with an understanding of and experience with PHP. Other books in this series, Learning PHP 5 by David Sklar and Learning PHP, MySQL, and JavaScript, 2nd Edition, by Robin Nixon (O’Reilly) are good 5
  • 32. places to start if you have no PHP experience. Of course, you may have learned PHP from any number of other books, courses, or online tutorials. What matters is that you knowhowtoprograminPHP.Further,we’regoingtobedealingwithPHP5andnothing earlier, like the last version of PHP 4 (PHP 4.4.9). That’s because just about everything we need for object-oriented programming (OOP) wasn’t implemented until PHP 5. Why Object-Oriented Programming? Although OOP has been around for more than 40 years, it was not until the last 15 years or so that it’s become more and more important. In large measure, this is due to the influence of Java, which includes built-in OOP structures. Newer languages associated with the Internet, such as JavaScript, ActionScript 3.0, and PHP 5, also have incorpo‐ rated OOP in style or structure. In 1998, JavaScript Objects by Alexander Nakhimovsky and Tom Myers (Wrox), two Colgate University professors, showed that OOP could be incorporated into JavaScript. So OOP is nothing new, even for those whose main pro‐ gramming has been in the realm of Internet languages, and we can even say that it is a “tried and proven” method of programming in most languages designed to give in‐ structions to computers. Spending some time understanding OOP is important because understanding design patterns relies on understanding OOP. So while you may have substantial experience programming in PHP 5, if you do not have OOP experience, spend some time in Part I. Making Problem Solving Easier Computer programs are designed to solve human problems. A process called dynamic programming is a technique for breaking down larger problems into smaller ones. The planistosolveeachsmallerproblemandthenputeverythingbacktogetherintoasingle, larger solution. Take, for example, planning a trip to Timbuktu. (It doesn’t sound like a complex problem, but see if you can find a flight from your town to Timbuktu on an online travel site.) Let’s break it down: 1. Does Timbuktu (aka Tombouctou or Timbuctu) exist? (Yes./No.) Answer = Yes. 2. Does Timbuktu have an airport? (Yes./No.) Answer = Yes, Airport Identifier = TOM. 3. Are there flights into TOM? (Yes./No.) Answer = Maybe. Flights are available from both Bamako and Mopti, but Islamist rebels took control of Timbuktu as of July 1, 2012, and flights have been canceled until further notice. 4. Are hostile rebels in control of Timbuktu now? (Yes./No.) If answer = Yes, there are no flights. If answer = No, there may be flights. 5. If flights are available, is Timbuktu safe for tourism or business? (Yes./No.) Answer = No. 6 | Chapter 1: PHP and Object-Oriented Programming
  • 33. 6. ArevisasfrommycountryintoMali(countrywhereTimbuktuislocated)available? (Yes./No.) Answer = Yes. 7. Are vaccinations required? (Yes./No.) Answer = Yes. As you can see, getting to and from Timbuktu is a complex issue, but the list of simple questions can all be answered by yes or no. Lots more questions would be included in the list, but each can be answered in a binary fashion. The “maybe” answer means that more questions need to be asked to get a yes/no answer. Modularization The process of decomposing a problem into small subproblems is the process of mod‐ ularization. Just like the complexities of getting from your home to Timbuktu can be modularized into a set of yes/no steps, any other complex problem also can be modu‐ larized. Figure 1-1 illustrates this process. Figure 1-1. Even the most complex problem can be broken into modules Inlookingatmodularization,youmaybethinkingthatitdoesn’tlooktoodifficult.You’d be absolutely right. The more complex the problem, the more it makes sense to mod‐ ularize it. So, the initial reasoning in OOP programming, far from being complex, sim‐ plifies the complex. Even the most daunting programming problem can be solved by this divide-and-conquer strategy. Why Object-Oriented Programming? | 7
  • 34. Classes and Objects Once a problem is modularized, what are you going to do with the modules? As you saw,breakingdownacomplexproblemcantransformitintomanysimplesubproblems, but you need a way to organize the modules and work with them in relation to each other to handle the larger problem being solved. One way to look at a module is as a collection of related functions. In programming, these modules are called classes. A class itself is made up of parts called properties and methods. The properties are different types of data objects like numbers, strings, nulls, and Booleans. Generally, the data are stored as abstract data types known as variables, constants, and arrays. Meth‐ ods, on the other hand, are functions that operate on the data. Single Responsibility Principle One way to think of a class is as a collection of objects with common characteristics. The “commonness” of characteristics does not mean that they are the same, but instead they deal with the common problem assigned to the module—the class. Keeping in mind that the purpose of a module is to solve some aspect of a more complex problem, we arrive at one of the first principles of object-oriented programming: the single re‐ sponsibility principle, which states that a class should have only a single responsibility. It’s not that a class cannot have multiple responsibilities, but keep in mind that we broke down a complex problem into simple modules so that we’d have several easy-to-solve problems. By limiting a class to a single responsibility, we not only remind ourselves of why we modularized the problem, but we also have an easier way of organizing the modules. Let’s look at a class with a single responsibility. Suppose you’re making a web‐ site for a client, and because the site is to be viewed by different devices ranging from desktops to tablets to smartphones, you want to have some way of determining what type of device and which browser is used to view your web page. With PHP, it’s easy to write a class that provides that information using the built-in array $_SERVER and the related element, HTTP_USER_AGENT. The TellAll class in the following listing demon‐ strates a class with a single responsibility—to provide information about the user agent viewing the PHP page: <?php //Saved as TellAll.php class TellAll { private $userAgent; public function __construct() { $this->userAgent=$_SERVER['HTTP_USER_AGENT']; echo $this->userAgent; } 8 | Chapter 1: PHP and Object-Oriented Programming
  • 35. } $tellAll=new TellAll(); ?> Loading this class through a Safari browser on an iMac displays the following: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/ 534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2 When tested on an iPad using an Opera Mini browser, the results are different: Opera/9.80 (iPad; Opera Mini/7.0.2/28.2051;U;en) Presto/2.8.119 Version/11.10 The class represents a module of a more complex operation, of which the class is only asinglepart.LikeagoodclassinOOP,ithasasingleresponsibility—findinginformation about the user agent. Constructor Functions in PHP A unique feature of PHP classes is the use of the __construct() statement as a con‐ structor function. Most computer languages use the name of the class as the constructor function name; however, using the __construct() statement removes all doubt as to the function’s purpose. The constructor function in a class automatically launches as soon as the class is in‐ stantiated. In the TellAll class, the results are immediately printed to the screen, whether you want them there or not. For demonstration purposes, that’s fine, but as a module, other modules may simply want to use the information about the device and/ or the browser. So, as you will see, not all classes include a constructor function. The Client as a Requester Class In the TellAll class, I included a little trigger at the bottom to launch the class. With the exception of the Client class, self-launching is not recommended. In your experi‐ ence with PHP, you most likely launched a PHP program from HTML using a form tag something like the following: <form action="dataMonster.php" method="post"> So, you’re familiar with launching a PHP file from an external source. Similarly, PHP files containing classes should be used by other modules (classes) and not self-launched. As we get more into design patterns, you’ll find a class named Client keeps appearing. The Client has different roles in the larger project, but the primary one is to make requests from the classes that make up the design pattern. Here, the Client is shown in relation to a revised version of the TellAll class. This new class used by the Client is different in several ways from TellAll that are more useful to an overall project and The Client as a Requester Class | 9
  • 36. reusable in other projects. The MobileSniffer class begins with the same user agent information, but the class makes it available in more useful ways with its properties and methods. Using a Unified Modeling Language (UML) diagram you can see that the Client instantiates (dashed arrow) the MobileSniffer. Figure 1-2 illustrates a simple class diagram of the two classes. Figure 1-2. Client class instantiates MobileSniffer class and can use its properties and methods Had a Client class instantiated automatically, the Client would have fewer options for how to use the MobileSniffer information. Take a look at the following listing to see how to create the class: <?php //User agent as property of object class MobileSniffer { private $userAgent; private $device; private $browser; private $deviceLength; private $browserLength; public function __construct() { $this->userAgent=$_SERVER['HTTP_USER_AGENT']; $this->userAgent=strtolower($this->userAgent); $this->device=array('iphone','ipad','android','silk','blackberry', 'touch'); $this->browser= array('firefox','chrome','opera','msie','safari', 'blackberry','trident'); $this->deviceLength=count($this->device); $this->browserLength=count($this->browser); } public function findDevice() { for($uaSniff=0;$uaSniff < $this->deviceLength;$uaSniff ++) { if(strstr($this->userAgent,$this->device[$uaSniff])) { 10 | Chapter 1: PHP and Object-Oriented Programming
  • 37. return $this->device[$uaSniff]; } } } public function findBrowser() { for($uaSniff=0;$uaSniff < $this->browserLength;$uaSniff ++) { if(strstr($this->userAgent,$this->browser[$uaSniff])) { return $this->browser[$uaSniff]; } } } } ?> Embedding Error Reporting in the php.ini File I work in a university environment where the system administrators often are students (withvaryinglevelsofknowledgeandcompetence),stillhoningtheircraft.Often,they’ll forget to set the php.ini file to report errors. As a result, I got into the habit of adding the following lines to the beginning of my code: ini_set("display_errors","1"); ERROR_REPORTING(E_ALL); For some, such added lines of code are annoying, but I include them in the Client class to provide a reminder of how important error reporting is in developing applications where feedback is essential. Learning OOP and design patterns relies heavily on such feedback. InordertousetheMobileSniffer,theClientinstantiatestheclassandusesitsmethods as shown in the following listing: <?php ini_set("display_errors","1"); ERROR_REPORTING(E_ALL); include_once('MobileSniffer.php'); class Client { private $mobSniff; public function __construct() { $this->mobSniff=new MobileSniffer(); echo "Device = " . $this->mobSniff->findDevice() . "<br/>"; echo "Browser = " . $this->mobSniff->findBrowser() . "<br/>"; The Client as a Requester Class | 11
  • 38. } } $trigger=new Client(); ?> Using the Client class provides a way to make the MobileSniffer class more useful. The MobileSniffer does not have to launch itself, and using a return statement, any class that calls MobileSniffer just gets the data. The Client can then use that data in any way it wants. In this case, the Client formats the data to output it to the screen, as you can see in Figure 1-3. Figure 1-3. The Client uses the MobileSniffer’s data to send to the screen We could have formatted the data in the MobileSniffer class, but then it would not have been as flexible or useful. By allowing the Client to use the data in the most general way, it could do any number of things with it. For example, instead of formatting the data for screen output, it could have used the data to call a CSS file that formats for the particular device and/or browser. Had the data been preformatted in the MobileSniff er class, using it for identifying a CSS file would require stripping away the unneeded formatting. Keep in mind that one of the most important features of design patterns is reuse of the objects. 12 | Chapter 1: PHP and Object-Oriented Programming
  • 39. Capturing Mobile: Nailing Jelly to a Tree At the time of this writing, the number and type of mobile devices just keeps growing, andanycodeyouwriteinPHPisboundtoletsomedevicesand/orbrowsersslipthrough the net. Even capturing the device may not be enough because some (like the iPad and the iPad Mini) have different screen resolutions in addition to different screen sizes. Suffice it to say that if you plan to create web pages for viewing on different devices, you will want a module in your system that can be updated without breaking your program. So, no matter what the latest technique is to detect and respond to multiple devices, be prepared for change. You can plan to start all over from scratch to incorporate new devices, such as Microsoft’s Surface, or you can be prepared with a module that can be incorporated into an existing application where changes will not break the system. At this point, you may be thinking, “I could write a better algorithm for sorting out devices and browsers.” You probably could, and in fact, you’ll probably have to because as new devices and browsers are introduced, they will have to be incorporated into a program that needs to use device/browser information. However, if you preserve the structure of the two methods, findDevice() and findBrowser(), you can make all the changes and improvements you want, and the larger program will not crash. You must imagine a much larger and more complex program and think about making changes. If you’ve ever had to revise a larger program, you know that a change can worm its way through the entire program and break it. Then your debugging becomes a nightmare. OneofthemainfunctionsofOOPanddesignpatternsisthecapacitytochangeamodule without breaking the entire program. What About Speed? Just about every programmer wants a program to run at optimum speed, and to do that, welookatthebestalgorithms.Fornow,though,weneedtoshiftourattentiontoanother kind of speed—the amount of time it takes to create and update a program. If a program cycles through an operation 100 million times, minor speed tweaks of that operation are important, but trying to squeeze a couple of microseconds from an operation that’s used only once can be an expensive use of time. Likewise, having to revise an entire program because of a few lines of added code is an equally expensive use of time. The Speed of Development and Change Consider a contract you have to update and maintain a program for a customer. You have negotiated a set amount for ongoing updates, and you want both to satisfy your client and to spend a fair but limited amount of time on updates. For example, suppose your customer has weekly sales on different products requiring ongoing text and image What About Speed? | 13
  • 40. updates. One solution may be to set up a weekly update using the time() function, and then all you have to do is add the most current image URL and text to a database. In fact, if you had the text and images ahead of time, you could go on vacation and let the PHP do the work while you’re away. That would be a sweet maintenance deal, and you could keep several customers happy simultaneously. Would you ever consider setting up a maintenance system where you had to rewrite the program every time you had to make a change? Probably not. That would be a very slow and expensive way of doing things. So where speed of revision is important, your pro‐ gram needs to consider the speed of both operation and development. Algorithms han‐ dle speed of operations, and design patterns handle speed of development. The Speed of Teams Another speed issue can be found in working with teams. When dealing with larger and more complex programs, teams need to agree on and understand a common plan and goal to effectively and efficiently create and maintain large programs. Among other things, OOP and design patterns provide a common language to speed along group work. References to “factories,” “state machines,” and “observers” all mean the same thing to those who understand OOP and design patterns. Most importantly, design patterns provide a way of programming so that a team of programmers can work on separate parts that will go together. Think of an assembly line making automobiles—each team assembles a different part of the car. To do that, they need a pattern of development and an understanding of the relationship of one part to another. In this way, everyone can do their job knowing that someone else’s job will fit with their work. They don’t have to know the details of another worker’s job. They just need to know that they’re working from the same plan. What’s Wrong with Sequential and Procedural Programming? “If it ain’t broke, don’t fix it” is a widely believed sentiment, and you may immediately agree with it if a solution works. However, such a mindset is the antithesis of progress and improvement. After all, for getting from one place to another, walking works just fine. However, for getting from one side of the country to the other, flying in a jet works much better. OOP and design patterns are improvements over sequential and proce‐ dural programming in the same way as flying is to walking. Sequential Programming Mostprogrammersbeginprogrammingbywritingonestatementafteranothertocreate a series of lines that will execute a program. For example, the following is a perfectly good PHP sequential program that works: 14 | Chapter 1: PHP and Object-Oriented Programming
  • 41. <?php $firstNumber=20; $secondNumber=40; $total= $firstNumber + $secondNumber; echo $total; ?> The variables are abstract data types, and the arithmetic add operator (+) combines the values of two variables into a third variable. The echo statement prints out the total of the combined values to the screen. Adding two numbers is a simple problem for PHP, and as long as you deal with simple problems, you can use simple solutions. Procedural Programming As programmers began to write longer and longer programs with more complex tasks, the sequences began to be entangled into what was called spaghetti code. A GOTO state‐ ment would allow sequential programmers to jump around in a program to complete a procedure, and so it was easy to become entangled. With procedural programming came the function. A function is a little object where an operation can be called to perform a sequence with a single statement. For example, the following is a procedural version of the sequential program shown in the previous listing: <?php function addEmUp($first,$second) { $total=$first + $second; echo $total; } addEmUp(20,40); ?> Thefunctions(orprocedures)allowprogrammerstogroupsequencesintomodulesthat can be reused in a program. Further, by having parameters, the programmer can enter different arguments into a function so that it can be used with different concrete values. Like OOP, procedural programming uses modularity and reuse. However, procedural programming does not provide for classes where programming tasks can be bundled intoobjects.Classobjects(instancesofclasses)canoperateontheirowndatastructures, and that cannot be done by functions alone. As a result, procedural programming re‐ quires long sequences to accomplish large tasks. Further, working in teams is more What’s Wrong with Sequential and Procedural Programming? | 15
  • 42. difficult with procedural programming because different team members cannot easily work on independent but interrelated classes, as can be done with OOP. Pay Me Now or Pay Me Later A while ago, I published a blog post titled “No Time for OOP and Design Patterns.” The post was in reaction to a number of developers who said reasonably that they did not have time to incorporate OOP or design patterns into their work even though they wanted to do so. They explained that a project would come along with a clear deadline, and in an effort to get it done on time, they’d cobble together a working program using sequential and procedural programming. Maybe they’d include a class or two if they had one that met a particular goal, but that was it. In learning OOP and design patterns for PHP, you need to remember a couple of points, which were first made by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlis‐ sides in Design Patterns: Elements of Reusable Object-Oriented Software: • Designing object-oriented software is hard. • Designing reusable object-oriented software is even harder. RatherthanlookingatthosestatementsasreasonsnottolearnOOPanddesignpatterns, they stand as reasons why OOP and design patterns are so valuable. Knowledge adds value to any skillset. The more difficult the knowledge is to obtain, the more it is valued. Don’t expect to pick up OOP and design patterns easily and quickly. Rather, incorporate them a little at a time into your PHP programming. At some point you will see the value. Over time, you will develop more skills and understanding, and you will run into a project where you can reuse most of the program structures from a previous project. In a recent project, I decided to use a Strategy design pattern. It included a table with 105 fields, and the customer wanted a certain set of functionalities. By using a Strategy design, each of the strategies was a class with an algorithm to handle a fairly mundane PHP problem—filtering, updating, and deleting data in a MySQL database. It took a while to set it up, but once it was configured, it was easy to change (customers always wantchange!).Sometimelater,Iwasaskedtodoasimilarkindofprojectusingfrontend and backend PHP with a MySQL database. Rather than starting over from scratch, I just pulled out the Strategy pattern, changed the algorithms, and had it up and running in no time. I got paid the same, but having worked smart, my customer got a much better piece of software than had I worked longer and dumber. At some point, we have to stop our old habits and upgrade our skills. At this point in time, many programmers are updating their skills to accommodate mobile devices. If they do not, they’ll lose out on many opportunities—eventually they may render their skills obsolete. Over time, we know that we’ll have to update our skills to incorporate the benefits of the latest PHP release, new technology, or direction the industry takes. 16 | Chapter 1: PHP and Object-Oriented Programming
  • 43. OOP and design patterns contain concepts that transcend all of these changes, make us better programmers, and provide our customers with better software. It all starts with a first step. By taking the time now, you won’t be scrambling for time to get a project done in the future. Besides, you will come out of the process as a better programmer, and that in and of itself is reason enough to learn OOP and design patterns. Above all, learning OOP and design patterns is the pleasure of doing something well. What’s Wrong with Sequential and Procedural Programming? | 17
  • 45. Two elements are needed to form a truth—a fact and an abstraction. —Remy de Gourmont Beware how you trifle with your marvelous inheritance, this great land of ordered liberty, for if we stumble and fall, freedom and civilization everywhere will go down in ruin. —Henry Cabot Lodge Everybody gets everything handed to them. The rich inherit it. I don’t mean just inheritance of money. I mean what people take for granted among the middle and upper classes, which is nepotism, the old-boy network. —Toni Morrison Our normal waking consciousness, rational consciousness as we call it, is but one special type of consciousness, whilst all about it, parted from it by the filmiest of screens, there lie potential forms of consciousness entirely different. —William James CHAPTER 2 Basic Concepts in OOP Abstraction If you’re new to OOP, don’t expect everything to make sense right away. As you use OOP more and more, you’ll experience little “aha!” moments when the pieces begin to come together. PHP does have important OOP features, and it has its own way of implementing these features in the language. If you are familiar with other OOP lan‐ guages, you can be assured that PHP is different in places—like allowing constants to 19
  • 46. be a part of an interface. Understanding abstraction is a cornerstone in both OOP and design patterns, and the more you use it, the more sense it makes. The notion of abstraction is so essential to both object-oriented programming and design patterns that it bears more than a fleeting consideration. The general idea of abstraction in computing is not unlike the abstractions we use every day in natural language. For example, the word dog denotes a phenomenon that has dog-like charac‐ teristics. If someone says, “look at the dog,” they use the abstraction of dog (in other words, the word dog) to indicate a concrete instance of an animal with dog-like features. By using the words dog and cat, we can differentiate one from the other and point to lots of different dogs and cats. However, if we use the word “dog” to indicate a cat, we may be corrected. “That’s not a dog. It’s a cat.” So while abstractions are general, they are specific enough so that we can differentiate specific instances. In Object-Oriented Design with Applications, 3rd Edition (Addison-Wesley), Grady Booch, a pioneer in both OOP and design patterns, has a clear definition of abstrac‐ tion that nicely sums it up: An abstraction denotes the essential characteristics of an object that distinguish it from all other kinds of objects and thus provide crisply defined conceptual boundaries relative to the perspective of the viewer. Abstraction is important because it allows programmers to group and classify objects. To some extent, all classes are abstractions of a set of operations on data. Keep the following in mind about abstractions: Abstraction is the main tool used to deal with complexity. The more complex a problem, the more it requires abstractions to solve. Think about this paradox: abstractions are concrete methods for handling complexity. We group similarities in reality (abstract concrete likeness) to make them more man‐ ageable to work with. So instead of, “my loyal, bold, furry-faced, tail-wagging, face- licking, wet-nosed friend whose name is SyntaxError,” I can say, “my dog.” Abstract Classes Besides regular classes, PHP also has what are called abstract classes. In OOP and design patterns,abstractclassesprovideanorganizingmechanismforyourproject.Anabstract class cannot be instantiated, but rather a concrete class (one you can instantiate) inherits its interface and any concrete properties from the abstract class. Before continuing, the term interface needs to be examined. Familiar interfaces include user interfaces, hardware interfaces, and other kinds of linkages involving computer hardware and software. Another kind of interface is one that describes the outline of an object. To begin, consider a simple class with a single method: 20 | Chapter 2: Basic Concepts in OOP
  • 47. <?php class OneTrick { private $storeHere; public function trick($whatever) { $this->storeHere=$whatever; return $this->storeHere; } } $doIt=new OneTrick(); $dataNow=$doIt->trick("This is perfect."); echo $dataNow; ?> The central part of an interface is made up of all the signatures in the class defined by its operations (functions). A signature consists of an operation’s name and parameters. Signatures also include the return data type, but because of the nature of data typing in PHP, we’ll have to return to this third element of a signature further on in the section “Type Hinting: Almost Data Typing” (page 26). Figure 2-1 shows the trick() method’s signature. Figure 2-1. An operation’s signature in PHP When you take all of an object’s signatures, it is the interface. For example, the One Trick class has one operation with one signature made up of the name trick() and a single parameter, $whatever. Abstraction | 21
  • 48. Abstract Properties and Methods To write the trick() function as an abstract one, include the interface but nothing else: abstract public function trick($whatever); If a class has at least one abstract method, it must be an abstract class. However, an abstract class can have concrete methods as well. For example, the following class is abstract and includes an abstract method: <?php abstract class OneTrickAbstract { public $storeHere; abstract public function trick($whatever); } ?> In addition to the abstract method, you can see a single variable, $storeHere. A variable that is part of a class is a property. In some contexts, a reference to both properties and methods is simply properties, but for the most part properties refer to variables and constants (abstract data) and methods refer to functions (operations on the data). PHP does not have abstract properties as such. You can declare a property with no assigned value and treat it as an abstract property, but unlike abstract methods, you are not forced to use them. If you declare an abstract method in an abstract class, you must implement it in each child class that inherits the parent. It might help to think about methods in abstract classes as being like a contract that forces a set of hierarchies for all subclasses, so that they must all follow the same standards. For now, begin thinking of abstract classes as you would containers that can be filled with just about anything and placed on ships, trucks, and trains. The containers, like abstract classes, are part of a larger structure. A class that inherits from a class is a child class, and the abstract class (or any other class from which another class has inheritance) is the parent class. The following shows how to implement the abstract class, OneTrickAbstract: <?php include_once('OneTrickAbstract.php'); class OneTrickConcrete extends OneTrickAbstract { public function trick($whatever) { $this->storeHere="An abstract property"; return $whatever . $this->storeHere; } } 22 | Chapter 2: Basic Concepts in OOP
  • 49. $worker=new OneTrickConcrete(); echo $worker->trick("From an abstract origin..."); ?> Abstract methods can be implemented in any way you want as long as you include the method’s signature and correct visibility. In this case, that signature includes the name “trick” and a single parameter, $whatever, and the visibility is public. The following are all legitimate implementations of the trick() method: public function trick($whatever) { $echo $whatever; } Or: public function trick($whatever) { $half=$whatever/2; return $half; } Or: public function trick($whatever) { $this->storehere=25; $quarter=$whatever * 100; return ($quarter / $this->storehere); } You may wonder what the point is in an abstract method if you can revise it as long as you maintain the signature and visibility. In the “Inheritance” (page 34) section of this chapter, you will be able to see more clearly why inheriting the interface is important. While abstract classes generally have some abstract methods, you can add as many concrete methods and properties as you want in addition to any abstract methods that must be implemented. However, an abstract class can consist of nothing but concrete methods. PHP 5.4 has a structure called Traits that are mechanisms for code reuse where multiple inheritance is not allowed. A class may inherit one class and then at the same time use a Trait that functions something like multiple inheritance. They will not be used in the examples in this book and are mentioned here in case there may be some pattern ex‐ ample in another language that uses multiple inheritance that you would like to imple‐ ment in PHP. Interfaces Another OOP and design pattern building block is an interface. Like most abstract classes, interfaces have abstract methods. However, you cannot include concrete Abstraction | 23
  • 50. methods in an interface or variables as in an abstract class. (In an exception to abstract‐ ness, you can include concrete constants in an interface, but that is a unique feature of PHP interfaces.) The salient point about interfaces is that they are important structural elements in OOP and design patterns. To create an interface, use the interface statement instead of class. As a general con‐ vention, interfaces begin with the letter I or i; in this book, we’ll use a capital I followed by a capital letter describing the interface. This is followed by abstract methods, but the abstract statement is not used. The following is a simple interface with three methods: <?php interface IMethodHolder { public function getInfo($info); public function sendInfo($info); public function calculate($first,$second); } ?> To implement an interface, use the implements statement instead of extend as is done with abstract classes. Note that the listing uses the include_once() function to make the interface available to the class implementing it: <?php include_once('IMethodHolder.php'); class ImplementAlpha implements IMethodHolder { public function getInfo($info) { echo "This is NEWS! " . $info . "<br/>"; } public function sendInfo($info) { return $info; } public function calculate($first,$second) { $calulated = $first * $second; return $calulated; } public function useMethods() { $this->getInfo("The sky is falling..."); echo $this->sendInfo("Vote for Senator Snort!") . "<br/>"; echo "You make $" . $this->calculate(20,15) . " in your part-time job<br/>"; } } $worker=new ImplementAlpha(); 24 | Chapter 2: Basic Concepts in OOP
  • 51. $worker->useMethods(); ?> When you test the program, you should see the following output: This is NEWS! The sky is falling... Vote for Senator Snort! You make $300 in your part-time job Note that in addition to implementing the three methods in the interface, the Imple mentAlpha class includes a third method, useMethods(). As long as you implement the full number of methods in the interface, you can add as many other methods and prop‐ erties as you need. Interfaces and Constants While you cannot include variables in interfaces, you can include constants. In order to use constants, you need the scope resolution operator (::). The double colon operator can be used to allow access to constants, both in classes and through an interface im‐ plementation. The general format can be seen in the following code samples: $someVariable= InterfaceName::SOME_CONSTANT; For example, the following interface has constants used in a MySQL connection: <?php interface IConnectInfo { const HOST ="localhost"; const UNAME ="phpWorker"; const DBNAME = "dpPatt"; const PW ="easyWay"; function testConnection(); } ?> Implement the interface just like any other PHP interface. The values of the constants can then be passed using the scope resolution operator in the implementation: <?php include_once('IConnectInfoMethod.php'); class ConSQL implements IConnectInfo { //Passing values using scope resolution operator private $server=IConnectInfo::HOST; private $currentDB= IConnectInfo::DBNAME; private $user= IConnectInfo::UNAME; private $pass= IConnectInfo::PW; public function testConnection() { Abstraction | 25
  • 52. $hookup=new mysqli($this->server, $this->user, $this->pass, $this->currentDB); if (mysqli_connect_error()) { die('bad mojo'); } print "You're hooked up Ace! <br />" . $hookup->host_info; $hookup->close(); } } $useConstant = new ConSQL(); $useConstant->testConnection(); ?> The only method is testConnection(), but your interface could be made up of nothing but constants if you wanted. The values are passed to the class properties (private vari‐ ables in the example) using the name of the interface (IConnectInfo), the scope reso‐ lution operator, and the name of the constant. Abstract Classes and Interfaces: Two Types of Interfaces One of the more confusing concepts in OOP and design patterns is differentiating ab‐ stract classes and interfaces. Keep in mind that both have interfaces, general outlines of methods. The set of all signatures defined by the methods in a class is the interface of the class (or object). So, you may often find a reference to a pattern’s interface referring to an abstract class as well as an interface. The reference is to the set of all signatures. Gamma et al. note that, “An object’s interface characterizes the complete set of requests that can be sent to the object.” This means that if your Client class is aware of an object’s interface, it knows what it can request and how to request it. So while both abstract classes and interfaces have interfaces of their own, abstract classes can have concrete methods (operations) and properties as well. Much of understanding design patterns relies on understanding the general use of the term interface as it applies to the set of signatures in an object (a class). Type Hinting: Almost Data Typing One of the important structural elements in the abstraction in OOP and design patterns istypingdatatoaninterfaceinsteadofanimplementation.Thismeansthatthereference to the data is through the parent class, typically an interface or abstract class. (In this context, interface is used to refer to either an interface or abstract class.) 26 | Chapter 2: Basic Concepts in OOP
  • 53. The basic format for type hinting is as follows: function doWork(TypeHint $someVar)... Type hints must be the name of a class or interface. In design pattern work, an abstract class or interface is preferred because it does not bind the type of an implementation, just the structure. The following example shows an interface with two implementations of the interface and a class that uses an interface in type hinting to establish a loose but clear bind. Interface //IProduct.php <?php interface IProduct { function apples(); function oranges(); } ?> FruitStore Implementation //FruitStore.php <?php include_once('IProduct.php'); class FruitStore implements IProduct { public function apples() { return "FruitStore sez--We have apples. <br/>"; } public function oranges() { return "FruitStore sez--We have no citrus fruit.<br/>"; } } ?> CitrusStore Implementation //CitrusStore.php <?php include_once('IProduct.php'); class CitrusStore implements IProduct { public function apples() { return "CitrusStore sez--We do not sell apples. <br/>"; } Abstraction | 27
  • 54. public function oranges() { return "CitrusStore sez--We have citrus fruit.<br/>"; } } ?> Object with type hinting //UseProducts.php <?php include_once('FruitStore.php'); include_once('CitrusStore.php'); class UseProducts { public function __construct() { $appleSauce=new FruitStore(); $orangeJuice=new CitrusStore(); $this->doInterface($appleSauce); $this->doInterface($orangeJuice); } //IProduct is type hint in doInterface() function doInterface(IProduct $product) { echo $product->apples(); echo $product->oranges(); } } $worker=new UseProducts(); ?> When you test the UseProducts class, the output displays the following: FruitStore sez--We have apples. FruitStore sez--We have no citrus fruit. CitrusStore sez--We do not sell apples. CitrusStore sez--We have citrus fruit. WhatyouseeonthescreenaredifferentimplementationsoftheIProduct interface. The crucial feature to note is that in the doInterface() method, the type hint of IProduct recognizes both of the classes that implemented the IProduct interface. In other words, instead of recognizing one as a FruitStore instance and the other as a CitrusStore instance, it recognizes their common interface IProduct. In practical terms for development, enforcing data types ensures that any object (class) used in conjunction with a given method where code hinting is used will have a given interface. Further, if an interface (either an abstract class or interface) 28 | Chapter 2: Basic Concepts in OOP
  • 55. Another Random Scribd Document with Unrelated Content
  • 56. The footsteps had now reached the landing of the first floor and, after another deathlike pause, commenced to ascend the stairs which led directly to us. "Can't you do something, Edward?" whispered my agonized wife, wringing her hands. "Can't you lock the door?" It is strange that the fact of the door being unlocked had not occurred to me before. I rushed to it instantly, and a sigh of intense relief escaped me at finding the key in the lock. I turned it like lightning, and we were so far safe. Then my wife flew to the window, and, throwing it open, began to scream for help--that is to say, she would have screamed if she had had the power, but her voice was almost frozen in her throat, and the sounds that issued from her were of a ravenlike hoarseness, and could have traveled but a few yards; too short a distance in our lonely situation to be of any practical value. Soon I added my shouts to her hoarse scream. They were sent forth to a dead world; to our frantic appeals no answer was made. Meanwhile, occupied as I was, I could still pay some attention to what was passing on the stairs that led to the room. I had indulged in a faint hope that our cries would alarm those without, and would induce them to forego their murderous attack upon us, but the stealthy pat, pat, pat of the footsteps continued, and were now in the middle of the staircase; there could be but a few more stairs to ascend. Still another hope remained--that when the footsteps reached the second landing they would proceed onward to the top of the house. This last hope, like those which had preceded it, was not fulfilled. Nearer, nearer, nearer they approached, until they were close to the door; then there was another pause; no further sounds were heard. My impression now was that the villains who had a design against us--for by this time I entertained no doubt of their diabolical purpose, and that we were in the direst peril--were making
  • 57. preparations to carry it into effect. Presently they would try the handle of the door, and, discovering that it was locked, would burst it open and spring upon us. A long and awful silence ensued, during which the agonizing question occupied my mind, what was being done outside the door? The torture of the suspense was maddening; the silence was more harrowing than the footsteps themselves had been. I was soon to receive an appalling answer to the question. The door--notwithstanding my firm belief that I had securely locked it--slowly and noiselessly opened. My heart beat wildly, but I held myself ready, so far as lay in my poor power, to meet the attack with which we were threatened. And now the door stood wide open, and I saw no form of man or woman. But gradually there shaped itself in the air the outline of a female shape, a shadow, which as I gazed grew more distinct, and yet was never quite vivid to my sight. It was the figure of a young girl, poorly dressed, with carpet slippers on her feet. Her hair was hanging loose, and the tattered remnants of a cap attached to it was an indication that her station in life was-- or more properly speaking, had been--that of a domestic servant. Her face was white and wan, and her large gray eyes were fixed mournfully upon me. There was a dead beauty in their depths which seemed to speak of glowing hopes of youth prematurely blasted and destroyed, and, though the features of the apparition were but airy outlines, I could not fail to perceive that in a bygone time they had been comely and prepossessing. More terrible than any form of living man or woman was this appalling spectacle as it stood, silent and still, upon the threshold. Had the bell I rang summoned it from the grave? For what purpose had it come? What did it require of me? It is probable that I should have mustered courage to ask some such questions as these, and indeed I was aware that my lips were moving, but no sound issued from them--my voice was gone; I could not utter an audible sound.
  • 58. For several minutes, as it seemed to me, though it could not have been so long, did I continue to gaze upon the figure. I had directed a brief glance at its feet, but when my eyes traveled up to its face they became magnetized, as it were. The spell was broken by a movement on the ground, not proceeding from the apparition of the girl. I looked down, and there, gliding past the upright spectral figure, I saw creeping toward me a skeleton cat. It was veritably a skeleton, and was to my sight as impalpable as the young girl. Through its skin, almost bare of hair, its bones were sharply outlined. It was black; its ears were pointed, its eyes were yellow, its mouth was open, showing its sharp teeth. This second apparition added to my horror, which grew deeper and deeper as the cat, with gliding motion, approached me. Had its paws left upon the ground a bloody imprint I could not have been more awestricken. It paused a few inches from me, where it crouched motionless so long as I remained so. When I moved it accompanied me, and when I stopped it stopped, waiting for a mandate from me to set it in motion. Raising my eyes to the door I discovered to my amazement that the figure of the girl had vanished. Nerving myself to the effort, I stepped softly into the passage and gazed along and at the staircases above and below me, but saw no movement of substance or shadow. Returning to the room I was irresistibly impelled by a desire to convince myself whether the cat which had accompanied me to and fro was as palpable to touch as to sight. Kneeling to put this to the test I found myself kneeling on my wife's dress. So engrossed had I been in the astounding apparitions that I had paid no attention to her, and now I saw that she had fainted. Before devoting myself to her I passed my hand over the cat and came in contact with nothing in the shape of substance. It was truly a specter, and I beheld it as clearly as I beheld the body of my wife lying at my side.
  • 59. I took my flask from my pocket and bathed my wife's forehead, and poured a few drops of brandy and water down her throat, and I was presently relieved by seeing her eyes open. She closed them again immediately, and said, in a whisper: "Is it gone?" Anxious to learn what she had seen--for I inwardly argued that I might myself be the victim of a strange delusion--I met her inquiry by asking: "Is what gone, Maria?" "The girl," she murmured; "that dreadful figure that came into the room?" "Look for yourself," I said. It was not without apprehension that I made the request, and I nervously followed the direction of her eyes. "It is not in the room," she sighed. "But, Edward, who opened the door?" "The wind blew it open, most likely." "You locked it, Edward! I heard you turn the key in the lock." "I thought I did, but I must have been mistaken. Terrified as we were, how could we trust the evidence of our senses? And do you suppose there's a lock in the house in proper order?" "It must have been my fancy. Did you see nothing?" How should I answer her? Revive her terror by telling her that she was under no delusion, but that the spectral figure of the young girl had really presented itself; or, out of kindness to her, strive to banish her fears by a pardonable falsehood?
  • 60. Before I decided how to act I felt it necessary to ascertain whether the cat lying in full view to me was visible to her. "Maria," I said, "take the evidence of your senses. Look round the room--at the door, at the walls, at the ceiling, on the floor--and tell me what you see." With timid eyes she obeyed, and glanced in every direction, not omitting the spot upon which the skeleton cat was lying. "I don't see anything, Edward." "Does not that prove that the figure you spoke of was a trick of the imagination?" "You actually saw nothing?" "Nothing." All this time she had been sitting on the floor, keeping tight hold of me. I assisted her to her feet; she was so weak that she could hardly stand. "For Heaven's sake!" she said "do not let us remain in the house another minute." I was as anxious to leave as she was, and had I been alone I should have rushed downstairs in blind haste, but I had to attend to my wife. The power of rapid motion had deserted her, and when we were about to pass through the passage she shrunk back, fearing that the apparition of the young girl was lurking there. She experienced the same fear as we descended the stairs, and clung to me in terror when we approached an open door. I was grateful that the apparition of the cat--which followed us faithfully down to the hall--was invisible to her; if it had not been she would have lost her senses again, and it would have been hard work for me to carry her out, as she is by no means of a light weight.
  • 61. The question which now agitated me was whether the cat would come into the streets with us, or would return to the resting place which should have been its last. It was soon and plainly answered. I opened the street door, and stood upon the threshold. The cat stood there also. I paused to give it the opportunity of returning, but it evinced no desire to do so. I went down the stone steps to the front garden; the cat accompanied me. I walked through the front garden out of the gate, straight into Lamb's Terrace, and thence across the wretched wastes of ground into more cheerful thoroughfares; and the skeleton cat was by my side the whole of the time. The evidence of civilized life by which we were now surrounded restored Maria's spirits; she found her tongue. "Why did you stop on the doorstep, Edward?" she asked. "I had to lock the street door," I answered. "We will not take that house, my dear," she said. "No, we will not take it." Some unaccustomed note in my voice struck her as strange. "Is anything the matter with you?" she asked. "No," I replied, glancing at the cat, "nothing." "What are you looking at? Why are your eyes wandering so?" "My dear," I said, with an attempt to speak in a lively tone, and failing dismally, "I must be a bit unstrung, that is all." She accepted my explanation as satisfactory.
  • 62. "No wonder," she said; "I would not go through such another trial for all the money in the world." CHAPTER VII. I MAKE SOME SINGULAR EXPERIMENTS. For a little while we walked along in silence, and then I asked my wife whether she would ride or walk home. "I should prefer to walk," she said; "it is early, and the air is fresh and reviving. Things look all the brighter now we are out of that horrible place. A walk will do us good." I made no demur, though I was curious to see what the skeleton cat would do when we entered an omnibus full of people. It would experience a difficulty in finding a place on the floor of the 'bus, and there would be no room for it to stretch itself comfortably on the seats. I wished to ascertain, also, whether among a number of strangers there would be one to whom it would make itself visible. I peered into the faces of the passers-by with this thought in my mind, but I saw no expression of surprise in them, notwithstanding that the cat seemed to touch their legs in brushing past. Again and again did I turn my eyes away from the apparition; and again and again, looking down at my feet, I beheld it as clearly as if it were an actual living example of its species. Once we got into a crowd and I hoped that I had lost it. No such luck; it evinced no disposition to leave me.
  • 63. "Edward," said my wife, "I am sure you are not well. I have tired you out with this eternal looking over houses to let. You have been very patient with me"--she pressed my arm affectionately--"and I will try and make it up to you. I know you never really wished to move." "I never wished it, Maria." "And you have gone through all this for my sake. I don't like to give up a thing once I have set my mind on it,--you know that of old, my dear,--but the experiences of this morning will last me a lifetime; so I will give this up." "The idea of moving?" I asked in a dull voice. "You give it up altogether?" "Yes, altogether. We will remain in our old house." It is a singular confession to make, but this proclamation of the victory I had gained afforded me no satisfaction. I had no wish to move; my earnest desire was to remain where we were; but with the infernal cat gliding by my side, I could think of nothing but the haunted house in Lamb's Terrace which we had just quitted. In that house was the spectral figure of the girl who, by spiritual means, had opened a door I had locked, and presented herself to me. She was now alone. I had deprived her of a companion who, for aught I knew, might have been a solace to her. It was as if I had been guilty of a crime; as if I had condemned her to solitude. But it was folly to torment myself with such reflections. What had I to do with the incidents of this eventful day? I was a passive instrument, and was being led by unseen hands. More pertinent to ask what was the portent of the apparitions, and why the supernatural visitation was inflicted upon me, although to these questions I could expect no answer. Involuntarily I stooped to assure myself once more that the cat was but a shadow. "What are you stooping for?" inquired my wife.
  • 64. "I thought I had dropped my handkerchief." "It is here, in your pocket." She took it out and handed it to me. "I was mistaken," I muttered. She held up her sunshade and hailed a passing hansom, saying energetically, and with a troubled look at me, "We will ride home." I did not object. I think if she had said "We will fly home," I should have made an attempt to fly, so absolutely was I, for the time, deprived of the power of deciding my own movements. I did not see the cat spring into the cab, but directly we were seated, there it lay crouched in front of us; and when the driver pulled up at our house there it was waiting for the street door to be opened. "Lie down and rest yourself for an hour," said my wife, with deep concern in her voice. "No," I replied, "I will smoke a pipe in the garden." With wifely solicitude she filled my pipe for me, and held a lighted match to the tobacco. I puffed up, thanked her with a look, and went into the garden accompanied by the cat. In the part of London in which we live there are pleasant gardens attached to many of the houses, and our little plot of ground is by no means to be despised. It is some ninety feet in length, is divided in the center by a broad graveled space, and has a graveled walk all around it; and here when the weather permits, my wife and I frequently sit and enjoy ourselves. I am also the proud possessor of a greenhouse, which, as well as the borders and beds I have laid out, is in summer and autumn generally bright with flowers, of which I am very fond; and into this greenhouse I walked to smoke the green fly, which was doing its worst for my pelargoniums. There are a couple of trees in my garden, and birds' nests in them. The birds
  • 65. were flitting among the branches, and I looked at the cat, wondering whether it would spring after its feathered victims. It took no notice of them, nor they of it. I remained in the greenhouse ten or twelve minutes, and then it occurred to me to make an experiment. With a swift and sudden motion I left the greenhouse and pulled the door behind me, shutting the cat inside. I walked toward the center of the garden, and the animal I thought I had cunningly imprisoned glided on at my side. Doors shut and locked, and doubtless stone walls, presented no greater obstacle to the creature than the air I breathed. I sat down on the garden seat and smoked and pondered, and was aroused by a soft purring at my feet, and the contact of a furry body against my legs. I uttered an exclamation, and, looking down, saw our own household cat--a tortoise-shell tabby--rubbing against me. Now, thought I, there will be a fight. But there was nothing of the kind. I felt convinced that the skeleton cat saw our tortoise-shell cat, and presently I was quite as convinced that the flesh and blood reality was unconscious of the presence of the disembodied spirit. I made another experiment. I went stealthily into the kitchen, and filled a saucer with milk. This saucer I took into the garden and put upon the gravel before the two cats. "You must be hungry," I said aloud to the spectral figure, with a feeble attempt at jocularity. "Lap up." It made no movement. With a look of gratitude at me our tabby lapped up the whole of the milk, and licked the saucer dry. My wife came out and, seeing what I had done, smiled. "Are you feeling better?" she asked solicitously. "There is nothing whatever the matter with me," I said, with an unreasonable show of irritation.
  • 66. She wisely made no reply, and I was once more left alone with my supernatural companion. Thus passed the day, and I was glad when the hour arrived for Bob Millet to make his appearance. He came punctually and was cordially received by my wife. "You are in time for tea, Mr. Millet," she said, shaking hands with him. "I want you to feel that you are really welcome here." "Indeed I do feel so," said Bob, gratified by this reception, which I fancy he hardly expected. They made a good meal, but though my wife had thoughtfully prepared a dish of which I was very fond--a tongue stewed with raisins--I ate very little. "No appetite, Ned?" said Bob. I shook my head gloomily. "He is out of sorts, Mr. Millet," said my wife, "and I am delighted you are here to cheer him up. He has me to thank for his low spirits; it is all because of my stupid wish to leave the house in which we are as comfortable as we could reasonably hope to be. I have worried him to death, almost, dragging him about against his will-- though he has never complained--from morning till night for I don't know how long past. He is not half the man he was; he doesn't eat well and he doesn't sleep well, and I am to blame for it." She was ready to cry with remorse, and I felt ashamed of myself for not having the strength to battle with the delusion which surely would not torture me forever. I patted her on the shoulder, and put on a more cheerful countenance. She brightened up instantly, and then Bob asked whether we had been to 79 Lamb's Terrace.
  • 67. "Yes, we have," said my wife, "and I am truly thankful that we got out of it safely." "Ah!" said Bob, lifting his eyes. "You were right, Mr. Millet," said my wife, "the house is haunted." "Oh," said Bob, "I only told you what I had heard. For my part, I don't even know where Lamb's Terrace is." "Take my advice, Mr. Millet, and don't try to know. The less you see of the place the better it will be for you." "Why?" "Because it is haunted," she replied with emphatic shakes of her head, "and I am much obliged to you for putting us on our guard." "Then you saw something?" My wife looked at me. "Tell him what you fancy you saw," I said. "It was not fancy," she rejoined; "I have been thinking over it during the day, and the more I think, the more I am convinced that I did see--what I saw." "I should like to hear about it," said Bob. "You shall." And she told him all; of our going over the house till we got to the room on the second floor, of my pulling the bell, of the sounds we had heard proceeding from the basement and approaching nearer and nearer till they were outside in the passage, of my locking the door, of the door opening of its own accord, and of the appearance
  • 68. on the threshold of the specter of a young girl, and, finally, of her fainting away. "It was only my obstinacy," she said, "that took us up to the top of the house. Edward was quite ready to leave it before we had been in the place two minutes, but I insisted upon going into all the rooms, and I was properly punished for it. I was frightened enough, goodness knows, before I fainted, for I was chilled all over by what I had already seen, and I ought to have been satisfied; but you know what women are, Mr. Millet, when they take a fancy into their heads." "There, Bob," said I, "there's a confession to make; not many women would say as much." Bob smiled, and said, "You are too hard on yourself. We are much of a muchness--men and women alike; there is nothing to choose between us." "You are very good to say so, Mr. Millet." "When you recovered from your faint," said Bob, "was the figure still there?" "No, it was gone." "And you did not see it again?" "No, thank God!" "Did you see it?" asked Bob, turning to me. "He says he didn't," said my wife, quickly replying for me, "but----" "But," I added, "she does not believe me." "How can I believe you," said my wife reproachfully, "when the very moment before I swooned away I saw your eyes almost
  • 69. starting out of your head with fright." "Oh, well," I said, "I suppose I have as much right to fancy things as you." "Of course you have, and it was very considerate of you to deny that you saw anything. He is the best husband in the world, Mr. Millet, and if he thinks I don't appreciate him he is mistaken." "Now, my dear," I said soothingly, "you know I don't think anything of the sort; if I am the best husband in the world, so are you the best wife in the world. What do you say to our going in for the flitch of bacon?" "It is all very well to make a laughing matter of it," said my wife seriously. "I will ask Mr. Millet this plain question. He may say, like you, that it is all fancy; but pray how does he account for the opening of a locked door?" "I told you," I interposed before Bob could speak, "that I must have been mistaken in supposing I had locked it." "Very good. But the door was shut if it was not locked." "I don't deny that it was." "How did it come open, then?" "I told you that, too," I replied. "The wind." "What wind?" "The wind from the window through the broken panes." She turned to Bob triumphantly. "What do you think of that, Mr. Millet? When we go into the room the door slams, and my husband says it slams because of the wind through the window. I accept that as reasonable, but is it reasonable to suppose that the same wind
  • 70. that blows a door shut from the inside of a room should blow it open from the outside?" "Well, no," said Bob, with a sly look at me; "I should say it was not reasonable." I was fairly caught. My wife's logic was too much for me. "And now," said she, "as I know it will worry him if I go on talking about it, I will leave you two gentlemen together while I go and look after some affairs. You will spend the evening with us, Mr. Millet?" "With much pleasure," he said. "And I beg your pardon," she said, "for having misjudged you. I did think that you and my husband were in a plot together to set me against the house, and I did not think it was nice behavior in a gentleman who was paying me his first visit. I told my husband as much last night before we went to sleep, and he stood up for you like the true friend he is; and now I am glad to say I have found out my mistake. I hope you will forgive me. "There is nothing to forgive," said Bob, in the kindest and gentlest tone imaginable. "All that you have said and thought and done was most fair and reasonable, and I ought to be thankful for the little misunderstanding, if it has given you a better opinion of me." CHAPTER VIII. I TAKE BOB INTO MY CONFIDENCE.
  • 71. "A sensible woman," said Bob, gazing after my wife; and then, in a more serious tone, "Ned, is it all true?" "Every word of it." "About the phantom of the girl?" "Yes, about the phantom of the girl. Frightfully, horribly true!" "You saw it?" "I did; and I would swear it was no trick of imagination." "And the door opened, as your wife has described?" "It did, and I will swear that that was no trick of the imagination." We had moved our chairs and were sitting by the open window, from which stretched the bright prospect of the flowers in my garden; there was a space of some three feet between our chairs as we sat facing each other, and on this space lay the skeleton cat. "There is something more," I said. "Look down here." I pointed to the cat. "Well? I am looking." "What do you see?" "Nothing." "Absolutely nothing?" "Nothing, except the carpet."
  • 72. "Bob, would you judge me to be a man possessed of a fair amount of common sense?" "Certainly." "Not likely to give way to fads and fancies?" "Certainly." "Caring, as a rule, more for the prosaic than the romantic side of things?" "I should say that, without doubt." "And you would say what is true of me, up to the present moment. I prefer the plain bread-and-butter side of life, and though I hope I have a proper sympathy for my fellow-creatures, I am not given to extravagant sentiment. I am putting this description of myself in very plain words, because I really want you to understand me as I am." "I think I do understand you, Ned." "I have never had a nightmare," I continued, "and, as a rule, my sleep is dreamless. It is true that my rest has been a little disturbed lately by my wife's wish to move, but the few restless nights I have passed from this reason are quite an exception. To sum myself up briefly and concisely, I claim to be considered a healthy human being in mind and body." "It is not I, Ned, who would dispute that claim." "I have told you that the spectral figure of the girl appeared to me. A doctor would at once declare it to be a delusion of the senses. If my wife informed the doctor that she also saw it, he would reply that she also was suffering under a delusion, and he would attempt to explain it away on the ground of sympathy between us. But the
  • 73. opening of the door could be no delusion; it was tight shut, and the key was incontestibly turned in the lock; and yet it opened to admit the specter. The doctor would smile at this, and ask incredulously, 'Is it necessary for the entrance of an apparition, that a door should be open, when it possesses the power of passing through material obstacles?' It does possess such a power, Bob; I have tested and proved it. Now, what I have been coming to is this. My wife saw one apparition; I saw two." "Two?" exclaimed Bob, regarding me more intently. "Yes, two. One, the girl, vanished; the other, the cat, remained." "In Heaven's name what are you talking about?" "I am relating an absolute fact. By the side of the girl appeared the apparition of a skeleton cat, which accompanied me from the house, which glided along the streets at my side, which entered my own house with me, and which now lies here, on this little space of carpet between us, on which you see--nothing. Now, Bob, tell me at once that I am mad." "I shall tell you nothing of the kind; I must have a little time to consider. What kind of reading do you indulge in? Sensation stories?" "I chiefly read the newspapers." "Digestion good, Ned?" "In perfect condition; for the last ten years I have not had a day's bad health." "All that is in your favor." "Thank you. I see that you are taking a medical view of my case."
  • 74. "Indeed, I am not; I only want to think it out for myself. You can actually see the cat?" "There it lies, its yellow eyes fixed on my face." "Touch it." I stretched forth my hand and passed it over and through the apparition. "Does it reply by any sign?" "By none." "And yet it moves?" "When I move. Otherwise it remains motionless, in a state of expectation, as it appears to me. "I don't quite understand, Ned." "It is difficult to understand, but it seems to be waiting for something in the near or distant future. It relieves me to unburden my mind to you, Bob. I do not intend to confide in my wife; it would frighten her out of her life, and in the kindness of her heart she would try to make me disbelieve the evidence of my own senses. Therefore not a word about this to her. I hear her singing; she is coming back to us, and she is singing to make me cheerful. Why, Maria," I said, as she entered the room, "what have you got your hat on for? Are you going out for a walk?" "I am," she replied briskly, "and you two gentlemen are coming with me. It is now half-past seven, and if you will be so good as not to raise any objection I propose to treat you to the theater." "A good idea," said Bob Millet, in a tone as lively as her own.
  • 75. "No tragedies," she continued, "a play that we can have a good laugh over; we have had enough of tragedies to-day, and I don't intend they shall get the best of me. We will go to the Criterion, where you always get a proper return for your money, and I hope you won't object to the pit, Mr. Millet?" "I assure you," said Bob, with grave humor, "that when I sit in the pit I shall consider myself one of the aristocracy. Your wife is a capital doctor, Ned." Very willingly I fell in with the thoughtful proposition, and as Maria insisted upon paying all the expenses out of her private purse I allowed her to do so, knowing that it would give her pleasure. We arrived at the Criterion before the raising of the curtain and we saw a laughable comedy most admirably acted, which afforded us great enjoyment. I may say that the circumstance of the skeleton cat not accompanying us was the mainspring of my enjoyment. Could it have been, after all, an illusion? Was it really possible that the apparitions I had seen were the creations of my fancy? Bob whispered to me once: "Has it accompanied us?" "No," I whispered back, "I see nothing of it." When we were outside the theater, and were ready to depart our separate ways, Bob said: "Will you come and spend an hour with me to-morrow evening, Ned?" "Yes, he will," said my wife; "it will do him good. It does not do, Mr. Millet, for a man to mope too much at home." So I consented, and we shook hands, and wished each other good-night.
  • 76. CHAPTER IX. I PAY BOB MILLET A VISIT. I was naturally curious when I arrived home to see if the cat was there. It was. It did not meet me at the street door, but it lay on the spot on which I had left it a few hours previously. Of course this distressed me, but I did not betray my uneasiness to my wife. I had at least cause for thankfulness in the silent announcement made by the apparition that it was not its intention to accompany me to every place I visited. We had our supper and went to bed; and it was an additional comfort to me when I found that it did not follow us to our bedroom. It was not likely, after such an exciting day, that I should pass a good night. My rest was greatly disturbed; and at about three o'clock I was wide awake. My wife was sleeping soundly. I rose quietly, thrust my feet in my slippers, and went downstairs to the dining-room. There lay the cat with its eyes wide open. "You infernal creature," I cried, holding the candle so that its light fell upon the specter, "what are you here for? What do you want me to do? Why do you not go back to your grave and leave me in peace?" I asked these questions slowly, and paused between each, with an insane notion that an answer might be given to them. No answer was vouchsafed, and I recognized the folly of my expectation. The
  • 77. peculiarity of the apparition was that its eyes never seemed to be closed, as the eyes of other cats are when they are in repose. It appeared to be ever on the watch, but what it was watching for was a sealed mystery to me. In a moment of exasperation I raised my hand against it threateningly; it did not move. I went no further than this, feeling that it would be cowardly to strike at a shadow. I returned to my bedroom, and after tossing about for an hour fell into a disturbed sleep. Bob lived at Canonbury, and had given me directions to take a North London train, his station being about half a mile from his lodgings. All the day the cat had remained in the dining-room, but when I was leaving the house on my visit to Bob, it rose and followed me. "Do you intend to favor me with your company?" I asked. "Very well, come along." And come along it did, to the train I took, got into the carriage with me, and emerged from it at the Canonbury station, where I found Bob waiting for me on the platform. "I have brought another visitor with me, Bob," I said, "but I can assure you it has accompanied me without any invitation." "Is it here, then?" he asked, following the direction of my eyes. "Yes, Bob, it is here." And as we walked to the old-fashioned house in which he rented one room at the top, I remarked, "Is it not singular that it did not come to the theater with me last night, and that it should accompany me now upon this friendly visit to you?" Bob nodded. "I am beginning to have theories about it," I continued, "and one is, that something will occur to-night in connection with the haunted house in Lamb's Terrace."
  • 78. "Do not get too many fancies into your head, old fellow," said Bob. "I will not get more than I can help, but ideas come without any active prompting or wish of my own; I am like a man who is being driven, or led." Bob's one room was by no means uncomfortable; it served at once for his living and bedroom, but the bed he occupied being a folding bed, and the washstand he used being inclosed, it did not present the appearance of a bedroom. There were shelves on the walls containing a large number of books; four or five of these were on the table. "Now, sir or madam," said I to the cat, "what do you think of Bob's residence, and what can we do to make you comfortable?" The cat glided to the hearthrug and stretched itself upon it; I wrested my attention from the unpleasant object. "I am very well off here," said Bob; "the landlady cooks my meals for me, and allows me to have them downstairs. I am at the top of the house, and there is a fine view from the roof; I often smoke for an hour there. You see that door in the corner; it is a closet, with a fixed flight of steps leading to the roof; in case of fire I should be safe. Sit in the armchair, Ned, and let us reason out things. I have been thinking a great deal about you to-day, and talking about you, too." "That was scarcely right, Bob." "Don't be afraid; you were not mentioned by name, and the gentleman I conversed with is blind. That is the reason, very likely, why he believes in what he does not see." "A friend of yours?"
  • 79. "A dear friend; a poor gentleman who has suffered, and who bears his sufferings with a resignation which can only spring from faith. I told you yesterday that I had been married and that I lost my wife. The gentleman I speak of is the son of my dead wife's sister, who is herself a widow. My wife's family were gentlefolk, who had fallen from affluence, not exactly into poverty, but into very poor circumstances. Ronald Elsdale--the name of my nephew--is a tutor; he was not born blind; the affliction came upon him gradually, and was accelerated by over study in his boyish days. Four years ago he could see, and when blindness came upon him he was fortunately armed, and able to obtain a fair living for himself and his widowed mother by tutoring. He is an accomplished musician, and frequently obtains remunerative engagements to play. He speaks modern languages fluently, is well up in the sciences, has read deeply, and is altogether as noble and sweet a gentleman as moves upon the earth." Bob spoke with enthusiasm, and it was easy to perceive that he had a sincere love for Mr. Ronald Elsdale. "In every way so accomplished and admirable," I said, "and with such a misfortune hanging over him, he needs a wife to look after him." "His mother does that," Bob replied, "with tender devotion, and Ronald will never marry unless--but thereby hangs a tale, as Shakspere says. He is not the only man who cherishes delusions." "Ah! he has delusions. I hope they are more agreeable than mine. How is it, Bob, that you have had time for so much talk to-day with your nephew?" "This is Thursday, and Mr. Gascoigne closes his office on Thursdays at two o'clock, so I have had a few hours at my disposal, which have been partly employed in talking with Ronald and partly in studying your case."
  • 80. "Explain." "I have been looking up apparitions," said Bob, pointing to the books upon the table. I did not trouble myself to examine them; it did not seem to me that the books would be of much service in my case; the facts themselves were sufficiently strong and stern, and I mentally scouted the idea that printed matter would enable me to get rid of the apparition that haunted me. "It is clear to me," I said, "that you think I am laboring under some hallucination, and that I see the specter, now lying on the hearthrug, with my mental and not my actual vision. Very well, Bob; a difference of opinion will not alter the facts." "The awkward part of it is," said Bob, "that all evidence is against you." I nodded toward the books on the table, and said, "All such evidence as that." "Yes, but you must not forget that cleverer heads than ours have occupied years of their lives in sifting these matters to the bottom." "In trying to sift them, Bob." "Well, in trying to sift them; but they give reasons for the conclusions they arrive at which it would be difficult, if not impossible, for men like ourselves to argue away." "There are two strong witnesses on my side," I remarked; "one is myself, the other is my wife. Bear in mind that we both saw the apparition of the girl; there was no collusion between us beforehand, and if, in our fright, our imaginations were already prepared to conjure up a phantom of the air, it is hardly possible that that phantom should, without previous concert, assume exactly the same
  • 81. form and shape; nor was there any after conspiracy between us as to the manner in which this phantom was to be dressed. Now, my wife has described to me the dress of the girl, the shreds of a cap sticking to her hair, the frock of faded pink, the carpet slippers, the black stockings, and I recognize the faithfulness of these details, which presented themselves to me exactly as they did to her. Granted that one mind may be laboring under a delusion, it is hardly possible that two minds can simultaneously be thus imposed upon. Answer that, Bob." "Sympathy," he replied. "The word I used yesterday evening, when I was imagining what the doctors would say upon my case; it is an easy way to get out of it, but it does not satisfy me. I suppose you have come across some curious cases in looking up apparitions?" "Some very curious cases. Here is one in which a door, not only locked but bolted, plays a part. A great Scotch physician relates how a person of high rank complains to him that he is in the habit of being visited by a hideous old woman at six o'clock every evening; that she rushes upon him with a crutch in her hand, and strikes him a blow so severe that he falls down in a swoon. The gentleman informs the physician that on the previous evening, at a quarter to six o'clock, he carefully locked and double bolted the door of the room, and that then he sat down in his chair and waited. Exactly as the clock strikes six the door flies wide open--as the door in Lamb's Terrace did, Ned--and the old woman rushes in and deals him a harder blow than she was in the habit of doing, and down he falls insensible. 'How many times has this occurred?' asks the physician. 'Several times,' is the reply. 'On any one of these occasions,' says the physician, 'have you had a companion with you?' 'No,' the gentleman replies, 'I have been quite alone.' The physician then inquires at what hour the gentleman dines, and he answers, five o'clock, and the physician proposes that they shall dine the next day in the room in which the old woman makes her appearance. The gentleman
  • 82. gladly consents; they dine together as agreed upon, and the physician--who is an agreeable talker--succeeds apparently in making his host forget all about the apparition. Suddenly, the clock on the mantelpiece is heard striking six. 'Here she is, here she is!' cries the gentleman, and a moment afterward falls down in a fit." "Very curious," I said, "and how does the wise physician account for the delusion?" "By the gentleman having a tendency to apoplexy." "There is, generally," I observed, "a weak spot or two in this kind of story. Does it say in the account that the door was locked and bolted when the gentleman and the physician dined together, and that the door flew open upon the appearance of the old lady?" "No, it does not say that." "The omission of the precaution to lock the door," I said, "is fatal, for the absence of that visible and material manifestation deprives the physician of the one strong argument he could have brought forward. Had the door been locked and bolted, and had the old woman appeared without its flying open, the physician could have said to the gentleman, 'You see, the door remains fastened, as we fastened it before we sat down to dinner; you imagined that it flew open, and there it remains shut, a clear proof that the old woman and her crutch is but a fevered fancy.' That would have disposed of this gentleman at once." "Quite so," said Bob. "You will, I suppose, admit that if the locked door had opened in the physician's presence, it would have been a sign that some spiritual power had been exercised for which he could not so readily have accounted?" "Yes, I should admit that."
  • 83. "Admit, then, that as my wife and I--two witnesses, each uninfluenced by the other--saw the locked door in Lamb's Terrace fly open, that that is an evidence of the exercise of a spiritual power." Bob laughed a little awkwardly. "You have made me give evidence against myself," he said. Here there came a knock at the door, and Bob calling "Come in," the landlady of the house made her appearance. "Mr. Elsdale is downstairs," she said, "and was coming up, when I told him you had a friend with you, and he sent me to ask whether he would be intruding." Bob looked at me inquiringly. "Not so far as I am concerned," I said; "I should very much like to make your nephew's acquaintance." "Ask Mr. Elsdale to come up," said Bob; and the landlady departed. "I have more than a passing fancy to see your nephew," I said; "you tell me he has delusions; what he says in our discussion, which I don't propose to drop when he joins us, may be of interest." As I spoke Ronald Elsdale entered the room. "My nephew, Ronald Elsdale," said Bob, introducing us. "My old friend, Mr. Emery." As we shook hands my attention was diverted to an incident which, insignificant as it might appear, struck me as very singular; the skeleton cat had risen from the hearthrug and was now standing at Ronald Elsdale's feet, looking up into his face.
  • 84. CHAPTER X. RONALD ELSDALE GIVES OPINIONS. Something more singular than this next attracted my attention. Ronald Elsdale, blind as he was, inclined his head to the ground and seemed to be returning the gaze of the cat. "Can it be possible," I thought, "that this man, physically blind, and this cat, invisible to all eyes but mine, are conscious of each other's presence?" I put this to the test. "You appear to be listening for something," I said. "Did you bring a dog with you?" he asked. "My uncle, I know, keeps neither cat nor dog." "No," I replied, "I brought no dog." "Then I must be mistaken," he said, and he felt his way to the seat he was in the habit of occupying in Bob's room. The cat lay at his feet. I was prepossessed in the young man's favor the moment I set eyes upon him. He was tall and fair, a true Saxon in feature and complexion. There was an engaging frankness in his manner, and his bearing was that of a gentleman. He aroused my curiosity by a habit he had of closing his eyes when any earnest subject occupied his mind. He closed them now as he sat upon his chair, and when he
  • 85. opened them he said, in a singularly gentle voice, "My uncle has told you I am blind, Mr. Emery?" "Yes," I replied; "I sincerely sympathize with you. "Thank you. It is a great misfortune; but there are compensations. There are always compensations, Mr. Emery, even for the worst that can happen to a man." "It is good if one can think so," I remarked. “As a rule men are not patient when things are not as they wish." "It is not only useless to repine," was his reply, "it is foolish, and morally weak. For, admitting that there is such a principle as divine justice, we must also admit a divine interposition even in the small matters of human life. I should not speak so freely if my uncle had not told me of his early association with you, and of the friendly and affectionate greeting he received from you after a separation of nearly forty years. I look upon you already as a friend." "I am glad to hear you say so; we will seal the compact." I pressed his hand once more, and he responded as I would have wished him to respond. "I knew you would like each other," said Bob. "When I closed my eyes just now," resumed Ronald Elsdale, "it was because of the impression I had that there was some other living creature in the room beside ourselves." Bob and I exchanged glances, and Bob said: "We three are the only living creatures within these four walls of mine."
  • 86. "Of course, of course. Mr. Emery said so, and it is not likely he would deceive me. Blind people, Mr. Emery, are generally very suspicious; it follows naturally upon their affliction. Seeing nothing, they doubt much, and are ever in fear that they are being imposed upon and deceived. I am happy to say this is not the case with me; where I have not a fixed opinion I generally believe what is told me." A pang of self-reproach shot through me as he spoke. Here was I, in my very first interview with this frank and ingenuous young gentleman, deliberately deceiving him. Bob, also, did not seem quite at his ease. He was playing with his lower lip, always an indication in him of mental disturbance. "You said something just now," I observed, with a wish to change the subject, "about compensations for misfortune, and I infer that you have compensations for yours. But it must cause you regret?" "It does, but I do not fret, I do not take it to heart; I accept the inevitable. The proper use of the higher intelligence with which we are gifted is to reason calmly upon all human and worldly matters which touch us nearly. Those who can thus reason have cause for gratitude; and I have cause. Compensations? Yes, I have them. Difficult to describe, perhaps, because they are spiritual; inspired by faith or self-delusion, which stern materialists declare are one and the same thing." "Your uncle and I," I said, "were having a discussion upon delusions when you entered." "In continuation"--he turned to Bob; he seemed to know always where the person he was addressing was standing or sitting--"in continuation of the discussion we were having this afternoon?" "Yes," said Bob, "and we do not quite agree." "My uncle is a skeptic," said Ronald, "he does not believe in miracles."
  • 87. Welcome to our website – the perfect destination for book lovers and knowledge seekers. We believe that every book holds a new world, offering opportunities for learning, discovery, and personal growth. That’s why we are dedicated to bringing you a diverse collection of books, ranging from classic literature and specialized publications to self-development guides and children's books. More than just a book-buying platform, we strive to be a bridge connecting you with timeless cultural and intellectual values. With an elegant, user-friendly interface and a smart search system, you can quickly find the books that best suit your interests. Additionally, our special promotions and home delivery services help you save time and fully enjoy the joy of reading. Join us on a journey of knowledge exploration, passion nurturing, and personal growth every day! ebookbell.com