Viewing the Quiz Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Saving a File to the File System . . . . . . . . . . . . . . . . . . . . . . 185 Introducing the saveSonnet.php Program . . . . . . . . . . . 185 Opening a File with fopen() . . . . . . . . . . . . . . . . . . . . . . . 187 Creating a File Handle. . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Examining File Access Modifiers. . . . . . . . . . . . . . . . . . . 188 Writing to a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Closing a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Loading a File from the Drive System . . . . . . . . . . . . . . . . . 189 Introducing the loadSonnet.php Program . . . . . . . . . . . 189 Beautifying Output with CSS . . . . . . . . . . . . . . . . . . . . . 191 Using the “r” Access Modifier. . . . . . . . . . . . . . . . . . . . . 191 Checking for the End of the File with feof() . . . . . . . . . . 191 Reading Data from the File with fgets() . . . . . . . . . . . . . 192 Reading a File into an Array . . . . . . . . . . . . . . . . . . . . . . . . . 192 Introducing the cartoonifier.php Program . . . . . . . . . . . 192 Loading the File into an Array with file() . . . . . . . . . . . . 193 Using str_replace() to Modify File Contents . . . . . . . . . . 194 Working with Directory Information . . . . . . . . . . . . . . . . . . . 194 Introducing the imageIndex.php Program . . . . . . . . . . . 194 Creating a Directory Handle with openDir() . . . . . . . . . . 196 Getting a List of Files with readdir() . . . . . . . . . . . . . . . . 196 Selecting Particular Files with preg_grep(). . . . . . . . . . . 197 Using Basic Regular Expressions . . . . . . . . . . . . . . . . . . 197 Storing the Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Working with Formatted Text . . . . . . . . . . . . . . . . . . . . . . . . 200 Introducing the mailMerge.php Program . . . . . . . . . . . . 200 Determining a Data Format . . . . . . . . . . . . . . . . . . . . . . . 201 Examining the mailMerge.php Code. . . . . . . . . . . . . . . . 201 Loading Data with the file() Command. . . . . . . . . . . . . . 202 Splitting a Line into an Array and to Scalar Values. . . . 203 Creating the QuizMachine.php Program . . . . . . . . . . . . . . . 203 Building the QuizMachine.php Control Page . . . . . . . . . 204 Editing a Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Writing the Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 Taking a Quiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Grading the Quiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Viewing the Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 xv C o n ten t s Chapter 7: Writing Programs with Objects . . . . .229 Introducing the SuperHTML Object . . . . . . . . . . . . . . . . . . . 230 Building a Simple Document with SuperHTML . . . . . . . 230 Working with the Title Property . . . . . . . . . . . . . . . . . . . . 233 Adding Text and Tags with SuperHTML . . . . . . . . . . . . . 235 Creating Lists the SuperHTML Way . . . . . . . . . . . . . . . . 237 Making Tables with SuperHTML . . . . . . . . . . . . . . . . . . . 239 Creating Super Forms. . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Understanding OOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Objects Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Creating a Basic Object. . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Adding Methods to a Class . . . . . . . . . . . . . . . . . . . . . . . 253 Inheriting from a Parent Class . . . . . . . . . . . . . . . . . . . . . 257 Building the SuperHTML Class . . . . . . . . . . . . . . . . . . . . . . . 260 Setting Up the File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Creating the Constructor . . . . . . . . . . . . . . . . . . . . . . . . . 261 Manipulating Properties . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Adding Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Building the Top of the Page . . . . . . . . . . . . . . . . . . . . . . 262 Creating the Bottom of the Page . . . . . . . . . . . . . . . . . . . 263 Adding Headers and Generic Tags . . . . . . . . . . . . . . . . . 263 Creating Lists from Arrays . . . . . . . . . . . . . . . . . . . . . . . . 264 Creating Tables from 2-Dimension Arrays . . . . . . . . . . . 265 Creating Tables One Row at a Time . . . . . . . . . . . . . . . . 266 Building Basic Form Objects . . . . . . . . . . . . . . . . . . . . . . 267 Building Select Objects. . . . . . . . . . . . . . . . . . . . . . . . . . . 268 Responding to Form Input . . . . . . . . . . . . . . . . . . . . . . . . 268 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Chapter 8: XML and Content Management Systems . . . . . . . . . . . .271 Introducing XCMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 Understanding Content Management Systems . . . . . . . . . 273 Working with PHP-Nuke . . . . . . . . . . . . . . . . . . . . . . . . . . 274 Installing PHP-Nuke. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Customizing PHP-Nuke. . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Introducing simpleCMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Viewing Pages from a User’s Perspective . . . . . . . . . . . 279 Examining the PHP Code . . . . . . . . . . . . . . . . . . . . . . . . . 280 Viewing the CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 xvi C o n ten t s Inspecting the Menu System . . . . . . . . . . . . . . . . . . . . . . 283 Improving the CMS with XML. . . . . . . . . . . . . . . . . . . . . . . . 285 Introducing XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Examining main.xml. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 Simplifying the Menu Pages . . . . . . . . . . . . . . . . . . . . . . 288 Introducing XML Parsers . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 Working with Simple XML . . . . . . . . . . . . . . . . . . . . . . . . 289 Working with the simpleXML API . . . . . . . . . . . . . . . . . . 289 Manipulating More-Complex XML with the simpleXML API. . . . . . . . . . . . . . . . . . . . . . . . 293 Returning to XCMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Extracting Data from the XML File . . . . . . . . . . . . . . . . . 297 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Chapter 9: Using MySQL to Create Databases . .299 Introducing the Adventure Generator Program . . . . . . . . . 300 Using a Database Management System . . . . . . . . . . . . . . . 302 Working with MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Installing MySQL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Using the MySQL Executable . . . . . . . . . . . . . . . . . . . . . 304 Creating a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 Creating a Table. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Inserting Values. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 Selecting Results. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 Writing a Script to Build a Table . . . . . . . . . . . . . . . . . . . . . . 313 Creating Comments in SQL . . . . . . . . . . . . . . . . . . . . . . . 314 Dropping a Table. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Running a Script with SOURCE . . . . . . . . . . . . . . . . . . . . 314 Working with a Database via phpMyAdmin . . . . . . . . . . . . 315 Connecting to a Server. . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Creating and Modifying a Table. . . . . . . . . . . . . . . . . . . . 317 Editing Table Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Exporting a Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Creating More-Powerful Queries . . . . . . . . . . . . . . . . . . . . . 322 Limiting Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 Limiting Rows with the WHERE Clause . . . . . . . . . . . . . 325 Changing Data with the UPDATE Statement . . . . . . . . . 327 Returning to the Adventure Game . . . . . . . . . . . . . . . . . . . . 328 Designing the Data Structure. . . . . . . . . . . . . . . . . . . . . . 328 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 xvii C o n ten t s Chapter 10: Connecting to Databases within PHP . . . . . . . . . . . . . . . . . . . . . .335 Connecting to the Hero Database . . . . . . . . . . . . . . . . . . . . . 336 Getting a Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 Choosing a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Creating a Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Getting Field Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 Parsing the Result Set. . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 Returning to the Adventure Game Program . . . . . . . . . . . . 342 Connecting to the Adventure Database . . . . . . . . . . . . . 342 Displaying One Segment . . . . . . . . . . . . . . . . . . . . . . . . . 343 Viewing and Selecting Records . . . . . . . . . . . . . . . . . . . . 348 Editing the Record. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 Committing Changes to the Database . . . . . . . . . . . . . . 355 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 Chapter 11: Data Normalization . . . . . . . . . . . . . . .359 Introducing the spy Database . . . . . . . . . . . . . . . . . . . . . . . . 360 The badSpy Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 Inconsistent Data Problems . . . . . . . . . . . . . . . . . . . . . . . 361 Problem with the Operation Information . . . . . . . . . . . . 362 Problems with Listed Fields . . . . . . . . . . . . . . . . . . . . . . . 362 Designing a Better Data Structure . . . . . . . . . . . . . . . . . . . . 363 Defining Rules for a Good Data Design . . . . . . . . . . . . . 363 Normalizing Your Data . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Defining Relationship Types . . . . . . . . . . . . . . . . . . . . . . 366 Building Your Data Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 Setting Up the System . . . . . . . . . . . . . . . . . . . . . . . . . . . 368 Creating the agent Table . . . . . . . . . . . . . . . . . . . . . . . . . 369 Building the operation Table . . . . . . . . . . . . . . . . . . . . . . 371 Using a Join to Connect Tables . . . . . . . . . . . . . . . . . . . . 373 Creating Useful Joins . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 Examining a Join without a WHERE Clause. . . . . . . . . . 374 Adding a WHERE Clause to Make a Proper Join . . . . . . 374 Adding a Condition to a Joined Query . . . . . . . . . . . . . . 375 Building a Link Table for Many-to-Many Relationships . . . 376 Enhancing the ER Diagram . . . . . . . . . . . . . . . . . . . . . . . 376 Creating the specialty Table . . . . . . . . . . . . . . . . . . . . . . . 377 xviii C o n ten t s Interpreting the agent_specialty Table with a Query . . . 378 Creating Queries That Use Link Tables . . . . . . . . . . . . . . 379 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Chapter 12: Building a Three-Tiered Data Application . . . . . . . . . . . . . . . . . 383 Introducing the SpyMaster Program . . . . . . . . . . . . . . . . . . 384 Viewing the Main Screen . . . . . . . . . . . . . . . . . . . . . . . . . 384 Viewing the Results of a Query . . . . . . . . . . . . . . . . . . . . 384 Viewing Table Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 Editing a Record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 Confirming the Record Update . . . . . . . . . . . . . . . . . . . . 387 Deleting a Record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 Adding a Record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 Processing the Add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 Building the Design of the SpyMaster System . . . . . . . . . . 389 Creating a State Diagram . . . . . . . . . . . . . . . . . . . . . . . . . 390 Designing the System. . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 Building a Library of Functions . . . . . . . . . . . . . . . . . . . . 392 Writing the Non-Library Code . . . . . . . . . . . . . . . . . . . . . . . . 393 Preparing the Database . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Examining the spyMaster.php Program . . . . . . . . . . . . . 394 Building the viewQuery.php Program. . . . . . . . . . . . . . . 399 Viewing the editTable.php Program . . . . . . . . . . . . . . . . 401 Viewing the editRecord.php Program . . . . . . . . . . . . . . . 402 Viewing the updateRecord.php Program . . . . . . . . . . . . 402 Viewing the deleteRecord.php Program . . . . . . . . . . . . . 404 Viewing the addRecord.php Program . . . . . . . . . . . . . . . 404 Viewing the processAdd.php Program . . . . . . . . . . . . . . 405 Creating the spyLib Library Module . . . . . . . . . . . . . . . . . . . 406 Setting a CSS Style. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 Setting Systemwide Variables . . . . . . . . . . . . . . . . . . . . . 407 Connecting to the Database . . . . . . . . . . . . . . . . . . . . . . . 408 Creating a Quick List from a Query . . . . . . . . . . . . . . . . . 408 Building an HTML Table from a Query . . . . . . . . . . . . . . 409 Building an HTML Table for Editing an SQL Table. . . . . 410 Creating a Generic Form to Edit a Record . . . . . . . . . . . 413 Building a Smarter Edit Form . . . . . . . . . . . . . . . . . . . . . 415 Determining the Field Type . . . . . . . . . . . . . . . . . . . . . . . 418 xix C o n ten t s . 273 Working with PHP- Nuke . . . . . . . . . . . . . . . . . . . . . . . . . . 274 Installing PHP- Nuke. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Customizing PHP- Nuke. . . . 394 Examining the spyMaster .php Program . . . . . . . . . . . . . 394 Building the viewQuery .php Program. . . . . . . . . . . . . . . 399 Viewing the editTable .php Program . . . . . . . . 401 Viewing the editRecord .php Program . . . . . . . . . . . . . . . 402 Viewing the updateRecord .php Program . . . . . . . . . . . . 402 Viewing the deleteRecord .php Program . . . . . . . .