Using PEAR, you can save yourself a considerable amount of work, but if you still prefer not to use it, at least you will now recognize PEAR packages when you see them used in other programs and will know how to work with them. Adding Other PEAR Packages With PEAR properly installed on your system, you are able to install additional pack- ages from the command line by using one of the commands in Table E-2, where package is the name of a PEAR package, as listed at the web page http://pear.php.net/ packages.php. Table E-2. Installing PEAR packages on different systems System Command Windows "C:\Program Files\EasyPHP 3.0\php\pear" install package Mac OS X /Applications/MAMP/bin/pear install package Linux Unix pear install package To determine which packages are installed, replace install package in Table E-2 with the word list and the output should be similar to the following: INSTALLED PACKAGES, CHANNEL PEAR.PHP.NET: ========================================= PACKAGE VERSION STATE Archive_Tar 1.3.2 stable Console_Getopt 1.2.3 stable MDB2 2.4.1 stable MDB2_Driver_mysql 1.4.1 stable PEAR 1.7.2 stable Structures_Graph 1.0.2 stable Unit Testing with PHPUnit Now that you are familiar with object-oriented programming, it’s a good idea to get a taste of unit testing. This is a method of code testing that verifies whether individual units of source code are working correctly. Unit testing provides the following benefits: • It allows for automation of the testing process. • It reduces the difficulty of discovering errors within more complex code. • Testing is often enhanced because attention is given to each unit. Install PHPUnit with the PEAR installer. To do this, go to a Command or Terminal prompt, ensure that you have Administrator or Superuser privileges, and issue the two Unit Testing with PHPUnit | 481 lines of code in Table E-3, according to your operating system. (On Windows systems, ignore and close any pop-up “Invalid configuration directive” alerts that may appear.) Table E-3. Commands for Installing PHPUnit on different systems System Instructions to type from an Administrator Command prompt or a Terminal window XP/Vista (4 instructions) cd \Program Files\EasyPHP 3.0\php pear channel-discover pear.phpunit.de pear install phpunit/PHPUnit Xcopy /E pear\*.* includes Mac OS X (3 instructions) cd /Applications/MAMP/bin pear channel-discover pear.phpunit.de pear install phpunit/PHPUnit Linux/Unix (2 instructions) pear channel-discover pear.phpunit.de pear install phpunit/PHPUnit The two main commands register the PEAR channel on your system, download PHPUnit, and install it. On Windows, you need the additional XCOPY command to resolve a file and path bug in EasyPHP 3.0. Press the A key if prompted to “Overwrite (Yes/No/All)?”. You are then ready to take on some powerful bug testing. But first, let’s look at how you might perform testing without PHPUnit. So, for example, consider the case of testing PHP’s in-built array and the function sizeof and its alias count. For a newly created array, sizeof should return a value of 0 and then increase by 1 for every new element added, as in Example E-2. Example E-2. Testing array and sizeof $names = array(); echo sizeof($names) . "<br />"; $names[] = 'Bob'; echo count($names) . "<br />"; // count is an alias of sizeof As you would expect, the output from this code is: 0 1 In Example E-3, this code is expanded to support automatic interpretation by writing the comparison of the expected and actual values, outputting “OK” if the value is cor- rect and “Not OK” if it isn’t. 482 | Appendix E: Using PEAR and PHPUnit Example E-3. Modified Example E-2 to output OK/Not OK $names = array(); echo sizeof($names) == 0 ? "OK<br />" : "Not OK<br />"; $names[] = 'Bob'; echo sizeof($names) == 1 ? "OK<br />" : "Not OK<br />"; Helpful as this code is, there’s an even better way to handle errors, which is to display a message only when a value is incorrect. Example E-4 uses function assertTrue to do this by throwing an exception. Example E-4. Modified Example E-2 to throw an exception $names = array(); assertTrue(sizeof($names) == 0); $names[] = 'Bob'; assertTrue(sizeof($names) == 1); function assertTrue($condition) { if (!$condition) throw new Exception('Assertion failed.'); } Now we’ve arrived at a fully automated test, let’s look at how we would rewrite it using PHPUnit (see Example E-5). Example E-5. PHPUnit testing in action require_once 'PHPUnit/Framework.php'; class ArrayTest extends PHPUnit_Framework_TestCase { public function testNewArrayIsEmpty() { $names = array(); $this->assertEquals(0, sizeof($names)); } public function testArrayContainsAnElement() { $names = array(); $names[] = 'Bob'; $this->assertEquals(1, sizeof($names)); } } $testObject = new ArrayTest; $testObject->testNewArrayIsEmpty(); $testObject->testArrayContainsAnElement(); Unit Testing with PHPUnit | 483 The first thing to notice is that PHPUnit/Framework.php has been included in order to make the PHPUnit classes available to the program. After that, the program defines a new class that extends the PHPUnit_Framework_TestCase class. This new class contains two methods: one for testing a newly created array and another for testing an array containing an element. The rules for writing PHPUnit tests are: • The tests for a class called Class go into a class with the name ClassTest. • ClassTest usually inherits from PHPUnit_Framework_TestCase. • The tests are public methods that are named testSomethingDescriptive. • Inside the test methods, assertion methods such as assertEquals are used to assert that an actual value matches an expected value. And there you have it. The three lines of code at the end of Example E-5 create a new test object called $testObject and then call each of the object’s methods in turn. All being well, this program will display nothing, so to see the output from PHPUnit, try changing the 0 or 1 parameters in the assertEquals calls to other values. A comprehensive and easy-to-follow manual on PHPUnit is available at http://www .phpunit.de. Click “Read the documentation” to view it in either HTML or PDF format. 484 | Appendix E: Using PEAR and PHPUnit Index Symbols ! (exclamation mark) != (not equal) operator, 43, 65, 68, 309, 321 !== (not identical) operator, 65, 68, 309, 321 logical not operator, 44, 309, 321, 324 precedence in PHP, 65 NOT operator, 69 " " (quotation marks, double) escaping in JavaScript strings, 310 in multiline PHP strings, 47 in MySQL search strings, 189 in PHP strings, 38, 46 in JavaScript strings, 306 $ (dollar sign) $ function in JavaScript, 316 end-of-line matching in regular expressions, 366, 367 preceding PHP variable names, 37 omitting when using -> operator, 105 % (percent sign) %= (modulus assignment) operator, 43, 65, 308, 321 modulus operator, 42, 65, 308, 321 & (ampersand) && (logical and) operator, 44, 309, 321, 324 precedence of, 321 && (logical and) operator/precedence in PHP, 65 &= (bitwise and assignment) operator, 65, 321 bitwise and operator, 65 variables passed by reference, 94 ' ' (quotation marks, single) enclosing PHP array items, 40 escaping in JavaScript strings, 310 in PHP strings, 46 in JavaScript strings, 306 ( ) (parentheses) forcing operator precedence, 65 function call in JavaScript, 321 function call in PHP, 90 grouping in regular expressions, 363, 367 implied, indicating operator precedence, 65 precedence in PHP, 65 * (asterisk) *= (multiplication assignment) operator, 43, 65, 308, 321 multiplication operator, 42, 65, 308, 321 regular expression metacharacter, 361, 367 wildcard character, use with SELECT command, 183 + (plus sign) ++ (increment) operator, 42, 45, 308, 310, 321 precedence in PHP, 65 using in while loop, 80 += (addition assignment) operator, 43, 45, 65, 308, 321 addition and string concatenation operator in JavaScript, 321 addition operator, 42, 65, 308 Boolean mode in MySQL searches, 189 regular expression metacharacter, 362, 367 string concatenation operator in JavaScript, 310, 321 We’d like to hear your suggestions for improving our indexes. Send email to index@oreilly.com. 485 , (comma) comma operator in JavaScript, 321 separating statements within parameter section of loop, 82 - (hyphen) indicating ranges in regular expressions, 364, 367 - (minus sign) -= (subtraction assignment) operator, 43 -> operator (PHP), 105 . (period) .= (string concatenation and assignment) operator, 43, 46, 65 member operator in JavaScript, 321 in regular expressions, 362, 367 separating objects, properties, and methods in JavaScript, 314 string concatenation operator, 46, 65 / (slash) /* and */ in JavaScript multiline comments, 305 /* and */ in PHP comments*, 36 // in JavaScript single-line comments, 305 // in PHP comments, 36 /= (division assignment) operator, 43, 65, 308, 321 division operator, 42, 65, 308, 321 enclosing regular expressions, 361, 367 /i (case-insensitive matching) in regular expressions, 369 : (colon) :: (scope resolution) operator in PHP, 106 using with self keyword, 107 replacing first curly brace in PHP switch statement, 77 ; (semicolon) ending JavaScript statements, 305 ending MySQL commands, 163 ending PHP statements, 37 separating parameters in for loop, 82 < (less than) operator, 43, 65, 68, 309, 321, 324 << (bitwise left shift) operator, 65, 321 <<< (heredoc) operator, 48 <<= (bitwise left shift and assignment) operator, 65, 321 <= (less than or equal to) operator, 43, 65, 68, 309, 321, 324 <> (not equal) operator, 65 <? ?> tags in PHP code, 5 <?php ?> tags, 34 importance in login file, 226 omitting closing tag, 35 = (equals sign) == (equal to) operator, 43, 65, 67, 309, 321, 323 === (identity) operator, 65, 68, 309, 321, 323 => assigning value to array index, 118 assignment operator, 43, 65, 308, 321 > (greater than) operator, 43, 65, 68, 309, 321, 324 >= (greater than or equal to) operator, 43, 65, 68, 309, 321, 324 >> (bitwise right shift) operator, 65, 321 >>= (bitwise right shift and assignment) operator, 65, 321 >>> (bitwise unsigned right shift) operator, 321 >>>= (unsigned right shift and assignment) operator, 321 ? (question mark) ? : (ternary) operator, 65, 77, 321, 331 encoding in URL for GET request, 399 regular expression metacharacter, 367 [ ] (square brackets) accessing array elements in JavaScript, 348, 349 array element, accessing, 122 character classes in regular expressions, 364, 367 member operator in JavaScript, 321 \ (backslash) escaping characters in JavaScript, 310 escaping characters in PHP strings, 47 escaping regular expression metacharacters, 363 ^ (caret) beginning-of-line matching in regular expressions, 366, 367 bitwise xor operator, 65 negating character class in regular expressions, 364, 367 ^= (bitwise xor with assignment) operator, 65, 321 _ (underscore) double underscore (__), beginning method names in PHP, 105 486 | Index in PHP variable names, 42 ` ` (backticks), execution operator, 63 { } (curly braces) in do . . . while loops, 81 in if . . . else statement in PHP, 72 in if . . . elseif . . . else statement in PHP, 73 in if statements in PHP, 71 in switch command in PHP, replacing, 77 in while loops, 79 statement execution in function calls, 92 | (pipe character) bitwise or operator, 65 regular expression metacharacter, 367 |= (bitwise or with assignment) operator, 65, 321 || (logical or) operator, 44, 65, 309, 321, 324 problems caused by, 325 ~ (bitwise not) operator in JavaScript, 321 – (minus sign) (decrement) operator, 42, 45, 308, 310, 321 precedence in PHP, 65 -= (subtraction assignment) operator, 45, 65, 308, 321 Boolean mode in MySQL searches, 189 subtraction and string operator in JavaScript, 321 subtraction operator, 42, 65, 308 A ActiveX, 378 Ajax, xiii, 8, 377–392 checking availability of usernames for email accounts, 10 choosing framework for JavaScript, 393 description of, 378 using XMLHttpRequest, 378–391 cross-browser function for, 378 example program (urlpost.html), 380– 385 GET method, using in example program, 385–387 properties and methods, 379 sending XML requests, 387–391 using YUI, 394–400 Ajax XML example, 399–400 asyncRequest method, 397 GET request (example), 397 including framework files, 396 alphabetical sort (JavaScript sort method), 352 ALTER command, 173 adding auto-incrementing column, 172 creating table index, 178 removing a column, 173 renaming a table, 175 and operator &&, 44, 309 low-precedence and, 44 precedence in PHP, 65 AND operator, 69 AND operator (in MySQL), 194 anonymous functions, 382 Apache web server, 8 arguments array (JavaScript functions), 338 arithmetic operators JavaScript, 308 PHP, 42 array function (PHP), testing, 482 array keyword (JavaScript), 347 array keyword (PHP), 118 arrays fetching row from MySQL database as associative array, 274 JavaScript, 307, 346–353 associative arrays, 347 concat method, 349 forEach method, 349 join method, 350 multidimensional arrays, 348 numeric arrays, 346 push and pop methods, 350 reverse method, 352 sort method, 352 PHP, 39, 115–128 assignment using array keyword, 118 associative arrays, 117 foreach . . . as loop, 119–120 multidimensional, 121–123 numerically indexed, adding items, 115 two-dimensional, 40 using array functions, 123–128 returning from PHP function call, 93 returning with JavaScript functions, 341 array_combine function, checking existence of, 98 AS keyword (MySQL), 194 assignment Index | 487 combining with expressions in PHP, 63 to PHP arrays, using array keyword, 118 variable type, setting in JavaScript, 311 assignment operators JavaScript, 308 PHP, 43 associative arrays in JavaScript, 347 in PHP, 117 $_FILES array, 145 multidimensional, 121 walking through, using foreach . . . as, 119 walking through, using list and each functions, 120 associativity, operator, 66 in JavaScript, 322 authentication, 279 (see also HTTP authentication) login page for social networking site project, 418 simplifying with sessions, 291 starting session after, 289 storing user IP addresses, 293 AUTO_INCREMENT data type, 172 using in MySQL table from PHP, 243 B \b (backspace character) in JavaScript strings, 310 \B (nonword boundary) in regular expressions, 367 \b (word boundary) in regular expressions, 367 backups and restores in MySQL, 219–223 creating backup file, 220 planning backups, 223 restoring from backup file, 222 using mysqldump, 219 BEGIN command, 216 Berners-Lee, Tim, 1 BIGINT data type, 171 BINARY data type, 169 binary operators, 64 bitwise operators, 63 BLOB data type, 170 blogging platform, WordPress, 86 Boolean expressions in JavaScript, 319 Boolean mode in MATCH . . . AGAINST queries, 189 break command using in JavaScript loops, 333 using in JavaScript switch statement, 330 using in PHP for loop, 83 using in PHP switch statement, 76 browser/server request/response dialog with cookies, 279 browsers, 1 basic request/response procedure, 2 catching JavaScript errors with try . . . catch, 327 dynamic request/response procedure, 3 forEach method, cross-browser solution, 350 JavaScript, 299 JavaScript error messages, accessing, 303 JavaScript implementations, differences in, 7 older and nonstandard, not supporting scripting, 301 reading link URL in JavaScript, 316 user agent string, 294 XMLHttpRequest object, cross-browser function, 378 browsing history (JavaScript history object), 317 bumpyCaps convention, 338, 342 BYTE data type, 169 C calendar (YUI), 400–403 callbacks, YUI asyncRequest method, 397 carriage return (\r) in JavaScript strings, 310 in PHP strings, 47 Cascading Style Sheets (CSS), manipulation with JavaScript, 5 case commands in switch statement, 76 case-insensitive matching in regular expressions (/i), 369 case-insensitivity, function names in PHP, 92 casting explicit, JavaScript and, 334 implicit and explicit in PHP, 84 CERN (European Laboratory for Particle Physics), 1 488 | Index CGI (Common Gateway Interface), server-side scripting, 5 CHANGE keyword, specifying data type, 176 CHAR data type, 168 listing of CHAR types, 169 character classes in regular expressions, 363 negating, 364 check user program (social networking site project), 417 checkboxes in forms, 257 submitting multiple values with an array, 258 checkdate function (PHP), 136 classes declaring in JavaScript, 342 defined, 89 PHP, 99 declaring, 100 inheritance and extension, 109–113 static properties and methods, 108 Classic FTP, 28 clone operator (PHP), 103 cloning objects in PHP, 102 Codd, E. F., 203 code examples from this book, xvi viewing and downloads, 35 website, 406 columns adding auto-incrementing column, 173 adding new column and viewing its data, 175 changing data type, 175 defined, 158 removing, 173, 176 renaming, 176 comma (,) comma operator in JavaScript, 321 separating statements within parameter section of loop, 82 Comma-Separated Values format (see CSV format) command prompts, MySQL, 163 command-line interface, accessing MySQL, 158–177 Linux users, 161 Mac OS X users, 160 MySQL commands, 164–168 MySQL data types, 168–177 using MySQL on, 163 Windows users, 159 commands, MySQL, 164–168 canceling, 163 comment tags in HTML <! and >, 301 comments JavaScript, 305 PHP, 36 COMMIT command, 216 compact function, using with PHP arrays, 126 comparison operators JavaScript, 309, 324 PHP, 43, 68 concat method (JavaScript), 349 condition expression (for loop), 81 conditionals in JavaScript, 328–331 ? operator, 331 if statement, 328 switch statement, 329 in PHP, 70–78 ? operator, 77 else statement, 72 elseif statement, 73 if statement, 71 switch statement, 74–77 connection-min.js file, 396 connections, database closing MySQL database connection from PHP, 231 closing PEAR MDB2 connection, 479 connecting to MySQL from PHP, 227–231 creating connect instance using PEAR MDB2, 477 constants PHP, 50 date constants, 136 defining within a class, 107 predefined, 51 constructors JavaScript classes, 342 PHP classes, 104 subclass constructors, 111 constructs (pseudofunctions), 90 content types, Internet media, 147 continue statements, 84 using in JavaScript loops, 334 cookies, 279–282 accessing in PHP, 281 Index | 489 browser/server request/response dialog with, 279 destroying in PHP, 282 forcing cookie-only sessions, 296 setting in PHP, 281 third-party, 279 copy function (PHP), 139 count function (PHP), counting array elements, 124 COUNT qualifier, SELECT command, 183 CREATE command adding auto-incrementing id column, 173 adding indexes when creating tables, 179 CREATE INDEX, 179 creating a table in MySQL, 167 Cross-Site Scripting (XSS) injections, 248 CSS (Cascading Style Sheets), manipulation with JavaScript, 5 CSV (Comma-Separated Values) format, 219 dumping data in, using mysqldump, 222 D \d (digit character) in regular expressions, 368 \d (digit character) in regular expressions, 364 \D (nondigit character) in regular expressions, 368 data types casting, in PHP, 84 JavaScript type-changing functions, 334 MySQL, 168–177 AUTO_INCREMENT type, 172 BINARY types, 169 BLOB, 170 changing for column, 175 CHAR types, 169 DATE and TIME types, 172 numeric, 170 TEXT and VARCHAR types, 170 variable typing in JavaScript, 311 databases, 6 creating in MySQL, 165 defined, 157 design in MySQL highly inefficient table design, 203 requirements of First Normal Form, 205 designing in MySQL, 201 privacy and, 214 selecting database for PHP query in MySQL, 228 triggers, 211 DATE and TIME data types, 172 date and time functions (PHP), 133–137 checkdate, 136 date constants, 136 date function (PHP), 53, 134 date functions (MySQL), 465–471 DATETIME data type, 172 debugging JavaScript errors, 303 decrement operator ( ), 42, 45 in JavaScript, 308 variable decrementing in JavaScript, 310 decrementing variables in JavaScript, 310 default action for switch statement in JavaScript, 330 in PHP, 76 default values in forms, 255 DELETE command, 184 issuing DELETE FROM query using PHP, 242 dependencies in table data, 209 DESC keyword (MySQL), 191 DESCRIBE command, 168 issuing from PHP, 239 destroy_session_and_data function (PHP), 292 destructor methods (PHP5), 104 development server, setting up, 13–32 installing LAMP on Linux, 25–26 installing MAMP on Mac OS X, 19–25 installing WAMP on Windows, 14–18 using a program editor, 29 using an IDE, 30 WAMP, MAMP, or LAMP, 13 working remotely, 26–28 die function (PHP), 227 different_user function (PHP), 294 digits (\d) in regular expressions, 364 DISTINCT qualifier, SELECT command, 184 DNS (Domain Name Service), 3 do . . . while loops, 81 in JavaScript, 332 DOCTYPE declaration, 153 HTML 4.01 document types, 153 XHTML 1.0 document types, 153 Document Object Model (see DOM) DOM (Document Object Model), 314–318 490 | Index . to type from an Administrator Command prompt or a Terminal window XP/Vista (4 instructions) cd Program FilesEasyPHP 3.0php pear channel-discover pear.phpunit.de pear install phpunit/PHPUnit Xcopy. PEAR package, as listed at the web page http://pear.php.net/ packages.php. Table E-2. Installing PEAR packages on different systems System Command Windows "C:Program FilesEasyPHP 3.0phppear". phpunit/PHPUnit Xcopy /E pear*.* includes Mac OS X (3 instructions) cd /Applications/MAMP/bin pear channel-discover pear.phpunit.de pear install phpunit/PHPUnit Linux/Unix (2 instructions) pear channel-discover