100% found this document useful (2 votes)
23 views

(Ebook) Practical Web 2.0 Applications with PHP by Quentin Zervaas ISBN 9781430204749, 9781590599068, 1430204745, 1590599063 pdf download

The document is an overview of the ebook 'Practical Web 2.0 Applications with PHP' by Quentin Zervaas, which focuses on building a collaborative blogging tool using PHP and various web technologies. It emphasizes the application of real-world programming concepts and the use of the Zend Framework for development. The book includes detailed chapters on planning, designing, and implementing a complete web application with Web 2.0 features.

Uploaded by

evenirxaq
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
23 views

(Ebook) Practical Web 2.0 Applications with PHP by Quentin Zervaas ISBN 9781430204749, 9781590599068, 1430204745, 1590599063 pdf download

The document is an overview of the ebook 'Practical Web 2.0 Applications with PHP' by Quentin Zervaas, which focuses on building a collaborative blogging tool using PHP and various web technologies. It emphasizes the application of real-world programming concepts and the use of the Zend Framework for development. The book includes detailed chapters on planning, designing, and implementing a complete web application with Web 2.0 features.

Uploaded by

evenirxaq
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 52

(Ebook) Practical Web 2.

0 Applications with PHP


by Quentin Zervaas ISBN 9781430204749,
9781590599068, 1430204745, 1590599063 download

https://ebooknice.com/product/practical-web-2-0-applications-
with-php-1408206

Explore and download more ebooks at ebooknice.com


Here are some recommended products for you. Click the link to
download, or explore more at ebooknice.com

(Ebook) Practical Web 2.0 Applications with PHP by Quentin


Zervaas ISBN 9781430204749, 1430204745

https://ebooknice.com/product/practical-web-2-0-applications-with-
php-36180122

(Ebook) Biota Grow 2C gather 2C cook by Loucas, Jason; Viles,


James ISBN 9781459699816, 9781743365571, 9781925268492,
1459699815, 1743365578, 1925268497

https://ebooknice.com/product/biota-grow-2c-gather-2c-cook-6661374

(Ebook) Matematik 5000+ Kurs 2c Lärobok by Lena Alfredsson, Hans


Heikne, Sanna Bodemyr ISBN 9789127456600, 9127456609

https://ebooknice.com/product/matematik-5000-kurs-2c-larobok-23848312

(Ebook) SAT II Success MATH 1C and 2C 2002 (Peterson's SAT II


Success) by Peterson's ISBN 9780768906677, 0768906679

https://ebooknice.com/product/sat-ii-success-math-1c-and-2c-2002-peterson-
s-sat-ii-success-1722018
(Ebook) Master SAT II Math 1c and 2c 4th ed (Arco Master the SAT
Subject Test: Math Levels 1 & 2) by Arco ISBN 9780768923049,
0768923042

https://ebooknice.com/product/master-sat-ii-math-1c-and-2c-4th-ed-arco-
master-the-sat-subject-test-math-levels-1-2-2326094

(Ebook) Cambridge IGCSE and O Level History Workbook 2C - Depth


Study: the United States, 1919-41 2nd Edition by Benjamin
Harrison ISBN 9781398375147, 9781398375048, 1398375144,
1398375047
https://ebooknice.com/product/cambridge-igcse-and-o-level-history-
workbook-2c-depth-study-the-united-states-1919-41-2nd-edition-53538044

(Ebook) PHP Web 2.0 Mashup Projects: Practical PHP Mashups with
Google Maps, Flickr, Amazon, YouTube, MSN Search, Yahoo!: Create
practical mashups in PHP grabbing ... MSN Search, Yahoo!,
Last.fm, and 411Sync.com by Shu-Wai Chow ISBN 9781847190888,
184719088X
https://ebooknice.com/product/php-web-2-0-mashup-projects-practical-php-
mashups-with-google-maps-flickr-amazon-youtube-msn-search-yahoo-create-
practical-mashups-in-php-grabbing-msn-search-yahoo-last-fm-and-411sync-
com-1287034

(Ebook) Web Database Applications with PHP & MySQL by Hugh E.


Williams ISBN 9780596007249, 0596007248

https://ebooknice.com/product/web-database-applications-with-php-
mysql-1272572

(Ebook) Web 2.0 Heroes: Interviews with 20 Web 2.0 Influencers


by Bradley L. Jones ISBN 9780470241998, 9780470378953,
0470241993, 0470378956

https://ebooknice.com/product/web-2-0-heroes-interviews-
with-20-web-2-0-influencers-4314944
 CYAN  YELLOW
 MAGENTA BLACK
 PANTONE 123 C

Books for professionals by professionals ® The EXPERT’s VOIce ® in Web Development


Companion
eBook Available
Practical Web 2.0 Applications with PHP
Dear Reader,
Practical
Many programming books on the market today focus specifically on a particu-

Practical

Web 2.0 Applications with PHP


lar methodology or software package, and although you will gain a solid under-
standing of the subject matter from these books, you won’t always know how
to apply what you’ve learned in a real-world situation. This book is designed
to show you how to bring together many different ideas and features by start-

Web 2.0
ing with a clean slate and gradually building the code base so it evolves into a
complete web application.
The premise of the application we build in this book is that it is a “Web 2.0”
application. What this means is that (among other things) our application gen-
erates accessible and standards-compliant code while making heavy of use of

PHP
Ajax. We achieve this by using the Smarty™ Template Engine and Cascading
Style Sheets, as well as the Prototype JavaScript library. Additionally, we create
a fun and intuitive interface by applying simple visual effects on various pages
using the Script.aculo.us JavaScript library.

Applications with
To help with the development of the extensive PHP code in this book, we
use the Zend Framework. This is an open source PHP 5 library that contains
many different components that you can easily use in any of your day-to-day
development. We use many of the Zend Framework components in this book, such
as database abstraction (with a focus on MySQL® and PostgreSQL), logging,
authentication, and search.
The “Web 2.0” application that we build in this book is a collaborative
blogging tool. It will allow users to register and create a personal blog. When
creating blog posts, users will be able upload images, apply tags, and assign
locations (using Google Maps). We will also look at how to use microformats
when displaying user blog posts.

Quentin Zervaas Develop a complete PHP web application


from start to finish
Companion eBook Related Titles

See last page for details


on $10 eBook version

SOURCE CODE ONLINE


www.apress.com
ISBN-13: 978-1-59059-906-8
ISBN-10: 1-59059-906-3
Quentin Zervaas
54499

US $44.99
Zervaas
Shelve in
PHP

User level:
9 781590 599068
Intermediate–Advanced

this print for content only—size & color not accurate spine = 1.1163" 592 page count
9063CH00CMP3 11/19/07 8:39 PM Page i

Practical Web 2.0


Applications with PHP

Quentin Zervaas
9063CH00CMP3 11/19/07 8:39 PM Page ii

Practical Web 2.0 Applications with PHP


Copyright © 2008 by Quentin Zervaas
All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means,
electronic or mechanical, including photocopying, recording, or by any information storage or retrieval
system, without the prior written permission of the copyright owner and the publisher.
ISBN-13 (pbk): 978-1-59059-906-8
ISBN-10 (pbk): 1-59059-906-3
ISBN-13 (electronic): 978-1-4302-0474-9
ISBN-10 (electronic): 1-4302-0474-5
Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1
Trademarked names may appear in this book. Rather than use a trademark symbol with every occurrence
of a trademarked name, we use the names only in an editorial fashion and to the benefit of the trademark
owner, with no intention of infringement of the trademark.
Lead Editor: Ben Renow-Clarke
Technical Reviewer: Jeff Sambells
Editorial Board: Steve Anglin, Ewan Buckingham, Tony Campbell, Gary Cornell, Jonathan Gennick,
Jason Gilmore, Kevin Goff, Jonathan Hassell, Matthew Moodie, Joseph Ottinger, Jeffrey Pepper,
Ben Renow-Clarke, Dominic Shakeshaft, Matt Wade, Tom Welsh
Project Manager: Richard Dal Porto
Copy Editors: Andy Carroll, Kim Wimpsett
Assistant Production Director: Kari Brooks-Copony
Production Editor: Liz Berry
Compositor: Diana Van Winkle
Proofreader: Lisa Hamilton
Indexer: Broccoli Information Management
Artist: Diana Van Winkle
Cover Designer: Kurt Krames
Manufacturing Director: Tom Debolski
Distributed to the book trade worldwide by Springer-Verlag New York, Inc., 233 Spring Street, 6th Floor,
New York, NY 10013. Phone 1-800-SPRINGER, fax 201-348-4505, e-mail orders-ny@springer-sbm.com, or
visit http://www.springeronline.com.
For information on translations, please contact Apress directly at 2855 Telegraph Avenue, Suite 600,
Berkeley, CA 94705. Phone 510-549-5930, fax 510-549-5939, e-mail info@apress.com, or visit
http://www.apress.com.
The information in this book is distributed on an “as is” basis, without warranty. Although every precaution
has been taken in the preparation of this work, neither the author(s) nor Apress shall have any liability to any
person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by
the information contained in this work.
The source code for this book is available to readers at http://www.apress.com.
9063CH00CMP3 11/19/07 8:39 PM Page iii

Contents at a Glance

About the Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv


About the Technical Reviewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii

■CHAPTER 1 Application Planning and Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1


■CHAPTER 2 Setting Up the Application Framework . . . . . . . . . . . . . . . . . . . . . . . . . . 9
■CHAPTER 3 User Authentication, Authorization, and Management . . . . . . . . . . . . . 45
■CHAPTER 4 User Registration, Login, and Logout . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
■CHAPTER 5 Introduction to Prototype and Scriptaculous . . . . . . . . . . . . . . . . . . 123
■CHAPTER 6 Styling the Web Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
■CHAPTER 7 Building the Blogging System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
■CHAPTER 8 Extending the Blog Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
■CHAPTER 9 Personalized User Areas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
■CHAPTER 10 Implementing Web 2.0 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
■CHAPTER 11 A Dynamic Image Gallery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
■CHAPTER 12 Implementing Site Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
■CHAPTER 13 Integrating Google Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
■CHAPTER 14 Deployment and Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
■INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547

iii
9063CH00CMP3 11/19/07 8:39 PM Page iv
9063CH00CMP3 11/19/07 8:39 PM Page v

Contents

About the Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv


About the Technical Reviewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii

■CHAPTER 1 Application Planning and Design .......................... 1


What Is Web 2.0? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Database Connectivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Web Site Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Web Site Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Main Home Page and User Home Page . . . . . . . . . . . . . . . . . . . . . . . . 3
User Registration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Account Login and Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
User Blogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Web Site Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Application Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Other Aspects of Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Search-Engine Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
PHPDoc-Style Commenting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Application Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Maintainability and Extensibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Version Control and Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

■CHAPTER 2 Setting Up the Application Framework ....................9


Web Server Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Operating System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Installing the Apache HTTP Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Installing MySQL 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Installing PHP 5.2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

v
9063CH00CMP3 11/19/07 8:39 PM Page vi

vi ■CONTENTS

Application Filesystem Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12


Web Root Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Data Storage Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
PHP Classes Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Templates Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Full Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Installing the Zend Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Configuring the Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Creating a Virtual Host in Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Creating a Virtual Host in Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Restarting Your Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Setting Up the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Using the Model-View-Controller Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Separating Application Logic from Presentation Logic . . . . . . . . . . . 19
Directing All Requests to index.php . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Introduction to the Zend_Controller Class . . . . . . . . . . . . . . . . . . . . . 22
How Requests Work with Zend_Controller . . . . . . . . . . . . . . . . . . . . . 23
Creating the IndexController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Defining Application Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Connecting to the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Testing the Database Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
The Smarty Template Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Why Not Use a Different Template Engine? . . . . . . . . . . . . . . . . . . . . 33
Downloading and Installing Smarty . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Automatic View Rendering with Zend_Controller . . . . . . . . . . . . . . . 36
Integrating Smarty with the Web Site Controllers . . . . . . . . . . . . . . . 39
Adding Logging Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Writing to the Log File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

■CHAPTER 3 User Authentication, Authorization, and Management . . . . . . 45


Creating the User Database Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Timestamps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
User Profiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Introduction to Zend_Auth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Instantiating Zend_Auth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Authenticating with Zend_Auth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Introduction to Zend_Acl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
A Zend_Acl Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
9063CH00CMP3 11/19/07 8:39 PM Page vii

■CONTENTS vii

Combining Zend_Auth, Zend_Acl, and Zend_Controller_Front . . . . . . . . 57


Managing User Records with DatabaseObject . . . . . . . . . . . . . . . . . . . . . . 61
The DatabaseObject_User Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Using DatabaseObject_User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Managing User Profiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Using Profile_User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Integrating Profile_User with DatabaseObject_User . . . . . . . . . . . . 69
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

■CHAPTER 4 User Registration, Login, and Logout . . . . . . . . . . . . . . . . . . . . . 73


Adding User Registration to the Application . . . . . . . . . . . . . . . . . . . . . . . . 73
Creating the Form Processor for User Registration . . . . . . . . . . . . . 74
Displaying the Registration Form and Processing Registrations . . . 81
Adding CAPTCHA to the User Registration Form . . . . . . . . . . . . . . . . 88
Adding E-mail Functionality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Implementing Account Login and Logout . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Creating the Login Template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Adding the Account Controller Login Action . . . . . . . . . . . . . . . . . . . 102
Logging Successful and Failed Login Attempts . . . . . . . . . . . . . . . . 105
Logging Users Out of Their Accounts . . . . . . . . . . . . . . . . . . . . . . . . 107
Dealing with Forgotten Passwords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Resetting a User’s Password . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Functions for Resetting Passwords . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Implementing Account Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Creating the Account Home Page . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Updating the Web Site Navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Allowing Users to Update Their Details . . . . . . . . . . . . . . . . . . . . . . . 120
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

■CHAPTER 5 Introduction to Prototype and Scriptaculous . . . . . . . . . . . . 123


Downloading and Installing Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Prototype Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Selecting Objects in the Document Object Model . . . . . . . . . . . . . . . . . . . 124
The $() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
The getElementsByClassName() Function . . . . . . . . . . . . . . . . . . . . 125
The $$() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
The getElementsBySelector() Function . . . . . . . . . . . . . . . . . . . . . . . 129
Prototype’s Hash Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

vii
9063CH00CMP3 11/19/07 8:39 PM Page viii

viii ■CONTENTS

Other Element Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130


Showing and Hiding Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Retrieving Dimensions of Elements . . . . . . . . . . . . . . . . . . . . . . 131
Managing Classes of Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Manipulating Strings with Prototype . . . . . . . . . . . . . . . . . . . . . . . . . 133
Ajax Operations in Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Ajax Request Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Ajax Callback Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
JavaScript Object Notation (JSON) . . . . . . . . . . . . . . . . . . . . . . . . . . 138
An Ajax.Request Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Event Handling in Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Observing an Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Finding Out Which Element an Event Occurred On . . . . . . . . . . . . . 146
Canceling an Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Creating JavaScript Classes in Prototype . . . . . . . . . . . . . . . . . . . . . . . . . 147
Creating a Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Binding Function Calls to Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
From Prototype to Scriptaculous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Prebuilt Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Drag and Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Visual Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
DOM Element Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
JavaScript Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Downloading and Installing Scriptaculous . . . . . . . . . . . . . . . . . . . . . . . . . 154
Combining Prototype, Scriptaculous, Ajax, and PHP
in a Useful Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Creating the Main HTML Page: index.php . . . . . . . . . . . . . . . . . . . . 156
Styling the Application: styles.css . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Creating and Populating the Database: schema.sql . . . . . . . . . . . . 158
Managing the List Items on the Server Side: items.php . . . . . . . . 159
Processing Ajax Requests on the Server Side: processor.php . . . 161
Creating the Client-Side Application Logic: scripts.js . . . . . . . . . . . 163
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

■CHAPTER 6 Styling the Web Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171


Adding Page Titles and Breadcrumbs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
The Breadcrumbs Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Generating URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Setting the Title and Trail for Each Controller Action . . . . . . . . . . . . 178
Creating a Smarty Plug-In to Output Breadcrumbs . . . . . . . . . . . . 180
Displaying the Page Title . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
809b8b6f91d5ff50033254241f3132ed
9063CH00CMP3 11/19/07 8:39 PM Page ix

■CONTENTS ix

Integrating the Design into the Application . . . . . . . . . . . . . . . . . . . . . . . . 183


Creating the Static HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Moving the HTML Markup into Smarty Templates . . . . . . . . . . . . . 188
Constructing the CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Specifying Media Types and Loading the CSS File . . . . . . . . . . . . . 192
Creating the Application CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
Creating a Print-Only Style Sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
The Full Application Style Sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Styling the Application Web Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Loading Prototype and Scriptaculous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Implementing Client-Side Form Validation . . . . . . . . . . . . . . . . . . . . . . . . . 208
Adding JSON Support to CustomControllerAction . . . . . . . . . . . . . . 209
Modifying the Form Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Modifying the Registration Controller Action . . . . . . . . . . . . . . . . . . 210
Creating the JavaScript Form Validator . . . . . . . . . . . . . . . . . . . . . . . 212
Loading the UserRegistrationForm Class . . . . . . . . . . . . . . . . . . . . . 216
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

■CHAPTER 7 Building the Blogging System . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219


Creating the Database Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
Setting Up DatabaseObject and Profile Classes . . . . . . . . . . . . . . . . . . . . 221
Creating the DatabaseObject_BlogPost Class . . . . . . . . . . . . . . . . . 221
Creating the Profile_BlogPost Class . . . . . . . . . . . . . . . . . . . . . . . . . 223
Creating a Controller for Managing Blog Posts . . . . . . . . . . . . . . . . . . . . . 223
Extending the Application Permissions . . . . . . . . . . . . . . . . . . . . . . . 223
The BlogmanagerController Actions . . . . . . . . . . . . . . . . . . . . . . . . . 225
Linking to Blog Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Creating and Editing Blog Posts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Creating the Blog Post Submission Form Template . . . . . . . . . . . . 228
Instantiating FormProcessor_BlogPost in editAction() . . . . . . . . . . 231
Implementing the FormProcessor_BlogPost Class . . . . . . . . . . . . . 233
Generating a Permanent Link to a Blog Post . . . . . . . . . . . . . . . . . . 240
Filtering Submitted HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
Creating a New Blog Post . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Previewing Blog Posts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
Creating the Preview Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Implementing the Preview Template . . . . . . . . . . . . . . . . . . . . . . . . . 249
Requesting Confirmation for User Actions . . . . . . . . . . . . . . . . . . . . 252
9063CH00CMP3 11/19/07 8:39 PM Page x

x ■CONTENTS

Updating the Status of a Blog Post . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254


Completing setstatusAction() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
Notifying the User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262

■CHAPTER 8 Extending the Blog Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265


Listing Blog Posts on the Blog Manager Index . . . . . . . . . . . . . . . . . . . . . 265
Fetching Blog Posts from the Database . . . . . . . . . . . . . . . . . . . . . . 266
Assigning Recent Posts and the Monthly Summary
to the Template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
Displaying Recent Posts in the Template . . . . . . . . . . . . . . . . . . . . . 276
Displaying the Monthly Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Ajaxing the Blog Monthly Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
Creating the Ajax Request Output . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
The BlogMonthlySummary JavaScript Class . . . . . . . . . . . . . . . . . . 285
Installing the BlogMonthlySummary Class . . . . . . . . . . . . . . . . . . . . 287
Notifying the User About the Content Update . . . . . . . . . . . . . . . . . . 287
Integrating a WYSIWYG Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Downloading and Installing FCKeditor . . . . . . . . . . . . . . . . . . . . . . . 292
Configuring FCKeditor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Loading FCKeditor in the Blog Editing Page . . . . . . . . . . . . . . . . . . . 294
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296

■CHAPTER 9 Personalized User Areas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297


Controlling User Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Presenting Customizable Settings to Users . . . . . . . . . . . . . . . . . . . 298
Processing Changes to User Settings . . . . . . . . . . . . . . . . . . . . . . . . 299
Creating Default User Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
The UserController Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
Routing Requests to UserController . . . . . . . . . . . . . . . . . . . . . . . . . . 303
Handling Requests to UserController . . . . . . . . . . . . . . . . . . . . . . . . . 309
Displaying the User’s Blog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Displaying the Blog Index Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Displaying Individual Blog Posts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
Generating Blog Archive Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
Displaying the Monthly Archive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Populating the Application Home Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
Loading Recent Public Posts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
Implementing the Application Home Page . . . . . . . . . . . . . . . . . . . . 327
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
9063CH00CMP3 11/19/07 8:39 PM Page xi

■CONTENTS xi

■CHAPTER 10 Implementing Web 2.0 Features . . . . . . . . . . . . . . . . . . . . . . . . . . 335


Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
Implementing Tagging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
Managing Blog Post Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Displaying a User’s Tags on Their Blog . . . . . . . . . . . . . . . . . . . . . . . 344
Displaying a Tag Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Displaying Tags on Each Post . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Web Feeds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Data Formats for Web Feeds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Creating an Atom Feed with Zend_Feed . . . . . . . . . . . . . . . . . . . . . . 352
Adding the Feed to UserController . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
Linking to Your Feed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
Other Feed Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Microformats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
An Example of Using Microformats . . . . . . . . . . . . . . . . . . . . . . . . . . 358
Why Use Microformats? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
Microformatting Your Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Allowing Users to Create a Public Profile . . . . . . . . . . . . . . . . . . . . . . . . . . 363
Allowing Users to Create a Public Profile . . . . . . . . . . . . . . . . . . . . . 363
Displaying a User’s Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369

■CHAPTER 11 A Dynamic Image Gallery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371


Storing Uploaded Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
Creating the Database Table for Image Data . . . . . . . . . . . . . . . . . . 373
Controlling Uploaded Images with DatabaseObject . . . . . . . . . . . . 373
Uploading Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
Setting the Form Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Adding the Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Specifying the File Input Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Setting the Maximum File Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
Handling Uploaded Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
Sending Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
Resizing Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
Creating Thumbnails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
Linking the Thumbnailer to the Image Action Handler . . . . . . . . . . 395
9063CH00CMP3 11/19/07 8:39 PM Page xii

xii ■CONTENTS

Managing Blog Post Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399


Automatically Loading Blog Post Images . . . . . . . . . . . . . . . . . . . . . 399
Displaying Images on the Post Preview . . . . . . . . . . . . . . . . . . . . . . 401
Deleting Blog Post Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Using Scriptaculous and Ajax to Delete Images . . . . . . . . . . . . . . . 406
Deleting Images when Posts Are Deleted . . . . . . . . . . . . . . . . . . . . . 411
Reordering Blog Post Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412
Displaying Images on User Blogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
Extending the GetPosts() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
Displaying Thumbnail Images on Blog Index . . . . . . . . . . . . . . . . . . 418
Displaying Images on the Blog Details Page . . . . . . . . . . . . . . . . . . 420
Displaying Larger Images with Lightbox . . . . . . . . . . . . . . . . . . . . . . 422
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425

■CHAPTER 12 Implementing Site Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427


Introduction to Zend_Search_Lucene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
Comparison to MySQL Full-Text Indexing . . . . . . . . . . . . . . . . . . . . . 428
Zend_Search_Lucene Field Types . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
Field Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
Indexing Application Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
Indexing Multiple Types of Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
Creating a New Zend_Search_Lucene_Document . . . . . . . . . . . . . 431
Retrieving the Index Location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
Building the Entire Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
Indexing and Unindexing a Single Blog Post . . . . . . . . . . . . . . . . . . 435
Triggering Search Index Updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
Creating the Search Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
Adding the Search Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
Handling Search Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
Querying the Search Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
Displaying Search Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
Types of Searches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
Adding Autocompletion to the Search Tool . . . . . . . . . . . . . . . . . . . . . . . . 452
Providing Search Suggestions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
Creating an Action Handler to Return Search Results . . . . . . . . . . 453
Retrieving Search Suggestions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
Loading the SearchSuggestor Class . . . . . . . . . . . . . . . . . . . . . . . . . 457
Displaying Search Suggestions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
Adding Mouse Navigation to Results . . . . . . . . . . . . . . . . . . . . . . . . . 460
Adding Keyboard Navigation to Results . . . . . . . . . . . . . . . . . . . . . . 462
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
9063CH00CMP3 11/19/07 8:39 PM Page xiii

■CONTENTS xiii

■CHAPTER 13 Integrating Google Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469


Google Maps Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
Geocoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
Displaying Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
Controlling Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
Planning Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
Limitations of Google Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
Browser Compatibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
Documentation and Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
Creating a Google Maps API Key . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
Adding Location Storage Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Creating the Database Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Creating the DatabaseObject_BlogPostLocation Class . . . . . . . . . 475
Modifying Blog Posts to Load Locations . . . . . . . . . . . . . . . . . . . . . . 477
Creating Our First Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
Creating a New Blog Manager Controller Action . . . . . . . . . . . . . . . 479
Displaying Your First Google Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
Managing Locations on the Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
Handling Location Management Ajax Requests . . . . . . . . . . . . . . . 487
Creating the Address Lookup Form . . . . . . . . . . . . . . . . . . . . . . . . . . 492
Extending the BlogLocationManager JavaScript Class . . . . . . . . . 493
Using BlogLocationManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
Displaying the Map on Users’ Public Blogs . . . . . . . . . . . . . . . . . . . . . . . . 509
Outputting Locations Using the Geo Microformat . . . . . . . . . . . . . . 509
Creating the BlogLocations Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
Updating the Blog Post Display Template . . . . . . . . . . . . . . . . . . . . . 514
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516

■CHAPTER 14 Deployment and Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519


Application Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
E-mailing Critical Errors to an Administrator . . . . . . . . . . . . . . . . . . 519
Using Application Logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
Site Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
Objectives of Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
Handling Predispatch Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
Application Runtime Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
Web Site Administration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Administrator Section Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Implementing Administration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
9063CH00CMP3 11/19/07 8:39 PM Page xiv

Application Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538


Different Configurations for Different Servers . . . . . . . . . . . . . . . . . 538
Deploying Application Files with Rsync . . . . . . . . . . . . . . . . . . . . . . . 542
Backup and Restore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
Exporting a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
Importing a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545

■INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
9063CH00CMP3 11/19/07 8:39 PM Page xv

About the Author

■QUENTIN ZERVAAS is a web developer based in Adelaide, South Australia, where he has been
self-employed since 2003. After receiving his bachelor’s degree in computer science from the
University of Adelaide in 2001, Quentin worked for several web development firms before
branching out on his own, developing a wide range of custom web applications for customers
all around the world.
Quentin has recently started a new company called Recite Media (http://www.recite.
com.au) with two partners. Recite Media develops web applications primarily for other devel-
opment or design companies to resell. Its flagship product, Recite CMS, is being used by
some of Australia’s largest companies.
Quentin also runs and writes for his PHP development resource site, PhpRiot (www.phpriot.com),
which provides a number of useful articles on a wide variety of PHP-related topics.
After completing his role as the technical reviewer for Beginning Ajax with PHP: From
Novice to Professional (Apress, 2006), he decided to undertake writing this book.

xv
9063CH00CMP3 11/19/07 8:39 PM Page xvi

About the Technical Reviewer

■JEFFREY SAMBELLS is a graphic designer and self-taught web application developer best
known for his unique ability to merge the visual world of graphics with the mental realm of
code. After obtaining his bachelor’s of technology degree in graphic communications manage-
ment with a minor in multimedia, Jeffrey originally enjoyed the paper-and-ink printing
industry, but he soon realized the world of pixels and code was where his ideas would prosper.
Jeffrey has previously published articles related to print design and has contributed to
award-winning graphical and Internet software designs. His latest book, AdvancED DOM
Scripting: Dynamic Web Design Techniques (friends of ED, 2007), was an instant success. In
late 2005, Jeffrey also became a PHP 4 Zend Certified Engineer; he updated the certification to
PHP 5 in September 2006 to become one of the first PHP 5 Zend Certified Engineers. Jeffrey
also maintains a blog at http://jeffreysambells.com where he discusses his thoughts about
everything from web development to photography.
He currently lives and plays in Ontario, Canada, with his wife, Stephanie; his daughter,
Addison; and their little dog, Milo.

xvi
9063CH00CMP3 11/19/07 8:39 PM Page xvii

Introduction

M any of today’s web development books and articles cover single aspects of the development
life cycle, delving only into specific features rather than looking at the whole picture.
In this book, we will develop a complete web application. Although we will be using various
third-party libraries and tools to aid in development, we will be developing the application from
start to finish.
The focus of this book is on Web 2.0, a catchphrase that has been in use for a few years
now and is typically used to refer to web sites or web applications that have particular charac-
teristics. Some of these characteristics include the following:

• Correctly using HTML/XHTML, CSS, and other standards

• Using Ajax (Asynchronous JavaScript and XML) to provide a responsive application


without requiring a full refresh of pages

• Allowing syndication of web site content using RSS

• Adding wikis, blogs, or tags

Although not everybody is an advocate of the “Web 2.0” phrase, the term does signify
forward progress in web development. And although not everybody has the need to provide
a wiki or a blog on their web site, the other characteristics listed (such as correct standards
usage) provide a good basis for a web site and should be used by all developers, regardless of
how they want their web site or application categorized.
I wrote this book because I want to share with other users how I build web sites. Having
been a web developer for ten years now (full-time for the past seven), I have a solid under-
standing of a wide range of web-related topics and have much to offer newer developers or
developers looking to expand their own knowledge.

Who This Book Is For


This book has been written primarily for intermediate to expert PHP programmers. Although
programmers of all levels will benefit from this book, we do jump in to the deep end very
quickly, so some prior knowledge of PHP is assumed.
Having said that, if you’re relatively new to PHP, you will definitely benefit from this book
because it will formalize some of the techniques you have already learned and will show you
some different ways of approaching various problems.
In this book, I have made the assumption that you are familiar with HTML and CSS,
although since most of the code developed in this book is PHP and JavaScript, an advanced
knowledge of HTML and CSS is not critical. All JavaScript code is explained thoroughly, which,
in combination with the Prototype JavaScript library we will be using, makes the listings rela-
tively straightforward.
xvii
9063CH00CMP3 11/19/07 8:39 PM Page xviii

xviii ■INTRODUCTION

How This Book Is Structured


We will start the book by determining which features to implement in our web application
and then implement each one as we progress through the book. Each chapter will add a new
set of features to the application, until reaching the final chapter where we look at strategies
for deploying the application.
The specific type of application we develop in this book (a multiuser blogging system) is
not particularly important; rather, it is used simply as a tool to show you the process of devel-
oping a web application. Each chapter is specifically designed to demonstrate particular
aspects of development that may arise regardless of the type of application:

• Chapter 1, Application Planning and Design. We begin the book by looking at what
defines Web 2.0, as well as looking briefly at the features that will be implemented in
the application. Additionally, this chapter covers various aspects of the web develop-
ment life cycle that should be considered when planning and implementing web
applications.

• Chapter 2, Setting Up the Application Framework. In this chapter, we begin to imple-


ment the web application. This process begins by correctly setting up the environment
(that is, installing the correct web server software) and then by creating the initial file
structure of the site. In addition to connecting to the database with PHP, we will handle
user requests with the Zend Framework and manage HTML code using the Smarty
Template Engine.

• Chapter 3, User Authentication, Authorization, and Management. This chapter gives


the first look at using a database. We look at how to easily manage database data when
we implement the user system. Additionally, we look at how a role-based permissions
system works and then implement it into the application.

• Chapter 4, User Registration, Login, and Logout. Continuing from Chapter 3, this
chapter shows how to implement a user registration system. Since this is the first time
the book deals with user-submitted data, this chapter looks at how to correctly deal
with such data when we create the registration and login forms.

• Chapter 5, Introduction to Prototype and Scriptaculous. Since we make heavy use of


JavaScript and Ajax in later chapters, we move away from the main application in this
chapter while we explore two of the most useful JavaScript libraries available. Prototype
helps programmers develop easily maintainable cross-platform JavaScript code, while
Scriptaculous simplifies the process of adding appealing visual effects to web pages.

• Chapter 6, Styling the Web Application. In this chapter, we step back slightly from the
web application in that we focus more on the user experience rather than on the main
application features. We first look at implementing various navigational items (which
also gives us a first taste of developing custom Smarty plug-ins), and we then complete
the chapter by implementing a simple and clean web design into the application.
Random documents with unrelated
content Scribd suggests to you:
Margot vände sig om. Hon kunde ännu ropa honom tillbaka. Men
hvarför det? Hvad kunde hon väl säga honom för att ställa saken till
rätta emellan dem? Han ville icke gifva efter och hon kunde det icke
häller.

Ögonblicket därpå stängdes dörren efter honom och hans snabba,


bestämda steg genljödo i trappan. Margot stirrade alldeles förvirrad
ned framför sig och viste knappast hvad som händt. John Croft
älskade henne och hade kommit för att säga henne det och för att
be henne bli hans hustru. Hans hustru — John Crofts hustru — och
hon hade gifvit honom afslag!

Ytterdörren slog igen med en skräll. Alt var förbi — alt; hon skulle
aldrig mera få återse honom.
XIV.

Andante con variazione.

Det var måhända en riktig lycka för Margot, att hennes tankar
under den närmast påföljande tiden så helt och hållet voro upptagna
af Valérie. Den sorgsenhet, som annars hade kommit öfver henne,
blef därigenom till en viss grad afledd. Valérie hade efter konserten
försjunkit i den djupaste nedslagenhet. Hon åt icke, hon sof illa, hon
ville icke tala och hon visade bort alla tröstegrunder.

— Låt mig vara i fred, sade hon, tror du inte jag lika bra som du
vet huru sakerna stå? Denna gång kan vårt fiasko icke mera
godtgöras.

Det återstod således ingenting annat för Margot än att vaka och
bedja, Och hon var mycket mild och tålig och begrafde sina egna
sorgsna tankar. Och Valérie satt hela dagen och stirrade med stora,
dystra ögon in i elden.

Men en dag, då Margot efter en tröttsam eftermiddag kom hem,


fann hon Valérie gående af och an med långa steg och med
händerna i kors på ryggen. Hennes ansikte hade ett sorgset, ja,
nästan tragiskt uttryck.

— Där är du ju! utropade hon och stannade framför Margot. Det


fägnar mig, ty jag har fattat ett beslut, som jag ville meddela dig.

Margot slog leende armen omkring den späda gestalten.

— Hvad är det för ett viktigt beslut? frågade hon.

— Ah, det är inte alls löjligt, skall jag säga dig! Jag tror, att jag
värkligen hittils drömt bort mitt lif. Hvad har det blifvit af alla de
planer vi uppgjorde, af alt det vi hoppades? Det är tid, att jag vaknar
upp och ser värkligheten in i ansiktet. Det är mig icke beskärdt att
röna framgång som konstnärinna; jag måste skjuta denna dröm åt
sidan likasom jag gjort med min fiol. Vet du, Margot, jag har lagt
bort den. Jag har lagt den allra underst i min stora koffert. När jag
gjorde det, föreföll det mig som om jag lagt den i en likkista. Den är
död, stendöd, och vi skola aldrig mera tala därom.

— Söta Valérie, sade Margot med ett skratt, som slutade med en
snyftning, var inte så tragisk! Din fiol dör inte så lätt — den kommer
ännu att lefva för dig och många andra.

— Nej, säger jag dig, den är död och begrafven. Vi skola icke
mera tala därom. Nu ämnar jag taga lifvet från dess allvarliga sida.
Hvarför skall jag låta dig ensam arbeta för vårt uppehälle?
Hädanefter skall jag dela dina mödor och försörja mig själf.

— Och hvad ämnar du göra, stackars liten? frågade Margot, som


smålog med ömt öfverseende, ehuru tårarna stodo i ögonen på
henne.
— Jag har tänkt öfver saken — det finnes icke mycket, som jag
kan göra. Jag kan icke gifva undervisning, emedan jag ej har
tålamod därtill. Jag tror, att jag skulle bli galen, om jag liksom du
hela dagen nödgades bråka med dumma barn. Jag skulle slå dem på
händerna, när de spelade falskt. Och jag kan inte sy. Därför tänkte
jag, att jag skulle börja måla — julkort, du vet, och påskkort. Det
vore just en lämplig tid nu, då påsken står för dörren.

— Men mitt söta barn, började Margot.

Men Valérie afbröt henne:

— Tst! låt mig tala till punkt, jag har noga öfvervägt alt.
Människorna behöfva alltid kort; julkort och påskkort till de båda
hälgerna och födelsedagskort hela året om. Nå du vet ju, huru
mycket de i butikerna taga för de målade korten: en shilling, en och
en half shilling och mera, Det måste naturligt vara någon, som målar
dessa kort, och denna någon måste ju få betalt för sin möda. Låtom
oss nu antaga, att jag målar tre kort om dagen och får en shilling i
medeltal för hvarje kort. Jag föreställer mig, att jag får nittio pence
för shillingskorten och en shilling och tre pence för de öfriga. Det
vore tre shilling om dagen — således aderton shilling i veckan. Är
det inte bra uttänkt?

Hon smålog nu faktiskt och hennes lilla ansikte såg helt belåtet ut.
Men Margot hade mera lust att gråta än att skratta.

— Säg, är det inte en utmärkt plan? envisades Valérie.

Margot kyste henne ömt och svarade:


— Ja, det är en utomordentlig plan. Men den har blott en
skuggsida, mitt stackars barn, och det är, att du ej kan måla. Du har
inte haft en enda teckningslektion i hela ditt lif. Huru ämnar du då
realisera din plan?

— Det gör då rakt ingenting, att jag ej haft några lektioner i


teckning, svarade Valérie mycket högdraget. Man behöfver inte
kunna teckna för att måla sådana här bagateller. Jag skall kopiera
andra kort och med tiden öfvar jag upp mig. Men beröfva mig nu
inte modet. Huru skall jag kunna lefva utan att göra någonting?

— Javisst, javisst, och jag vill inte häller beröfva dig modet,
utropade Margot hastigt, ty systerns ansikte mulnade åter och
förödmjukelsens tårar stego upp i ögonen på henne. Jag undrade
bara, huru du ämnade gå tillväga; men det är förstås mycket lätt att
måla dessa kort.

— Ja, det tycker jag också — det kan ju hvem som hälst. Du köper
mig i morgon en liten, nätt färglåda med fina, fina penslar och litet
kalkerpapper och några kort — jag skall börja med de billigare —
och i morgon eftermiddag tager jag ihop med arbetet.

Hon gnuggade händerna och dansade på sitt gamla vis genom


rummet. När alt gick omkring var det ändå en sysselsättning, som
förde henne på andra tankar, tänkte Margot. Det var afgjordt bättre
än att hon hela dagen tyst och olycklig hängde på en stol, medan
hennes ansikte blef alt mindre och mindre och hennes ögon alt
större och större. Hon må gärna syssla med sina kort och färger, hon
tröttnar nog snart därvid. Men denna sysselsättning kunde ju för en
tid vara bra för henne.
Dagen därpå tog Valérie således ihop med arbetet och långt fram
på eftermiddagen erbjöds Margot att skärskåda hennes pensels
första alster. Det var ett gelatinkort, hvars hörn blifvit tämligen
skrynkliga i och genom beröringen med Valéries små heta fingrar.
Midt på kortet stod ett brunt kors, eller det lutade, rättare sagdt, litet
åt höger, och en hvit dufva, hvars ena vinge petade rätt upp i luften
och hvars stjärt var mycket förkrympt, satt på den ena sidan och en
stjälk med förgät-mig-ej, som allesamman hade sex blomblad, låg på
den andra. Inunder detta hade Valérie med röda bokstäfver målat
ordet "Resurgam."

— Ser du, ser du mitt första försök! Tycker du inte det är lyckadt?
Jag har själf tänkt ut altsamman. "Resurgam" passar så bra till
påsken; jag tror det åtminstone, fastän jag inte riktigt vet hvad det
betyder. Korset är inte riktigt rakt, men det märkes väl knappast, då
jag fylt platsen på sidan om det med förgät-mig-ej. Ser du nu,
Margot, du påstod, att jag inte kunde teckna! Och nu har jag ändå
tecknat förgät-mig-ejerna alldeles ur hufvudet och bladen med! Och
min dufva sedan — är den inte söt?

— Ja, det är den visst; men jag förstår inte riktigt hvarför den har
ett rödt band om halsen och jag tror inte, att dufvor bruka draga
ihop stjärten på det där viset. Har du också ritat den ur hufvudet?

— Nej, jag kopierade den efter en rödhakesångare och målade


den hvit — Jag tykte det var ett så bra påhitt — och hvarför kan inte
en dufva sitta stjärten i vädret, då en rödhakesångare gör det? Och
jag målade det röda bandet dit, emedan jag tykte, att det behöfdes
litet färg. Hvarför betraktar du kortet med en så komisk min?

— Jag undrar bara, hvarför du låter den ena vingen sticka så högt
upp i luften — borde man inte då också se den andra?
Valérie sköt häftigt ihop sina penslar och färger.

— Ja, om du klandrar hvarenda smula, så lönar det sig naturligtvis


icke, att jag försöker. Jag trodde, att du skulle glädja dig däråt, och
jag tycker det värkligen inte är så dåligt, då man betänker, att jag
aldrig förut försökt mig på någonting dylikt.

— Nej, min hjärteunge, jag klandrar det visst icke, utrepade


Margot ifrigt. Jag tycker du är mycket skicklig, som kan göra det så
bra, och det var dumt af mig, att jag ej förstod hvad du menade.
Dufvan lutar sig naturligtvis öfver korset ock därför är hennes vinge
utbredd. Den andra är likaledes utbredd, men den kan man ej se.

— Du tycker inte ens om mitt röda band, mumlade Valérie, som


fortfarande var stött. Jag gjorda mig så mycken möda därmed. Jag
försökte ge den lilla knuten på ryggen formen af en riktig
kärleksknut.

Hon höll på att brista i gråt. Då vågade Margot inte ens draga på
munnen, ehuru idésammanställningen föreföll henne så ytterst
komisk. Hon kyste och tröstade den lilla konstnärinnan och hade till
slut den tillfredsställelsen, att hon fullkomligt tröstad åter satte sig
vid arbetet och förkunnade, att hon kanske skulle lämna detta första
kort, som inte var riktigt lyckadt, till sex pence.

— Stackars liten, tänkte Margot; om hon värkligen tror, att någon


människa skall köpa dessa små fasligheter, fruktar jag hon blir bra
besviken. Men kanske hon tröttnat, innan hon hunnit med så många
kort, att det lönar sig att bjuda ut dem.

Men Valérie hade med den för henne egendomliga entusiasmen


kastat sig öfver sin nya sysselsättning. Hon arbetade på detta
vidunder med samma energi, som hon eljes brukade nedlägga på
sina musikstudier. Hennes fingrar, som voro så skickliga, så fina och
smidiga, då det gälde att föra stråken, vore skickliga och tafatta som
ett barns, då det blef fråga om något annat arbete. De voro äfven
nu styfva och oskickliga, men Valérie, som var förtjust i de lysande
färgerna och i sysslandet med penslar och vatten, var mycket
belåten med hvad hon åstadkom. Hon fortfor att måla dufvor och
kors och blommor — de senare med ett totalt förbiseende af all
botanisk sanning; hon försökte måla sprängda ägg, ur hvilka duniga
kycklingar tittade, men hon måste själf tillstå, att de misslyckades för
henne. Sålunda var hon en hel vecka lycklig och belåten. Margot blef
orolig, då dagarna skredo framåt och cremonesaren fortfarande fick
ligga nedbäddad i sin svarta låda och Valérie bara målade sina
påskkort i stället för att åter egna sig åt sin musik. Hon fruktade, att
hennes fingrar skulle bli styfva. Och hon önskade, att Valérie icke
skulle försumma sitt värkliga kall för denna nyck. Och skapade hon
sig icke ånyo svikna förhoppningar: Ingen skulle någonsin på fullt
allvar kasta en blick på dessa hennes konstprodukter. Margot kände,
huru hon rodnade vid tanken på att erbjuda dem åt någon
butikinnehafvare.

Slutligen en morgon fjorton dagar före påsk förkunnade Valérie att


hon nu målat två dussin kort och föreslog, att de skulle gå till en
pappershandel vid High Street, Kensington och uppgöra affären med
butikegaren.

— Jag tager allesamman med mig, sade hon. Det är inalles kort
för tjugofyra shilling, men som äggen och kycklingarna ej lyckats så
bra som de andra, så ämnar jag föreslå honom, att jag skall lämna
honom allesamman för ett pund.
— Huru vore det, om vi skulle lämna ägg- och kycklingskorten
hemma, föreslog Margot rysande, då hon tänkte på dessa
konstvärk?

— Nej, det går absolut inte an! Huru kan du vara så enfaldig! Jag
lämnar ingenting hemma; tjugu är ett så dumt tal; dessutom
kommer försäljaren att anse oss för mycket ädelmodiga, då vi gifva
honom de fyra korten på köpet.

Margot hade ingenting vidare, utan begaf sig med tungt hjärta på
väg. Valérie var däremot vid det gladaste lynne, pratade muntert och
gjorde upp planer om hvad hon alt skulle använda sina inkomster till.

— Det är riktigt förtjusande att själf förtjäna pengar, icke sant? Jag
känner mig så stolt, så stolt! Till och med du, madame Margot,
behöfver tid på dig, innan du förtjänar ett pund.

Då de kommo in i den omtalade butiken, gick Valérie genast fram


till disken och frågade med en så förnäm och viktig min efter
egaren, att denne genast skyndade till för att betjäna henne. Men då
han fann, att den förtjusande varelsen, som tilltalade honom, icke
var någon förnäm dam, utan en anspråkslös konstadept, som
uppmanade honom att köpa ett antal nästan barnsligt utförda
teckningar, stod han ett ögonblick så godt som mållös. Då Valérie,
som icke det minsta blef bragt ur fattningen genom hans tystnad, för
honom förklarade sina åsikter angående det pris, hon ämnade
begära, och huldrikt tillade, att hon denna gång skulle gifva honom
några kort på köpet, skrattade han henne midt upp i ansiktet, sköt
ihop korten och räkte dem med en ironisk bugning.

— De äro icke fullt ut sådana, som vi bruka erbjuda våra kunder.


Jag tror, att de skulle bli bra förvånade, om vi uppmanade dem att
köpa någonting dylikt. Nej, jag tackar, madame, men vi kunna ej
använda edra kort.

Med ansiktet betäkt af en glödande rodnad rykte Margot sin syster


i armen, och, sedan Valérie stuckit korten på sig, gick hon med
högburet hufvud sin väg.

— Det var en tarflig butik, sade hon, då de kommo ut i det fria.


Karlen var ju riktigt ohöflig. Jag tror han var förargad, för att jag
begärde mera än han ämnade gifva. Vi skola försöka på något annat
ställe.

— Vet du, min lilla Valérie, jag tror att det är fruktlöst. De där
herrarna ha säkert sina bestämda leverantörer och vilja icke göra
affärer med några andra.

Valérie stannade och betraktade henne med en upprörd och


förargad min.

— Nu pratar du riktiga dumheter, sade hon. Om det förhölle sig


sålunda, så skulle ju ingen människa komma framåt. Alt måste ju ha
en början. Låtom oss gå till Regent- eller Oxford-Street och uppsöka
några riktigt fina butiker, där bli vi bättre bemötta än af dessa simpla
människor. Ser du, där kommer en "bus", vi skola stiga upp i den.

Margot tykte det var klokare att låta Valérie själf komma
underfund med huru fruktlösa hennes bemödanden voro än att
försöka afråda henne, ty hon viste af erfarenhet huru envis hon
kunde vara och hon viste, att vidare invändningar endast skulle reta
henne utan att ändå öfvertyga henne.
De påbörjade således en mödosam vandring, som slutade med ett
fullständigt nederlag för Valérie. Hvar och en hon bjöd ut sina
stackars kort åt skrattade ut henne eller blef förargad. På hemvägen
sade hon icke ett ord, men när de väl voro hemma bredde hon ut
sina tjugufyra kort på bordet och betraktade dem en lång stund
fundersamt. Slutligen ropade hon på Margot och bad henne likaledes
betrakta dem.

— Tycker du de äro mycket fula — mycket illa utförda? frågade


hon sakta. Hennes glänsande ögon voro med ett forskande uttryck
fästa på Margots ansikte. Men Margot teg och sökte förgäfves efter
ord, som icke skulle vara för sårande, för nedslående. Valérie fattade
henne i båda axlarna och höll henne fast: Du måste säga sanningen,
sade hon; du måste svära att säga mig sanningen! Bah! ditt ansikte
skulle förråda dig, om du också ville dölja hvad du tänker. Margot,
jag ser det på dina ögon. Du tycker, att de där herrarna ha rätt;
mina kort äro afskyvärda och ingen människa vill köpa dem.

— Nej, jag försäkrar dig, bedyrade Margot ifrigt, jag tycker visst
inte, att ditt arbete är dåligt. Men det är kanske icke precis sådant,
som människorna äro vana att köpa. De personer, som äro vana att
måla dylika kort, ha sitt eget sätt, du har måhända ännu icke riktigt
lärt dig metoden. Hvem vet, kanske de använda andra färger.

— Jag ser! Jag ser! utropade Valérie med darrande läppar. Jag har
gjort mig löjlig, då jag försökte någonting, jag inte kunde. Hvarför
skall jag också försöka göra någonting? Ingenting lyckas för mig.

Hon samlade med darrande händer ihop sina kort och skyndade
genom rummet, och, innan Margot hann förekomma det, hade hon
kastat dem allesamman i elden. Sedan sjönk hon ned i en länstol
och grät som om hennes hjärta velat brista.
— Jag har lust att också bränna upp min fiol! snyftade hon. Ack,
Margot, hvarför får jag inte dö! Jag försöker och jag hoppas, men
ingenting lyckas for mig!

— Min hjärtunge, svarade Margot, som kastat sig på knä bredvid


och dragit ned det lilla, lockiga, bruna hufvudet mot sin axel, vi få
inte i samma andetag tala om din konst, din stora talang och dessa
saker! De ha endast varit ett tidsfördrif för dig. Om du kunnat sälja
dem, hade du varit stolt och fägnat dig däråt; men betänk blott. Om
du också fått sälja alla dina kort lika fort som du målade dem, hade
de likväl aldrig kunnat bereda dig samma glädje och stolthet som din
musik.

— Ack, min musik! Tala inte om den! Du kallar den en glädje och
stolthet? Säg hällre mitt kval och min förtviflan. Jag tror denna
längtan att få låta höra mig och medvetandet, att ingen bryr sig om
det, ännu komma att taga lifvet af mig!

— Haf en smula tålamod, min älskling, bad Margot och torkade


hennes tårar, som så hastigt rullade utför kinderna. Du är ju ännu
blott aderton år. Var tålig och ihärdig. Framgången och ryktbarheten
komma nog i sinom tid. En gång skola vi båda skratta, då vi tänka
tillbaka på en dag sådan som denna.

Men Valérie suckade blott och Margot hade själf svårt att tro på
sina egna, om så mycken tillförsikt vittnande ord. Valérie smög sig
ännu flere dagar omkring som en liten fridlös ande och var så blek,
så nedslagen och apatisk, att Margot beslöt att till hvad pris som
hälst rycka henne upp ur detta tillstånd.

— Vet du, Valérie, sade hon en vacker dag till henne, jag har läst
en konsertannons af en alldeles ny pianist — Paul Waldeneck. Han
har åtminstone aldrig förut spelat i England. Han är ungrare, tror
jag, tycker du inte det vore intressant att få höra en landsman? Det
påstås, att han skall vara alldeles utmärkt. Skola vi ej gå dit?

— Nej, jag vill inte, svarade Valérie vid dåligt humör. Jag bryr mig
icke ens mera om att höra musik.

Margot sade ingenting vidare, men då de träffades vid bordet


räkte hon systern programmet till morgondagens konsert, hvilket
pryddes af konsertgifvarens porträtt. Detta visade ett ungdomligt
ansikte med fina, regelbundna drag och stora ögon. Håret var
tämligen långt och uppstruket ur pannan.

— Har han då hvitt hår? frågade Valérie, som med intresse


betraktade porträttet, eller ha de glömt att skugga bilden? Det är ett
präktigt hufvud, Margot, och ett vackert ansikte. Det är visst mycket
smickradt, men man ser ut som han hade gnistan inom sig. Kanske
vi ändå kunde gå och höra honom. Det vore ju helt annat, om han
spelade fiol, tillade hon suckande.

Margot och Valérie begåfvo sig således följande dag till S:t James
Hall och då de kommo närmare funno de gatan formligen blockerad
af åkdon.

— Det tyckes komma mycket folk för att höra honom, sade Valérie
fundersamt. Tänk, Margot, huru härligt det vore, om det vore jag
som spelade och denna människomassa väntade för att taga emot
mig!

Margot betraktade henne medlidsamt.


— Min älskling, var säker på, att människorna också en vacker dag
skola stå och vänta på dig. Jag är öfvertygad om, att Waldeneck ej
häller vid aderton års ålder spelade för en så stor åhörarekrets.

Hon sade likväl detta en smula modstulet, ty hon jämförde också


den lysande framgång, som ögonskenligen väntade denna artist,
med det nederlag, hennes syster lidit, och tillika med minnet af detta
nederlag vaknade äfven andra minnen, hvilka måhända icke voro så
bittra, men desto sorgligare. I och med detsamma yttrade Valérie
några ord, som berörde föremålet för hennes tankar.

— Då jag sist var här hade jag sir John med mig. Den stackars sir
John! Jag undrar just hvar han nu är! Vi höra aldrig mera af honom!

Som de i och med detsamma kommo fram till dörren behöfde


Margot icke svara, och då de en gång väl voro inne i salen, togo
Valéries tankar genast en annan riktning.

Salen var tätt fyld; en viss, andlös förväntan höll massan så


fången, att det var så godt som tyst, ända tils den store konstnären
uppenbarade sig, och då mottogs han af en stormande applåd.
Valérie satt rak som ett ljus, hennes ögon vidgades och läpparna
skildes.

— Tycker du om hans utseende? frågade Margot leende, men


Valérie höjde fingret varnande.

— Tst! han ämnar börja.

Men Waldeneck dröjde ännu ett ögonblick och bugade sig åt alla
sidor. Han var en lång, smärt man, som rörde sig med ett visst
nonchalant behag. Porträttet var, såsom Margot genast upptäkte,
icke smickradt och kunde naturligtvis icke återgifva den vackra,
elfenbenshvita hyn, som så egendomligt framhöll de mörka ögonen
och ögonbrynen; det fina, silkeslena håret var snöhvitt och stod i en
skarp motsats till den kraftfulla gestalten och det unga ansiktet.
Konstnärens hela utseende var så ovanligt, så pikant, att det genast
fängslade åskådaren. Han såg ut som han stigit ut ur en gammal
tafla; hufvudet och ansiktsuttrycket, ja, till och med formen på
händerna voro sådana, att en konstnär från adertonde århundradet
gärna hade målat dem. Då han vände sig om och gick fram till
pianot, kastade Margot ofrivilligt en blick på honom för att se, om
inte hans vackra, hvita hår i nacken var prydt med en stångpiska.
Ögonblicket därpå bröto de första tonerna den dödstystnad, som
följt på de entusiastiska applåderna, och hela den stora
åhörarekretsen lyssnade som en enda, hänförd varelse.

Margot var i en sådan extas, att hon till och med glömde Valérie,
och hon förblef i detta rus, ända tils de underbara fingrarna sjönko
ned från tangenterna och konstnären gjorde en paus. Då såg hon på
sin syster.

— Valérie, hviskade hon, har du någonsin hört någonting så


skönt? Har du haft en aning om, att pianot haft dylika toner? Ah,
han är en stor man, en mästare!

Valérie vinkade åt henne med handen.

— Tala inte med mig, hviskade hon. Du stör mig. Ack, de dumma
människorna! — hvarför sluta de icke med sina applåder, så att han
kan få fortsätta.

Hon yttrade icke ett ord vidare under de två timmar, som nu
följde. Hon tyktes endast vakna, då det applåderades och ropades
da capo; då klappade hon så lidelsefullt i sina små händer och
stampade så fanatiskt i golfvet, att hon blef alldeles utom sig! Den
store artisten hade tydligen förnimmelse om, att han stod i kontakt
med sina åhörare, ty ett så varmt, entusiastiskt bifall kom sällan de i
London uppträdande konstnärerna till del. Åhörarnas entusiasm fann
beredvilligt gensvar hos artisten. Han spelade och spelade åter,
fastän han till slut var så trött, att han nästan tumlade. Då han reste
sig för att tacka för det stormande bifall, som följt på det tredje
upprepandet af programmets sista nummer — en fin och förtrollande
nocturne af hans egen komposition, stängdes pianot på
impressarions befallning, ty denne fruktade, att de omättliga
åhörarna öfverhöfvan skulle taga sin afguds krafter i anspråk. Han
stod alt ännu leende och bugande kvar, då publiken plötsligt trängde
sig fram till honom. Herrarna klättrade upp på estraden för att trycka
hans händer, vackra kvinnor med glödande kinder, på hvilka tårarna
alt ännu glittrade, lutade sig framåt och mumlade fram ord af
hänförelse och beundran. Han hade ännu aldrig upplefvat någonting
dylikt här.

Margot hade icke trott, att en dylik entusiasm vore möjlig i det
kalla, känslolösa England. Hon kastade en blick på Valérie och såg till
sin förfäran, huru blek hon var. Hennes ansikte hade ett sällsamt
uttryck; hon såg nästan ut som om hon varit nära att falla i vanmakt.

— Kom härifrån, min älskling, kom. Jag borde icke ha fört dig hit;
det är för mycket för dig. Min stackars, lilla älskling, jag borde ha
tänkt på, att anblicken af denne mans oerhörda framgång skulle
påminna dig om —

— Ack nej, afbröt Valérie henne. Nej, det är icke detta, du förstår
det icke. Nej, för mig inte härifrån ännu — icke så länge han är här.
Men ögonblicket därpå var Waldeneck försvunnen och publiken
började skingra sig. Margot förde bort Valérie, hvilken darrade så, att
Margot, då de kommo ut på gatan, ansåg det för klokast att taga en
vagn och fara raka vägen hem i stället för att vänta på omnibusen,
deras vanliga befordringsmedel.

Då vagnsdörren stängts efter dem och de voro på väg, vände


Valérie sig plötsligt till sin syster.

— Ack, Margot! utropade hon, en sådan olycka! Ser du icke hvad


som händt? Jag har mött mitt öde! Jag älskar Waldeneck och han
kommer aldrig att älska mig!
XV.

Apassionata subito.

Af alla de sorger, som fallit på Margots lott, var denna måhända


den allvarligaste. Till en början hade hon försökt betrakta hela saken
som en nyck, en öfvergående inbillning, det icke var värdt att fästa
så mycket afseende vid; men Valérie var så allvarlig, så ofantligt
öfvertygad om djupet af sin passion för Waldeneck, att Margots hela
visdom kom till korta och hon viste hvad hon skulle taga sig till.

— Jag har ju alltid sagt dig, förklarade Valérie med en allvarsam


och förtviflad min, att jag aldrig kunde älska någon, om hvilken jag
ej viste, att han var min herre och mästare — någon, som stod öfver
mig. I samma ögonblick jag såg denne man erfor jag hans snilles
makt; och då jag hörde honom spela — ack! Margot, Margot, hvad
skall jag göra? Jag känner, att man är den enda man jag någonsin
kan älska, och du vet, huru hopplös denna min kärlek är. Jag får
aldrig lära känna honom — fordom hade jag väl kunnat drömma om,
att jag också skulle bli ryktbar — att han åtminstone skulle få höra
mitt namn — att vi en dag kunde mötas som jämlikar. — Men hvad
får jag? En stackars, okänd flicka, som icke vet hvad hon skall taga
sig till med sitt lif — som kommer att lefva och dö obekant.

Margot försökte först att med lätt gäckeri väcka sin syster till insikt
om det dåraktiga i denna nya idé; sedan blef hon allvarsam.

— Valérie, du är ju inte eljes så okvinnlig. Det är orätt, att du


tillåter dig att på detta sätt tänka på en man, som du blott en gång
sett och aldrig talat med. Huru kan du veta, hurudan han i själfva
värket är? Han kan vara mycket dålig; många af dessa stora
konstnärer föra ett lättsinnigt lif. Han är kanske i alla afseenden
ovärdig, att du egnar honom en tanke.

— Bah! Ovärdig! upprepade Valérie förtretad. Hvar har du dina


ögon, Margot! — Sedan tillade hon utan minsta konsekvens: — Dålig
eller icke dålig, så är han mitt öde! Jag älskar honom och kommer
aldrig att älska någon annan.

— Tyst, barn — tyst! Jag kan inte höra på dig. Hvad kommer det
åt dig — du, som alltid varit så fin och förnäm i dina åsikter? Jag
tycker det är förskräckligt att yppa dylika känslor — då det absolut
icke finnes någon anledning därtill. Jag för min del förstår icke, huru
en kvinna kan älska, då hon ej först blir älskad, eller åtminstone,
förbättrade hon sig hastigt, medan hennes ansikte färgades af en
glödande rodnad, huru en flicka, om en dylik olycka händer henne,
helt lugnt kan tala därom. Jag skulle icke ens kunna tillstå det för
mig själf.

— Du är du och jag är jag, svarade Valérie förtrytsamt. Jag skall


icke mera säga ett ord därom, eftersom denna tanke är så plågsam
för dig; jag skall behålla den för mig själf, men den kommer alltid,
alltid att vara där. Det var grymt af dig att säga, att det är okvinnligt,
jag kan inte förändra min natur. Solrosen kan inte låta bli att vända
sig efter solen. Han är min sol och mitt hjärta, och mina tankar skola
följa honom hvart han än tager vägen.

Margot suckade och vred händerna:

— Valérie, Valérie, du vet ju, att jag vill ha ditt fulla förtroende;
om denna känsla finnes inom dig, så måste du tala med mig därom,
men, min älskling, försök att vara förnuftig. Saken är ju alldeles
omöjlig, försök därför att bekämpa den och förjaga den ur dina
tankar. Tänk om du finge höra, att Waldeneck är gift?

— Det är han icke, afbröt Valérie henne vildt.

— Men om han vore det? Då vore det ju din skyldighet att förjaga
hvarje tanke på honom ur ditt hjärta.

— Om han vore det — om han vore det! Han är det inte, säger jag
och hvad skulle det väl göra, om han också vore det. Han kommer
aldrig att få veta det och jag är icke ansvarig för mina tankar. Ack,
hvad du är förfärad! Jag skall icke mera tala med dig därom; jag
skall endast anförtro det åt min fiol. Ack, min cremonesare! — min
trogne vän, du skall åtminstone förstå mig och ha medlidande med
mig.

Hon rusade med glödande kinder ut ur rummet och kom strax


därpå tillbaka med sin fiol; sedan började hon spela. Så upprörd och
orolig Margot än var, genombäfvades hon likväl af ofrivillig beundran,
då hon lyssnade till hennes spel. Hon gick igenom den ena efter den
andra af numrorna på Waldenecka program. Då hon kom till hans
egna kompositioner, inlade hon en sådan trånande lidelse i
återgifvandet däraf, att tårarna stego upp i ögonen på Margot.
— Ack, Valérie du är en stor konstnärinna! Du är ett snille! Hvarför
kan världen icke få höra dig? Om du kunde intaga den plats, som
tillkommer dig, skulle dessa dåraktiga tankar drifvas på flykten.

— Hör! Hör! utropade Valérie med ansiktet strålande och i högsta


spänning, hör du, var det icke så här? Ack, hvad det är härligt! Hans
fingrar voro underbara, men min cremonesare kan säga ännu mera
än något piano. Lyssna! Hör du ej, huru hans själ ropar efter
någonting, som icke är den förunnadt? Margot, han saknar också
någonting. Huru stor han än är, så är hans lif icke ännu fullständigt;
han behöfver ännu någonting — han behöfver mig.

— Valérie, du blir galen! snyftade Margot.

— Nej, det är sant: min fiol har sagt mig det; du kan själf höra
det. Är hans musik inte ännu härligare, då jag spelar den? Ack, om
vi kunde spela tillsamman! Margot, Margot, om vi kunde spela
tillsamman — om vi alltid kunde vara tillsamman! Ser du ej, huru
min konst skulle förfullkomna hans. Mitt lif skulle göra hans
fullkomligt; min kärlek skulle fylla den tomhet i hans hjärta, som
hans musik klagar öfver. Ack, Margot, Margot, hvarför kunna vi ej nå
hvarandra?

Handen med stråken uti sjönk ned och hufvudet sänktes mot
bröstet. Margots förbittring hade försvunnit, hon var förfärligt orolig.
Gaf Valéries exalterade hjärna, hennes öfverspända, nervösa
organisation efter för denna häftiga sinnesrörelse, som nu följde på
den långvariga spänningen och de svikna förhoppningarna? Hvad
skulle hon göra? Huru skulle hon gå tillväga för att afvärja den
hotande faran.
Efter mycket öfvertalande förmådde hon slutligen Valérie att
lämna fiolen ifrån sig och att lägga sig. Men medan hon gick af och
an i rummet, vattnade blommorna och sysslade med allehanda, som
hon trodde skulle förströ Valérie, kände hon mycket väl, att systerns
stora glödande ögon endast med en frånvarande blick följde henne
och att hennes tankar voro på helt annat håll.

I dagningen morgonen därpå vaknade Margot alldeles förskräkt,


Valéries säng var tom. Hon flög upp och rusade till dörren. Då hon
öppnade den, trängde de svaga tonerna af en fiol upp till henne från
rummen på nedra botten. Hon skyndade ned i det lilla förmaket,
som såg riktigt spöklikt ut i den grå dagern, och där fann hon
Valérie, en eterisk, hvitklädd gestalt, som spelade Waldenecks
nocturne. Hon öfvertalade systern kärleksfullt att återvända till
sängen, och fastän den frysande, lilla gestalten snart åter blef varm
och försjönk i en lugn sömn, låg Margot likväl vaken och kastade sig
oroligt på sitt läger, tils dagen inbröt och plikten åter kallade henne.

Men alt efter som tiden gick ökades Margots oro snarare än den
minskades. Valérie var visserligen icke så upprörd som i början, men
det led intet tvifvel, att hon icke helt och hållet var fången under
denna passion. Hon köpte icke allenast de stycken Waldeneck spelat
på konserten, utan alla hans kompositioner. Det var blott högst få af
dem, som voro skrifna för fiol, men hon satte dem för detta
instrument i det hon tog hans temata och omspann dem med de
underbaraste fantasier. — Margot tykte, att hon aldrig förut till fullo
uppskattat den lilla varelsens beundransvärda talang, men hon
lyssnade i alla fall med värklig hjärteångest på den sällsamma,
sorgliga musiken, som hela dagen ljöd i huset. Det föreföll henne
som hon genom den hörde sin systers hjärta klaga och längta efter
någonting, som aldrig skulle komma henne till del.
Veckorna förflöto sålunda, mars kom och gick och april kom och
gick full af spänning och hopp till och med i det dimhöljda London.
Täcka vårblommor blomstrade i skogarna och trädgårdarna, små,
krusiga, ljusgröna blad tittade ut ur knopparnas bruna höljen och
himmelen hvälfde sig blå öfver stadens rök-atmosfär; och en vacker
dag lade Valérie sig till sängs.

Hon svimmade, då hon skulle stiga upp på morgonen, och nu låg


hon med det lilla ansiktet nästan lika blekt som kudden i sin säng
och alt lif tyktes helt och hållet vara koncentreradt i de feberaktigt
glänsande ögonen.

Margot var alldeles utom sig, hon trodde, att Valérie skulle dö;
Valérie hyste själf samma åsikt och förkunnade detta faktum med
orubblig säkerhet.

— Jag har ingenting, jag önskade lefva för, sade hon. Jag skulle
gärna dö, om inte du funnes, Margot.

Men då läkaren kom, slog han bort hvarje tanke därpå. Det var
bara nervös utmattning, den unga damen hade måhända arbetat för
flitigt, hon hade synbarligen öfverskattat sina krafter. Eller hade hon
haft någon sinnesrörelse? Hon behöfde fullkomligt lugn, fullkomlig
hvila.

— Mycket mjölk, frisk luft och luftombyte skulle göra henne godt.
Hon skulle snart bli frisk, om det vore möjligt att få henne härifrån.
Känner fröken Kostolitz till Wiesbaden? Denna ort skulle jag
rekommendera. Det är en utmärkt ort för nervösa personer och inte
— med en hastig blick omkring rummet — inte för dyr. Vore det
möjligt att föra fröken Kostolitz till Wiesbaden?
— Alt hvad som är nödvändigt för min systers hälsa måste bli
möjligt, svarade Margot.

— Nå, far då redan nästa vecka till Wiesbaden, om ni kan. Vi ha


nu början af maj — stanna, om möjligt, hela sommaren där, och då
ni kommer hem med henne är hon fullkomligt frisk. Wiesbaden är
härligt vid denna tid på året. Hyr er rum i ett hus, som ligger högt
och är omgifvet af träd, låt henne dricka så mycket mjölk hon kan
och vara mycket ute i friska luften.

Han aflägsnade sig högst belåten med det program han uppgjort
och utan någon aning om, huru svårt det var att utföra det. Då
dörren stängts efter honom rörde Valérie otåligt på sig i sängen.

— Jag vill inte fara till Wiesbaden, sade hon, det är bestämdt ett
mycket tråkigt ställe. Jag vill mycket hällre dö och komma till
himmelen.

— Men jag kan inte undvara dig, sade Margot samt lutade sig ned
och kyste henne, och du är icke häller mogen för himmelen. Smickra
dig inte därmed! Du är alt för stygg och elak! Petrus skulle alt slå
igen porten för dig.

Margot var så lycksalig öfver läkarens försäkran, att Valéries


sjukdom ej var farlig, att hon var färdig att skratta åt allting. Hon var
icke ens orolig vid tanken på, huru hon skulle skaffa medel till resan
och den långvariga vistelsen på en främmande ort.

— Ja, det är godt och väl, sade Valérie, men huru skola vi komma
dit och hvad skola vi lefva af, då vi en gång äro där.
— Oroa dig inte för den skull, svarade Margot, det blir nog någon
utväg, bara vi väl äro där.

Men då hon sedan blef ensam funderade hon närmare på saken.


Hon måste naturligtvis lämna sina lektioner i London med fara att
förlora sina elever och vid sin återkomst stå utan alla medel till sitt
uppehälle. Nåväl, hon måste riskera detta; hon hade redan en gång
gjort en början, i värsta fall måste hon börja om igen och lita på sin
tur. De medel, som stodo henne till buds, voro ytterst ringa, ifall hon
ej tillgrep de pengar, hon hade på banken. Men dem hade hon ända
sedan den olyckliga konserten ansett för John Crofts rättmätiga
tillhörighet. Den summa biljettförsäljningen inbringat hade räkt till
att betäcka kostnaderna med; men Margot hade alltid ansett dessa
pengar för sir Johns tillhörighet.

Hon ämnade återställa dem åt honom en dag, då minnet af det


som passerat dem emellan hunnit blekna en smula. Men nu i denna
nöd kom hon att tänka, att pengarna tillhörde henne och att hon
kunde använda dem såsom hon fann för godt. Sir John hade endast
uttänkt sin fantastiska plan och satt den i värkställighet för att hjälpa
dem. Och huru sårad skulle han icke bli, om han viste, att Margot,
blott för att han hade ett indirekt anspråk på dessa pengar, icke
begagnade sig af dem, ehuru hon så nödvändigt behöfde dem. Det
låg ju ingenting ohederligt eller oädelt i detta handlingssätt. Ty om
hon velat hade hon ju kunnat vara härskarinna öfver alt det, som
tillhörde honom. Om han varit en smula försiktigare i utförandet af
sin plan, hade hon ju aldrig fått veta, att han var den enda köparen
till ifrågavarande biljetter. Han hade menat så väl, han hade varit så
ädelmodig; hvarför kunde hon icke likaledes vara ädelmodig?
— Jag skall göra det, sade Margot med glödande kinder. Ack, min
vän! Du är vänlig och god, men jag använder icke gärna de
penningar, som tillhöra dig. Men jag skall likväl besegra min stolthet
och göra det.

Hon påbörjade genast ett bref till sir John. Hon kände, att hon
icke kunde taga detta steg utan att underrätta honom därom, ty hon
bröt därigenom ett beslut, som hon meddelat honom.

"Min bäste sir John," skref hon, "ni minnes väl, att jag, då
vi skildes, sade er, att jag skulle betala tillbaka de pengar, ni
gifvit ut för biljetterna. Det enda skäl hvarför jag icke genast
gjorde det var, att jag fruktade ni skull anse mig för ovänlig
och småaktig samt känna er sårad. Men jag hade städse för
afsikt att göra det och ville blott uppskjuta det, tils ni — huru
skall jag säga — hade glömt mig eller utan smärta kunde
tänka på den episod i ert lif, där jag spelade en roll. Jag
känner er så väl, min käre vän, att jag knappast kan tro, att
det nu redan vore fallet — men jag hoppas och ber innerligt,
att det snart måtte ske; och jag är också fullkomligt
öfvertygad om, att ni snart kommer underfund med, att det
icke var någonting så synnerligt med mig och att det blott var
er hjärtegodhet, som låg till grund för er goda tanke om mig.
Men nu måste jag underrätta er om, att jag gärna ville
använda de pengar, jag är skyldig er. Valérie är sjuk och
måste resa till utlandet. Som ni vet, kostar det alt en hop
pengar och därför vill jag taga emot er hjälp. Jag vet, att ni ej
missförstår mina bevekelsegrunder och att ni icke häller
föraktar mig på grund af detta mitt förändrade beslut. Ni
känner mig tillräckligt för att veta, att jag ej gör det gärna;
men det måste ske för Valéries skull och jag anser äfven för
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebooknice.com

You might also like