Sie sind auf Seite 1von 398

1

Developing Dynamic Web Applications with MySQL and PHP


Revision 1.4

PRESENTED BY

MYSQL AB TRAINING SERVICES


training@mysql.com http://www.mysql.com/training/ INSTRUCTOR GUIDE

Developing Web Applications with MySQL and PHP


Consulting Developer

DBA

Chapter

Course/Chapter/Section Name

Duration (Hours)

Support

Track

Comments

Owner

PHP and MySQL


Day One 1 Introduction 1.1 Structure of MySQL AB 1.2 MySQL Products and Services 1.3 MySQL Partners 1.4 Supported Operating Services 1.5 MySQL Certification Program 1.6 Training Curriculum Paths 1.7 MySQL Website 2 Verify Installation 2.1 LAMP Architecture 2.2 Install/Verify Apache Installation 2.3 Install/Verify MySQL Installation 2.4 Install/Verify PHP Installation 2.5 Putting it All Together 3 PHP Foundations 3.1 Delimit PHP Code Within HTML 3.2 Comment PHP Code 3.3 Construct PHP that interacts with end users 3.4 Data Types in PHP 3.5 Key Control Systems 3.6 Use Defined Functions Day Two 4 MySQL Foundations 4.1 General Architecture 4.2 SQL Parser and Storage Engine Tiers 4.3 MySQL Client 4.4 MySQL Query Browser 5 Manage Databases 5.1 Database Properties 5.2 Database Design Practices 5.3 MySQL Identifiers 5.4 Create Databases 5.5 Alter Databases 5.6 Drop Databases 6 Manage Tables 6.1 Table Properties 6.2 MySQL Data Types 6.3 Create Table 6.4 Alter Table 6.5 Empty Table 6.6 Remove Table 6.7 Indexes 6.8 Foreign Keys 7 SQL SELECT Commands 7.1 SELECT Statements 7.2 Aggregating Query Results 8 SQL Expressions 8.1 SQL Expressions 8.2 Functions in SQL Expressions Day Three 9 SQL DML Commands 9.1 INSERT Statement 9.2 DELETE Statement 9.3 UPDATE Statement 9.4 REPLACE Statement 10 SQL Joins 10.1 What is a Join 10.2 Inner Joins 10.3 Outer Joins 10.4 Using Quaifiers and Aliases

26.5
7.5 1 0 0.25 0 0 0.25 0.25 0.25 3.25 0.25 1 0.75 0.75 0.5 3.25 0.25 0.25 0.5 0.75 0.75 0.75 5.75 1 0 0.25 0.5 0.25 1.25 0 0.25 0.25 0.25 0.25 0.25 2.25 0 0.5 0.5 0.5 0.25 0 0.25 0.25 0.5 0.25 0.25 0.75 0.25 0.5 6.25 1.25 0.25 0.25 0.5 0.25 1.25 0 0.5 0.25 0.25

3
5 5 5 3 5 5 5 5 4 4 3 5 4 4 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5

5
5 5 5 3 4 5 5 5 4 5 4 4 4 4 5 5 4 5 5 5 5 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4

4
5 5 5 3 5 5 5 5 4 4 3 3 5 5 3 3 3 3 3 3 3 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5

4
5 5 5 3 5 5 5 5 4 4 3 3 5 5 3 3 3 3 3 3 3 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5

Developing Web Applications with MySQL and PHP


10.5 Multiple Table UPDATE and DELETE Statements 11 MySQL Database Driven Web Based Forms 11.1 Connecting to MySQL 11.2 Retrieving Data 11.3 Inserting Data 11.4 Updating Existing Data 11.5 Deleting Data 11.6 MySQL Metadata 11.7 MySQL Error Information Day Four 12 Session Handling 12.1 What is Session Handling 12.2 Session Handling Tasks 12.3 PHP Session Handling with MySQL 13 Object Oriented Programming 13.1 Benefits of OOP 13.2 Working with Objects 13.3 Exception Handling 14 Authentication 14.1 HTTP Authentication 14.2 PHP Authentication 15 Securing PHP & MySQL 15.1 PHP Configuration Parameters 15.2 Data Encryption 15.3 Securing the MySQL Server 15.4 Privileges 16 Conclusion 16.1 Course Overview 16.2 MySQL System Overview 16.3 Training and Certification Website 16.4 Course Evaluation 16.5 Thank You! 16.6 Q&A Session 0.25 3.75 0.25 1 0.5 0.5 0.5 0.5 0.5 7 2 0.25 0.75 1 1 0.25 0.5 0.25 0.75 0.25 0.5 1.75 0.5 0.25 0.25 0.75 1.5 0.25 0.25 0.25 0.25 0 0.5 1 1 1 1 1 1 1 1 1 1 1 3 1 1 5 5 4 3 3 3 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4 3 3 3 5 5 5 3 3 3 3 3 3 3 3 3 3 3 4 3 3 5 5 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 5 5 3 3 3 3 3 3 3 5 1 1 1 1 1 1 1 1 4 5 5 5 5 5 5 5 5 5 3 3 3 3 3 3 3 3 5 3 3 3 3 3 3 3 3

NOTES: Using Scale of 0-5 on Importance (0-not needed, 5-high) A duration of zero (0) means that the section should take less than 15 minutes (from 5 to 14) . Some section/chapter durations are padded to adjust for zero durations as well as for labs quizzes, further practices and breaks. Lunch breaks areNOT accounted for in this schedule.

Developing Dynamic Web Applications with MySQL and PHP

Developing Dynamic Web Applications with MySQL and PHP Training Guide
This is the training guide for the Developing Dynamic Web Applications with MySQL and PHP training course. This training guide was developed using the MySQL 5.0 Community Edition - Generally Available (GA) Release and MySQL 5.1 Community Edition - Beta Release. MySQL AB would like to thank the many individuals that played a part in bringing this training material to the numerous students who will benefit from the knowledge and effort that each of these contributors put into the training. Even though there were a large number of contributions from many MySQL AB personnel, the following list of contributors played a vital role in developing this material and ensuring that its contents were accurate, timely and most of all presented in a way that would benefit those that are utilizing it for the benefit of improving their skills with MySQL. Max Mether, Course Development Manager Jeffrey Gorton, Course Developer and Editor Tom Hanlon, Subject Matter Expert Developing Dynamic Web Applications with MySQL and PHP Training Guide Copyright 2007 by MySQL AB All rights reserved. No part of this training guide shall be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical, photocopying, recording, or otherwise, without the written permission of MySQL AB. No patent liability is assumed with respect to the use of the information contained herein. Although every precaution has been taken in the preparation of this training guide, MySQL AB and the associated contributors assume no responsibility for errors or omissions. Nor is any liability assumed for damages resulting from the use of the information contained herein. First Printing: May 2007 Trademarks The copyright to this training guide is owned by the Swedish company MySQL AB. MySQL and the MySQL logo are registered trademarks of MySQL AB. Other trademarks and registered trademarks referred to in this manual are the property of their respective owners, and are used for identification purposes only. Warning and Disclaimers Every effort has been made to make this training guide as complete and accurate as possible to meet the needs of the training herein, but no warranty or fitness is implied. The information provided is on an as is basis.

Developing Dynamic Web Applications with MySQL and PHP

Worldwide Office Locations and Contact Information

MySQL HQ MySQL AB Bangrdsgatan 8 S-753 20 Uppsala Sweden Tel: +46-18-10 18 90 (Administration only) Fax: +46-18-10 18 91 Sales (Scandinavia): +46 730 234 111

US Headquarters MySQL Inc. Cupertino City Center 20450 Stevens Creek Boulevard Suite 350 Cupertino, CA 95014 USA Sales & Support (Toll Free): 1-866-697-7522 Tel: 408-213-6540 Fax: 408-213-2807 Finland MySQL Finland Oy Laaksotie/Dalvgen 10 02700 KAUNIAINEN/GRANKULLA Finland Tel/Fax: +358 9 852 1421 Sales/Myynti: GSM: +358 40 551 9358 Iko Rein

MySQL Inc. 2510 Fairview Avenue East Seattle, WA 98102 USA Tel: 206-336-2030 Fax: 206-336-2002

Germany, Austria and Switzerland MySQL GmbH Radlkoferstrae 2 D-81373 Mnchen Germany Tel. +49 (0)89 724 99-150 Fax: +49 (0)89 724 99-250

France MySQL AB (France) 123, rue du Faubourg St. Antoine 75011, Paris France Tel (Sales / Service Commercial): 0800.908.683 Tel (outside France): 33 (0)1.43.077.099 Fax: 33 (0)1.43.077.100 Italy MySQL AB (Italy) Numero Verde: 800 788 345 UK Tel: 0845 300 4266 Fax: +44 207 900 3955 Australia, Asia & Pacific Tel: +61 2 83 073 824

Ireland MySQL AB Fleet Chambers, 3rd Floor 8-9 Westmoreland Street Dublin D2, Republic of Ireland Tel: +353 1 6177878 Fax: +44 207 900 3955

Japan MySQL K.K. N30F Shinjuku Park Tower, 3-7-1 Nishi-Shinjuku, Shinjuku-ku, Tokyo 163-1030 Tel: 81-(0)3-5326-3133 Fax: 81-(0)3-5326-3001

ii

Developing Dynamic Web Applications with MySQL and PHP

Conventions Used in This Training Guide


This training guide uses certain typographical conventions: TEXT IN THIS STYLE is used for SQL statements; database, table, and column names; program listings and source code; and environment variables. Example: To reload the grant tables, use the FLUSH PRIVILEGES statement. Text in this style indicates input that you type in examples. Text in this style indicates the names of executable programs and scripts, examples being mysql (the MySQL command line client program) and mysqld (the MySQL server executable). Text in this style is used for variable input for which you should substitute a value of your own choosing. Filenames and directory names are written like this: The global my.cnf file is located in the /etc directory. Character sequences are written like this: To specify a wildcard, use the '%' character. Text in this style is used for emphasis. Text in this style is used in table headings and to convey especially strong emphasis. When commands are shown that are meant to be executed from within a particular program, the prompt shown preceding the command indicates which command to use. For example, shell> indicates a command that you execute from your login shell, and mysql> indicates a statement that you execute from the mysql client program: shell> type a shell command here mysql> type a mysql statement here The shell is your command interpreter. On Unix, this is typically a program such as sh, csh, or bash. On Windows, the equivalent program is command.com or cmd.exe, typically run in a console window. When you enter a command or statement shown in an example, do not type the prompt shown in the example. Database, table, and column names must often be substituted into statements. To indicate that such substitution is necessary, this manual uses db_name, tbl_name, and col_name. For example, you might see a statement like this: mysql> SELECT col_name FROM db_name.tbl_name; This means that if you were to enter a similar statement, you would supply your own database, table, and column names, perhaps like this: mysql> SELECT author_name FROM biblio_db.author_list; SQL keywords are not case sensitive and may be written in any lettercase. This training guide uses uppercase. In syntax descriptions, square brackets ('[' and ']') indicate optional words or clauses. For example, in the following statement, IF EXISTS is optional: DROP TABLE [IF EXISTS] tbl_name When a syntax element consists of a number of alternatives, the alternatives are separated by vertical bars ('|'). When one member from a set of choices may be chosen, the alternatives are listed within square brackets ('[' and ']'): TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str) When one member from a set of choices must be chosen, the alternatives are listed within braces ('{' and '}'): {DESCRIBE | DESC} tbl_name [col_name | wild] An ellipsis (...) indicates the omission of a section of a statement, typically to provide a shorter version of more complex syntax. For example, INSERT ... SELECT is shorthand for the form of INSERT statement that is followed by a SELECT statement. An ellipsis can also indicate that the preceding syntax element of a statement may be repeated. In the following example, multiple reset_option values may be given, with each of those after the first preceded by commas: RESET reset_option [,reset_option] ... Commands for setting shell variables are shown using Bourne shell syntax. For example, the sequence to set the CC environment variable and run the configure command looks like this in Bourne shell syntax: shell> CC=gcc ./configure If you are using csh or tcsh, you must issue commands somewhat differently: shell> setenv CC gcc and shell> ./configure

iii

Developing Dynamic Web Applications with MySQL and PHP

Supporting Images Used in This Training Guide


The following is a summary of the standard images used in this manual to support the instruction: IMAGE NAME Preparation DESCRIPTION This image is used to describe the steps required to be completed prior to performing a hands-on exercise.

Written Exam

This image is used to identify that the student is going to be tested upon the material previously presented in the instructional material. Throughout the course the instructor will conduct labs in line with the instruction, which are designed to help you to understand the nuts and bolts (inner-workings) of the topic. This image is used to convey to the student that there is a final exercise to complete prior to the completion of the chapter. This image identifies an area on a page designated for students to write notes associated with the class. This image is used throughout the course guide to indicate the existence and number of a corresponding instruction slide.

InLine Lab

Further Practice Lab

Student Notes

123

Slide Number Boxes

Instructor Notes: Boxes like this one are used throughout the course manual to give instructors tips on how to deliver the material and to give them extra information that is not included in the student manual. Please be advised that instructors are requested to cover all the material in this manual, as prompted by the slides. Although some slides will mimic the manual exactly, most will not. In those cases, instructors will need to use the manual, along with these notes to deliver the required information to the students. These note boxes will always be placed at the bottom of the page, and are only in the instructor guide.

iv

Developing Dynamic Web Applications with MySQL and PHP


2

COURSE OBJECTIVES
This instructor-led course is designed for students planning on developing applications that make use of MySQL and PHP. Through a hands-on approach, this course will help developers with a reasonable knowledge of PHP improve their development skills to the point where they can use PHP and MySQL as a cohesive platform for the development of complex dynamic web applications. Upon completion of this course you will be able to: Verify the correct installation of the LAMP Components Utilize the basic components of PHP to build a foundation for more complex web applications Understand the basic components of MySQL to build a foundation for the development of fully dynamic and database-driven sites Manage Databases within MySQL Manage Tables within MySQL Utilize SQL query commands to retrieve data from the MySQL Database Utilize SQL expressions Manipulate table data using the SQL Data Manipulation Language (DML) commands Retrieve data from multiple MySQL tables using Joins

Create web based forms that interact with the end user and the data within MySQL Utilize session handling within PHP to track user-specific behavior and preferences. Utilize error and exception handling in PHP to detect, log and report issues that may arise during program execution Integrate PHP's object oriented programming (OOP) functionality into the design of web applications Authenticate user identities utilizing PHP built-in authentication capabilities and MySQL's user and privilege management capabilities Securing PHP and MySQL to improve the integrity of the application and subsequent data

Developing Dynamic Web Applications with MySQL and PHP

Table of Contents
1 Introduction ....................................................................................................................................................... 1-1 1.1 Learning Objectives................................................................................................................................... 1-1 1.2 MySQL AB................................................................................................................................................ 1-2 1.3 MySQL Products ....................................................................................................................................... 1-3 1.3.1 MySQL Database Products................................................................................................................ 1-3 1.3.2 MySQL GUI Tools ............................................................................................................................ 1-5 1.3.3 MySQL Drivers ................................................................................................................................. 1-5 1.4 MySQL Services........................................................................................................................................ 1-6 1.4.1 MySQL Training ............................................................................................................................... 1-6 1.4.2 MySQL Certification ......................................................................................................................... 1-6 1.4.3 MySQL Consulting............................................................................................................................ 1-6 1.4.4 MySQL Support................................................................................................................................. 1-6 1.5 Community vs. Enterprise ......................................................................................................................... 1-7 1.6 MySQL Partners ........................................................................................................................................ 1-9 1.7 Supported Operating Systems...................................................................................................................1-10 1.8 MySQL Certification Program .................................................................................................................1-11 1.9 Training Curriculum Paths........................................................................................................................1-12 1.10 MySQL Website .......................................................................................................................................1-14 1.10.1 MySQL Community Web Page ........................................................................................................1-15 1.11 Chapter Summary .....................................................................................................................................1-18 2 LAMP ................................................................................................................................................................ 2-2 2.1 Learning Objectives................................................................................................................................... 2-2 2.2 LAMP Architecture ................................................................................................................................... 2-3 2.3 Apache Server............................................................................................................................................ 2-4 2.4 MySQL Server........................................................................................................................................... 2-8 2.5 PHP...........................................................................................................................................................2-12 2.6 Putting It All Together..............................................................................................................................2-16 2.7 Chapter Summary .....................................................................................................................................2-19 3 PHP FOUNDATIONS ............................................................................................................................................ 3-1 3.1 Learning Objectives................................................................................................................................... 3-1 3.2 Delimiting PHP Code ................................................................................................................................ 3-2 3.3 Comments.................................................................................................................................................. 3-3 3.4 Construct Feedback ................................................................................................................................... 3-5 3.5 PHP Data Types......................................................................................................................................... 3-7 3.5.1 Scalar Data Types .............................................................................................................................. 3-7 3.5.2 Compound Data Types ...................................................................................................................... 3-9 3.5.3 Special Data Types ...........................................................................................................................3-11 3.6 Flow Control Statements ..........................................................................................................................3-12 3.6.1 if ... else ... elseif ...............................................................................................................................3-13 3.6.2 Switch ...............................................................................................................................................3-15 3.6.3 While ................................................................................................................................................3-16 3.6.4 Do ... While.......................................................................................................................................3-16 3.6.5 For.....................................................................................................................................................3-17 3.6.6 Foreach .............................................................................................................................................3-18 3.6.6.1 Break and Continue ......................................................................................................................3-19 3.7 User Defined Functions ............................................................................................................................3-20 3.8 Chapter Summary .....................................................................................................................................3-22 4 MYSQL FOUNDATIONS ...................................................................................................................................... 4-1 4.1 Learning Objectives................................................................................................................................... 4-1 4.2 MySQL General Architecture.................................................................................................................... 4-2 4.2.1 MySQL Server................................................................................................................................... 4-2 4.2.2 Client Programs ................................................................................................................................. 4-2 4.3 SQL Parser and Storage Engine Tiers ....................................................................................................... 4-4 4.3.1 Storage Engine Breakdown ............................................................................................................... 4-5

Developing Dynamic Web Applications with MySQL and PHP The mysql Client ..................................................................................................................................... 4-6 4.4 4.4.1 Using mysql Interactively................................................................................................................ 4-6 4.4.2 Statement Terminators....................................................................................................................... 4-7 4.5 MySQL Query Browser............................................................................................................................. 4-9 4.5.1 Using the Connection Dialog............................................................................................................. 4-9 4.5.2 The MySQL Query Browser Window ..............................................................................................4-10 4.6 Chapter Summary .....................................................................................................................................4-13 MANAGING DATABASES ..................................................................................................................................... 5-1 5.1 Learning Objectives................................................................................................................................... 5-1 5.2 Database Properties ................................................................................................................................... 5-2 5.3 Database Design Practices ......................................................................................................................... 5-4 5.4 MySQL Identifiers..................................................................................................................................... 5-5 5.5 Creating Databases .................................................................................................................................... 5-6 5.6 Drop a Database......................................................................................................................................... 5-7 5.6.1 CAUTION: When Using DROP DATABASE.................................................................................. 5-7 5.7 Chapter Summary .....................................................................................................................................5-11 MANAGING DATABASE TABLES ......................................................................................................................... 6-1 6.1 Learning Objectives................................................................................................................................... 6-1 6.2 Table Properties ......................................................................................................................................... 6-2 6.2.1 Storage Engines ................................................................................................................................. 6-3 6.3 MySQL Data Types................................................................................................................................... 6-5 6.3.1 Numeric Data Type............................................................................................................................ 6-6 6.3.2 String Data Types .............................................................................................................................. 6-8 6.3.3 Temporal Data Types......................................................................................................................... 6-9 6.4 Creating Database Tables .........................................................................................................................6-10 6.4.1 Displaying Table Creation Information ............................................................................................6-11 6.4.2 Table Properties ................................................................................................................................6-12 6.4.3 Column Options................................................................................................................................6-13 6.4.4 Temporary Tables .............................................................................................................................6-14 6.5 Altering Tables .........................................................................................................................................6-15 6.5.1 Add Columns ....................................................................................................................................6-15 6.5.2 Remove Columns..............................................................................................................................6-16 6.5.3 Modifying Columns..........................................................................................................................6-16 6.5.4 Changing Columns ...........................................................................................................................6-17 6.5.5 Renaming Tables ..............................................................................................................................6-17 6.5.6 Emptying Tables ...............................................................................................................................6-17 6.6 Drop Tables ..............................................................................................................................................6-18 6.7 Table Indexing ..........................................................................................................................................6-19 6.8 Foreign Keys.............................................................................................................................................6-21 6.9 Chapter Summary .....................................................................................................................................6-30 SQL SELECT COMMANDS ................................................................................................................................... 7-1 7.1 Learning Objectives................................................................................................................................... 7-1 7.2 SELECT Statements .................................................................................................................................. 7-2 7.2.1 SELECT with DISTINCT ................................................................................................................. 7-4 7.2.2 SELECT with WHERE ..................................................................................................................... 7-6 7.2.3 SELECT with ORDER BY................................................................................................................ 7-8 7.2.4 SELECT with LIMIT........................................................................................................................7-10 7.2.5 SELECT with MySQL Query Browser ............................................................................................7-12 7.3 Aggregating Query Results.......................................................................................................................7-13 7.4 Chapter Summary .....................................................................................................................................7-18 SQL EXPRESSIONS ............................................................................................................................................. 8-1 8.1 Learning Objectives................................................................................................................................... 8-1 8.2 SQL Expressions ....................................................................................................................................... 8-2 8.2.1 Numeric Expressions ......................................................................................................................... 8-3 8.2.2 String Expressions ............................................................................................................................. 8-4 8.2.3 Temporal Expressions........................................................................................................................ 8-7 8.3 Functions in SQL Expressions................................................................................................................... 8-9

Developing Dynamic Web Applications with MySQL and PHP Comparison Functions ....................................................................................................................... 8-9 8.3.1 8.3.2 Control Flow Functions ....................................................................................................................8-10 8.3.3 Numeric Functions............................................................................................................................8-13 8.3.4 String Functions................................................................................................................................8-15 8.3.5 Temporal Functions ..........................................................................................................................8-16 8.3.6 NULL-Related Functions .................................................................................................................8-18 8.4 Chapter Summary .....................................................................................................................................8-23 9 SQL DML COMMANDS ..................................................................................................................................... 9-1 9.1 Learning Objectives................................................................................................................................... 9-1 9.2 The INSERT Statement ............................................................................................................................. 9-2 9.2.1 INSERT with SELECT...................................................................................................................... 9-3 9.2.2 INSERT with LAST_INSERT_ID .................................................................................................... 9-3 9.2.3 INSERT with NULL Values.............................................................................................................. 9-3 9.3 The UPDATE Statement ........................................................................................................................... 9-4 9.3.1 UPDATE with SET ........................................................................................................................... 9-5 9.3.2 UPDATE with ORDER BY .............................................................................................................. 9-5 9.3.3 UPDATE with LIMIT ....................................................................................................................... 9-5 9.4 The REPLACE Statement ......................................................................................................................... 9-6 9.4.1 INSERT with ON DUPLICATE KEY UPDATE Instead of REPLACE .......................................... 9-7 9.5 The DELETE Statement ............................................................................................................................ 9-8 9.6 Chapter Summary .....................................................................................................................................9-13 10 SQL JOINS ........................................................................................................................................................10-1 10.1 Learning Objectives..................................................................................................................................10-1 10.2 What is a Join?..........................................................................................................................................10-2 10.3 Inner Joins.................................................................................................................................................10-3 10.3.1 Comma Separated Inner Join ............................................................................................................10-3 10.3.2 The INNER JOIN Keywords..........................................................................................................10-4 10.4 Outer Joins................................................................................................................................................10-6 10.4.1 Left Outer Join..................................................................................................................................10-6 10.4.2 Right Outer Join................................................................................................................................10-8 10.5 Using Qualifiers and Aliases ....................................................................................................................10-9 10.5.1 Qualifying Column Names ...............................................................................................................10-9 10.5.2 Qualifying and Aliasing Table Names............................................................................................10-11 10.5.3 Self Joins.........................................................................................................................................10-12 10.6 Multi-Table UPDATE and DELETE Statements .....................................................................................10-13 10.7 Chapter Summary ...................................................................................................................................10-17 11 MYSQL DATA DRIVEN WEB BASED FORMS .....................................................................................................11-1 11.1 Learning Objectives..................................................................................................................................11-1 11.2 Connecting to MySQL..............................................................................................................................11-2 11.2.1 Independent Connection Information ...............................................................................................11-4 11.3 Retrieving Data.........................................................................................................................................11-6 11.4 The Web Interface ..................................................................................................................................11-10 11.5 Update Existing Data..............................................................................................................................11-16 11.6 Delete Data .............................................................................................................................................11-18 11.7 Inserting Data .........................................................................................................................................11-21 11.8 MySQL Metadata ...................................................................................................................................11-24 11.8.1 PHP Functions for Retrieving Metadata .........................................................................................11-27 11.9 MySQL Error Information......................................................................................................................11-29 11.10 Chapter Summary ...............................................................................................................................11-31 12 SESSION HANDLING...........................................................................................................................................12-1 12.1 Learning Objectives..................................................................................................................................12-1 12.2 What is Session Handling .........................................................................................................................12-2 12.3 Session Handling Tasks............................................................................................................................12-3 12.3.1 Encoding/Decoding Session Data.....................................................................................................12-5 12.4 PHP Session Handling with MySQL........................................................................................................12-6 12.4.1 MySQL Handling Logins Example ..................................................................................................12-6 12.4.2 Session Handling Configuration Options .......................................................................................12-10

Developing Dynamic Web Applications with MySQL and PHP 12.5 Chapter Summary ...................................................................................................................................12-13 13 OBJECT ORIENTED PROGRAMMING ...................................................................................................................13-1 13.1 Learning Objectives..................................................................................................................................13-1 13.2 Benefits of OOP........................................................................................................................................13-2 13.3 Working with Objects...............................................................................................................................13-3 13.4 Exception Handling ..................................................................................................................................13-6 13.5 Chapter Summary .....................................................................................................................................13-9 14 ESTABLISHING USER AUTHENTICATION ............................................................................................................14-1 14.1 Learning Objectives..................................................................................................................................14-1 14.2 HTTP Authentication................................................................................................................................14-2 14.3 PHP Authentication ..................................................................................................................................14-3 14.3.1 Hard-Coded Authentication ..............................................................................................................14-4 14.3.2 File-Based Authentication ................................................................................................................14-5 14.3.3 Database Authentication ...................................................................................................................14-7 14.4 Chapter Summary ...................................................................................................................................14-10 15 SECURING PHP AND MYSQL............................................................................................................................15-1 15.1 Learning Objectives..................................................................................................................................15-1 15.2 Building a Wall of Security ......................................................................................................................15-2 15.2.1 PHP Configurations ..........................................................................................................................15-3 15.3 Data Encryption ........................................................................................................................................15-5 15.4 Securing the MySQL Server (mysqld) .....................................................................................................15-6 15.5 MySQL Access Privilege System.............................................................................................................15-8 15.5.1 MySQL versus Operating System Accounts ....................................................................................15-8 15.5.2 Creating and Dropping User Accounts .............................................................................................15-9 15.5.3 Setting Account Password ................................................................................................................15-9 15.6 Privileges ................................................................................................................................................15-10 15.6.1 Types of Privileges That MySQL Supports....................................................................................15-10 15.6.2 The Grant Tables ............................................................................................................................15-12 15.6.3 Granting Privileges .........................................................................................................................15-14 15.6.4 The GRANT Statement ..................................................................................................................15-15 15.6.5 The SHOW GRANT Statement......................................................................................................15-16 15.6.6 Revoking Privileges........................................................................................................................15-18 15.6.7 Changing Account Passwords.........................................................................................................15-19 15.6.8 When Privilege Changes Take Effect .............................................................................................15-19 15.7 Chapter Summary ...................................................................................................................................15-21 16 CONCLUSION .....................................................................................................................................................16-1 16.1 Course Objectives.....................................................................................................................................16-1 16.2 Training and Certification Website..........................................................................................................16-2 16.3 Course Evaluation.....................................................................................................................................16-4 16.4 THANK YOU! ........................................................................................................................................16-5 16.5 Q&A Session ............................................................................................................................................16-6

Appendix A Appendix B Appendix C Appendix D Appendix E

Introduction to Linux........................................................................................................................A-1 Basic vi Commands ..........................................................................................................................B-1 Upload Form Example......................................................................................................................C-1 PHP Strings and Regular Expressions..............................................................................................D-1 Further Practice Solutions................................................................................................................. E-1

Developing Dynamic Web Applications with MySQL and PHP Instructor Notes: This slide number corresponds to a slide with the course Table of Contents (Structure). There will be one of these slides before each chapter to show the current chapter being covered. This is to give the students a sense of the progress of the class.

CHAPTER 1
5

INTRODUCTION

Developing Dynamic Web Applications with MySQL and PHP

Chapter 1 Introduction

1
6

INTRODUCTION
Learning Objectives
This chapter introduces you to MySQL and MySQL AB, the support organization for MySQL. In this chapter, you will learn: The details of the MySQL AB Business Model What MySQL products and professional services are available from MySQL AB Define and differentiate between Enterprise and Community Which Operating Systems are currently supported What is available through the MySQL Community web page What is the MySQL Certification program Which courses are available to you after this course

1.1

Instructor Notes: This slide number corresponds to a slide with information that is not included in the instructor or student guides. It is pertaining to getting to know the students in the class.

Instructor Notes: This slide number corresponds to a slide with information that is not included in the instructor or student guides. It is pertaining to the checklist of items to discuss before starting the class.

Instructor Notes: This slide number corresponds to a slide with information that is not included in the instructor or student guides. It is pertaining to explaining the format of the majority of the slides.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-1

Developing Dynamic Web Applications with MySQL and PHP


10

Chapter 1 Introduction

1.2

MySQL AB
MySQL is a Relational Database Management System (RDBMS). MySQL AB develops and markets a family of high performance, affordable database servers and tools. Contributing to building the mission-critical, high-volume systems and products worldwide is what makes MySQL the worlds most popular open source database, as well as its reliability, excellent performance and ease of use. MySQL is not only the worlds most popular open source database, its also the fastest growing database in the industry, with more than 11 million active installations and 50,000 downloads per day.

The company was founded in Sweden by two Swedes and a Finn: David Axmark, Allan Larsson and Michael "Monty" Widenius who have worked together since the 80's. MySQL AB(Swedish for Inc.) is the sole owner of the MySQL server source code, the MySQL trademark and the mysql.com domain worldwide. MySQL has always been a strong supporter of the Open Source philosophy and the Open Source Community, and strives to work with partners that share the same values and mind-set. The MySQL mission: To make superior database software available and affordable to all.

MySQL is installed on every continent in the world (Yes, even Antarctica!)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-2

Developing Dynamic Web Applications with MySQL and PHP

Chapter 1 Introduction

1.3
1.3.1
11

MySQL Products
MySQL Database Products MySQL provides database products to meet the needs of ISV/OEM, Enterprise, and Community Server users. MySQL database products are recognized for superior ease of use, performance, and reliability. Enterprise Server o The most reliable, secure and up-to-date version of the world's most popular open source database for cost-effectively delivering E-commerce, Online Transaction Processing (OLTP), and multi-terabyte Data Warehousing applications. (Available only with the MySQL Enterprise subscription). The MySQL database server for open source developers and technology enthusiasts who want to get started with MySQL. Supported by the large MySQL open source community. Under the General Public License (GPL), benefits to the open source community include a commercialgrade framework that is free of charge. The most popular choice for OEMs/ISVs who want to cost-effectively embed or bundle a reliable and high-performance relational database. A fault tolerant database clustering architecture for deploying highly available mission-critical database applications. Formerly known as SAP DB, MaxDB is the result of a strategic alliance between MySQL and SAP to jointly develop and market an open source database for SAP/R3.

Community Server o

Embedded Database o

Cluster o

MaxDB o

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-3

Developing Dynamic Web Applications with MySQL and PHP


12

Chapter 1 Introduction

MySQL Enterprise A comprehensive set of enterprise-grade software, support and services directly from the developers of MySQL to ensure the highest levels of reliability, security and uptime. As a proactive service that helps you eliminate problems before they occur, it gives you everything you need in a single, unified offering to successfully develop and deploy business critical applications using MySQL. Enterprise Server o The most reliable, secure and up-to-date version of the world's most popular open source database for cost-effectively delivering E-commerce, Online Transaction Processing (OLTP), and multi-terabyte Data Warehousing applications. Network Monitoring and Advisory o Services to ensure the maximum quality, uptime, and performance of MySQL Enterprise systems. Production Support o Around-the-clock support for the MySQL Enterprise server, along with consulting services and self-help knowledge aids.

13

Network Enterprise Dashboard...

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-4

Developing Dynamic Web Applications with MySQL and PHP


14

Chapter 1 Introduction

1.3.2

MySQL GUI Tools A comprehensive set of open source visual database tools. These easy to use visual tools enable database developers and DBAs to be more productive. MySQL Migration Toolkit o Using a wizard-driven interface, the MySQL Migration Toolkit implements a proven methodology and walks you through the necessary steps to successfully complete a database migration project.

MySQL Administrator o A powerful visual administration console that enables you to easily administer your MySQL environment and gain significantly better visibility into how your databases are operating. MySQL Query Browser o An extremely user-friendly visual tool for creating, executing, and optimizing SQL queries for your MySQL Database Server. Bundled Tools The MySQL graphical user interface (GUI) tools discussed here come bundled together when downloaded from the MySQL website.

1.3.3
15

MySQL Drivers Standards-based drivers (also known as Connectors) enable developers to build database applications in their language of choice. In addition, a native C library allows developers to embed MySQL directly into their C applications. MySQL provides the following drivers: MySQL Connector/ODBC o Connect to a MySQL database server using the ODBC database API on all Microsoft Windows and most Unix platforms. MySQL Connector/J o A native Java driver that converts JDBC (Java Database Connectivity) calls into the network protocol used by the MySQL database. MySQL Connector/Net o An ADO.NET provider that allows access from the .NET platform using the network protocol used by the MySQL database. MySQL Connector/MXJ o An MBean that allows seamlessly embedding the MySQL database server within the J2EE environment. MySQL Connector/PHP (New to the MySQL family of Connectors) o For connecting to MYSQL from PHP on Windows (not necessary for Unix variants).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-5

Developing Dynamic Web Applications with MySQL and PHP


16

Chapter 1 Introduction

1.4
1.4.1

MySQL Services
MySQL Training MySQL offers a comprehensive set of MySQL training courses that give you a competitive edge in building world-class database solutions. Courses can be chosen individually, as part of a bundle, and/or following our suggested curriculum path for Developers and Database Administrators (DBAs).

1.4.2

MySQL Certification MySQL Certification Program is a high quality certification program that provides Developers and DBAs with the credentials to prove they have the knowledge, experience and skills to use and manage MySQL Server. With MySQL personal certifications, you get to show that you are among the best-of-breed MySQL users and lay the foundation for becoming a trusted and valuable resource for your company and customers.

1.4.3

MySQL Consulting MySQL AB offers a full range of consulting services. Whether you are starting a new project, needing to optimize an existing MySQL application, or migrating from a proprietary database to MySQL, we have an affordable solution for you. Using industry best practices and proven methodologies, your MySQL certified consultant will help you deliver on-time and on-budget.

1.4.4

MySQL Support MySQL offers a full range of support options. MySQL Technical Support is designed to save you time and to ensure you achieve the highest levels of performance, reliability, and uptime. Community support o Mailing Lists o Forums (http://forums.mysql.com/) o Community Articles (http://dev.mysql.com/tech-resources/articles) o Bugs Database (http://bugs.mysql.com/) o No direct access to support engineers o PlanetMySQL Blogs (http://www.planetmysql.org/) o MySQL Reference Manuals (http://dev.mysql.com/doc) o MySQLForge (http://forge.mysql.com/) Purchased support o Enterprise subscription o Support for MySQL Cluster o Support for MySQL Embedded (OEM/ISV) o MaxDB Support

o Online Knowledge Base ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-6

Developing Dynamic Web Applications with MySQL and PHP


17

Chapter 1 Introduction

1.5

Community vs. Enterprise


There are many things to consider when choosing between using the Community server versus the Enterprise server subscription. The following charts summarize the uses and requirements for each and do a comparison to assist in understanding the differences. How does the MySQL Community work?

MySQL AB

MySQL Community

Open Source Database Server Minimum Two Binaries/Year Fixes/Feature Constant Source Code Drops Free Mgmt Tools/Connectors Help, Forums

New Ideas

Code Contributions Bug Reports Help, Forums

Spread MySQL Goodwill

The left side of this chart shows what MySQL provides to the user community. On the right, is what our user community provides back to us and to the whole community.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-7

Developing Dynamic Web Applications with MySQL and PHP


18

Chapter 1 Introduction

How does the MySQL Enterprise work?

Community / Third Party Development


Many Ideas / Submissions

MySQL Community Server


Selected Submissions Become Features

MySQL Enterprise Server


Mature Features Only

Design/Development

Community Purpose

Enterprise Grade

Community Recommendations Community Server Code Contributions - Direct Community Code Contributions MySQL Forge Third party contributions

Delivery of Community and Customer Recommendations Acceptance/Rejection of Community Code Contributions Community Testing and Validation As Needed Release Schedule, including Bug Fixes and New Features

Selected Feature Set for Enterprise Installations Predictable Service Pack Schedule Strong Internal Quality Assurance Testing External Quality Assurance Testing Certified for Popular Platforms and Applications
Formal Technical Support

The above chart shows the progression of code feature implementation into the MySQL Enterprise Server; from user input, to MySQL Community Server placement/testing, to further improvements which are placed in the MySQL Enterprise Server product.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-8

Developing Dynamic Web Applications with MySQL and PHP


19

Chapter 1 Introduction

1.6

MySQL Partners
MySQL has had the privilege of forming alliances with excellent partners and attracting some of the most impressive customers in the industry! When you join our ranks, you are joining a winning team with a wide variety of MySQL implementations. It never ceases to amaze us, the innovative and powerful ways in which our tools are being used. To name only a few; Education AUF (Agence Universitaire de la Francophonie) University of California, Berkeley World Wide Web Yahoo! Wikipedia Finance Chicago Mercantile Exchange HypoVereinsbank Healthcare Finnish National Public Health Institute UNICEF Manufacturing Yamaha Epson Media BBC The Weather Channel (Weather.com) Open Source Projects PHProjekt eGroupWare Retail Axfood AB Macys Technology Apple Motorola Telecom AT&T Wireless Nokia Transport AXS Marine Viasuisse Travel Continental Airlines Orbitz

"We have used MySQL far more than anyone expected. We went from experimental to mission-critical in a couple of months." Jeremy Zawodny--MySQL Database Expert Yahoo! Finance

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-9

Developing Dynamic Web Applications with MySQL and PHP


20

Chapter 1 Introduction

1.7

Supported Operating Systems


MySQL runs on more than 20 platforms, giving users the kind of flexibility that puts them in control. Windows, Linux and Solaris are the most popular operating systems for running MySQL. Versions of MySQL are currently available for the following operating systems; Windows (multiple) Linux (multiple) Solaris FreeBSD Mac OS/X HP-UX IBM AIX QNX SCO Open BSD SGI Irix Novell NetWare

This list is continually being updated. For the most current information, please check our website: http://www.mysql.com . Source code and special builds are also available.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-10

Developing Dynamic Web Applications with MySQL and PHP


21

Chapter 1 Introduction

1.8

MySQL Certification Program


The MySQL Certification Program is a high quality certification program that provides developers and DBAs with the credentials to prove they have the knowledge, experience and skills to use and manage MySQL Server. MySQL will offer two tiers of certification for MySQL 5.0 (most recent version): 1. Certified MySQL 5.0 Developer (CMDEV) - proves mastery of the fundamental skills of using MySQL including creating and using databases and tables, inserting, modifying, deleting, and retrieving data. 2. Certified MySQL 5.0 Database Administrator (CMDBA) - proves mastery of the ability to manage MySQL Server including such advanced areas of database management, installation, security, disaster prevention and optimization. 3. Certified MySQL Cluster DBA (CMCDBA) - part of the DBA track which represents an advancement level exceeding CMDBA certification. In order to attain CMCDBA certification, you must attain CMDBA certification and pass one CMCDBA exam.

The chart above shows the curriculum path for Developers, Database Administrators and Cluster. They show the current course available for certification preparation, the respective exams, and the receipt of the certification. Certification Web Page For more information on the certification program and the content of the exams, see our Certification web page; http://www.mysql.com/certification/ . Exam Administration All exams are administered through one of more than 3,000 Pearson VUE testing centers available worldwide. And through the Linux Professional Institute proctor network. Visit the MySQL certification webpage, online forum or email certification@mysql.com for more information. ______________________________________________________________________________________________ Instructor Notes: Suggestion for extra exercise: go to www.vue.com/mysql and locate your nearest testing center. ______________________________________________________________________________________________ Information about all the exams can be found on the Certification web page. Have students find this page now, if ______________________________________________________________________________________________ the majority is interested. Also mention that the new Cluster certification is coming soon. ______________________________________________________________________________________________

Page 1-11

Developing Dynamic Web Applications with MySQL and PHP

Chapter 1 Introduction

1.9

Training Curriculum Paths


MySQL offers the most comprehensive set of MySQL training courses that enable the building of database solutions and competitiveness now and into the future. In addition to our open courses, we also offer inhouse training. The MySQL training services staff has put together great courses designed for success, and an excellent training path for each individual to reach his/her training goals. There are two tiers to the curriculum paths:

22

Developer Path Introduction Courses o Developing Dynamic Web Applications with MySQL and PHP This course will provide the tools needed for the development of dynamic web application. This course takes the student from the basics to the advanced features in four hands-on, heavy duty training days. Each student will have the opportunity to build a real-world application during the course. Prerequisites: Basic experience with designing HTML pages including HTML forms and experience with any programming language. Basic PHP skills. 4 days in length. o MySQL for Beginners This course covers the fundamentals of SQL and relational databases, using MySQL as a teaching tool. Prerequisites: Basic computer literacy is required. Previous experience with any command-line program (such as MS-DOS or the MS Windows command prompt) is beneficial. 4 Days in length. Intermediate Courses o MySQL for Developers - This instructor-led course is designed for students planning on developing applications that make use of MySQL 5.0 (and higher). This course covers essential SQL statements for data design, querying, and programming. In addition, it will prepare students for the MySQL Developer certification. Prerequisites: Some experience with Relational Databases and SQL. 5 days in length. o MySQL 5.0 Upgrading and New Features This instructor-led course will provide in-depth knowledge needed to become proficient using MySQL 5.0. This training course will provide quality time both on the topic, hands-on labs and with the expert instructor. Prerequisites: Existing MySQL users who want to become proficient using MySQL 5.0. 3 Days in length. Advanced Courses o Advanced Stored Procedures This instructor-led course with focus on labs is designed to teach you how to maximize the use of stored procedures along with the knowledge to discern when an application should contain stored procedures and when they should not. 2 Days in length.

Virtual Courses o MySQL Database Design - This instructor-led virtual course is designed for developers who wish to use sound database design principles while creating MySQL databases. This course will prepare each student with the skills needed to create databases that maintain data consistency, data integrity and data accuracy while improving SQL efficiency. Students will be provided with demonstrations that will support their ability to apply their learning immediately upon completion of the training. 4 hours in length.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-12

Developing Dynamic Web Applications with MySQL and PHP


23

Chapter 1 Introduction

Database Administrator (DBA) Path Introduction Courses o MySQL for Beginners This course covers the fundamentals of SQL and relational databases, using MySQL as a teaching tool. Prerequisites: Basic computer literacy is required. Previous experience with any command-line program (such as MS-DOS) is beneficial. 4 Days in length. Intermediate Courses o MySQL 5.0 Upgrading and New Features This instructor-led course will provide in-depth knowledge needed to become proficient using MySQL 5.0. This training course will provide quality time both on the topic, hands-on labs and with the expert instructor. Prerequisites: Existing MySQL users who want to become proficient using MySQL 5.0. 3 Days in length. o MySQL for Database Administrators This course covers essential DBA tasks such as, installation and upgrading, user management, disaster recovery, and optimization. In addition, it will prepare students for the MySQL Database Administrator certification. Prerequisites: Some experience with Relational Databases and SQL. 5 days in length. Advanced Courses o MySQL Performance Tuning The MySQL Performance Tuning course is designed for Database Administrators and others who wish to monitor and tune MySQL. This course will prepare each student with the skills needed to utilize tools for monitoring, evaluating and tuning. Students will evaluate the architecture, learn to use the tools, configure the database for performance, tune application and SQL code, tune the server, examine the storage engines, assess the application architecture, and learn general tuning concepts. 4 Days in Length. o MySQL Cluster - Learn how to install and configure the cluster nodes to ensure high availability. Also learn about all of the high availability features that are implemented in the new storage engine for the MySQL Cluster fail-over between storage nodes, network partitioning protocol, two-phase commit and much more. Prerequisites: Attendance to the MySQL for Database Administrators or an equivalent mastery of database concepts, SQL and the MySQL server. 3 Days in length. Note: This is the sole course offering in the Cluster certification (CMCDBA) path. o MySQL High Availability - This course is designed for experienced database administrators and system architects that want to analyze and form a basis of understanding different high availability options, including clustering and replication solutions within MySQL. This course will provide the tools required to make the decision of what high availability solution is appropriate and how to implement a system with the correct design.. 3 days in length.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-13

Developing Dynamic Web Applications with MySQL and PHP


24

Chapter 1 Introduction

1.10 MySQL Website


Everything you ever wanted to know about MySQL and more can be found on our website: http://www.mysql.com. From the home page, you may navigate the web site with the tabs (pull-down menus) across the top, the menu along the left side, and/or the many links on the page.

______________________________________________________________________________________________ Instructor Notes: Do NOT open the website at this time. It will be done later in a lab. However, you may want to ______________________________________________________________________________________________ mention (and perhaps show) now about the MySQL website searching capability; www.mysql.com/<keyword> . ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-14

Developing Dynamic Web Applications with MySQL and PHP


25

Chapter 1 Introduction

1.10.1

MySQL Community Web Page The MySQL Community web page is located at http://dev.mysql.com and is maintained by MySQL AB. This is the main support tool for the MySQL open source community and can provide valuable insight for Enterprise users also. Information such as the following can be found:

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-15

Developing Dynamic Web Applications with MySQL and PHP


26

Chapter 1 Introduction

Product Downloads o MySQL Products are available under the "dual licensing" model. Under this model, users may choose to use MySQL products under the free software/open source GNU General Public License (commonly known as the "GPL") or under a commercial license. ISVs and Resellers, who are embedding and reselling MySQL as part of their own commercial solutions, can purchase a MySQL commercial license. Documentation o The MySQL Reference Manual covers most of the areas of MySQL use. This manual is for both MySQL Community Edition and MySQL Network. If the answer(s) cannot be found from the manual, support can be purchased through MySQL Network, which provides comprehensive support and services. MySQL Network also provides a comprehensive knowledge base library that includes hundreds of technical articles resolving difficult problems on popular database topics such as performance, replication, and migration. Articles o Check out the many articles available regarding specialized uses of MySQL, by the top experts from all over the globe. MySQL Forums o Community and Enterprise Users alike can utilize the MySQL forums to interact with each other and the staff of MySQL AB. The forums are a great way to continue the community support for MySQL and keep both MySQL AB and the MySQL users in constant communication thus making MySQL even better. Mailing Lists o MySQL provides its customers, both community and enterprise users, a way to keep up with the latest updates to MySQL software along with many other MySQL specific issues through the use of mailing lists. Mailing lists are similar to the forums but with the option to receive discussions and information about MySQL through a users local mail client. If a user cannot get an answer for their questions from one of our mailing lists, one option is to pay for support from MySQL AB, which puts the user in direct contact with MySQL developers. MySQL Bugs o Bugs can be reported through the MySQL Bug page within MySQL, search for bugs submitted by MySQL users and MySQL AB staff and view bug statistics. PlanetMySQL Blogs o Find the link to this site containing dozens of high quality articles every week from community and MySQL employees: http://www.planetmysql.org/ . And much more!

______________________________________________________________________________________________ Instructor Notes: Demonstrate the use of the online MySQL Reference Manual. Make sure to stress the use of the ______________________________________________________________________________________________ reference manual throughout the class. If a user cant get an answer for their questions from our website resources, ______________________________________________________________________________________________ one option is to pay for support from MySQL AB, which will puts the user in direct contact with MySQL developers (i.e. MySQL Enterprise). ______________________________________________________________________________________________

Page 1-16

Developing Dynamic Web Applications with MySQL and PHP

Chapter 1 Introduction

Lab 1-A
In this exercise you will review some web pages on the MySQL AB website. Make sure that your web browser window is displayed.

ACTION (You Do)


1. Click in the text area of the Address/Location Toolbar. 2. In the toolbar text area, type: www.mysql.com 3. Click on the Products tab located at the top of the MySQL home page. Scroll down the list to review the various product information provided. 4. Review the details of the new MySQL Enterprise program, by clicking on the Learn More >> link.

COMPUTER RESPONSE / Comments


The URL currently listed will be selected. The MySQL Homepage is displayed. A list of currently available products will appear, with links for further information and downloads.

MySQL Enterprise provides a comprehensive set of enterprise-grade software, support and services directly from the developers of MySQL to ensure the highest levels of reliability, security and uptime. A list of currently available services will appear, with links for further information and downloads. Featured information on this page will be updated periodically. For specific Training sub-topics select one of the links in the sub-menu in the upperleft corner of the page. Featured information on this page will be updated periodically. For specific Certification sub-topics select one of the links in the sub-menu in the upperleft corner of the page. Returns to the top level Services page. Shows the various support programs available.

5. Click on the Services tab located at the top of the MySQL home page. 6. Review the details of the new MySQL Training program, by clicking on the Learn More >> link. 7. From the Training web page, select the Certification link in the sub-menu and review the contents. 8. Click on the Services tab located at the top of the MySQL home page. 9. Review the details of MySQL Support programs, by clicking on the Learn More >> link. 10. Click on the Community tab located at the top of the MySQL home page. 11. Click on the News & Events tab located at the top of the MySQL home page.

The community page contains many links to more information and access to various open communication forums. Shows the latest MySQL happenings, from news stories to upcoming seminars.

______________________________________________________________________________________________ Instructor Notes: Do this lab live along with the students and emphasize that the primary goal of our website is to ______________________________________________________________________________________________ service their needs. Ask them if there are any particular topics they would like to find on the website (that are not ______________________________________________________________________________________________ included in the lab) and you may want to help them find a few items as part of the lab. ______________________________________________________________________________________________

Page 1-17

Developing Dynamic Web Applications with MySQL and PHP


27

Chapter 1 Introduction

1.11 Chapter Summary


This chapter introduced you to MySQL and MySQL AB, the support organization for MySQL. In this chapter, you learned: The details of the MySQL AB Business Model. What MySQL products and professional services are available from MySQL AB. Define and differentiate between Enterprise and Community Which Operating Systems are currently supported. What is available through the MySQL Community web page. What is the MySQL Certification program. Which courses are available to you after this course.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 1-18

Developing Dynamic Web Applications with MySQL and PHP

28

CHAPTER 2
29

LAMP

Developing Dynamic Web Applications with MySQL and PHP


30

Chapter 2 - LAMP

2
2.1

LAMP
Learning Objectives
This chapter provides the knowledge and methods used to verify the correct installations of MySQL and PHP on the web server being utilized. At the completion of this chapter, you will be able to: Explain the LAMP architecture Verify that the Apache Server is installed and running Verify that MySQL is installed and running Verify that PHP is installed and accessible

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-2

Developing Dynamic Web Applications with MySQL and PHP


31

Chapter 2 - LAMP

2.2

LAMP Architecture
The strength of the world wide web and the internet are that they stand upon open standards such as TCPIP, SMTP, UDP, HTTP and the like. This allows a Mac to talk to another systems mainframe and to send email to a windows computer. This open-ness may or may not extend to the tools used to deliver or create content on the world wide web. Proprietary tools such as Macromedia/Adobe FLASH, ADOBE, Cold Fusion, Microsoft IIS are tools developed by companies to generate revenue. An alternative paradigm exists. That is where individuals and companies collaborate in order to help each other to get various tasks done. This is called "open source". Open source software gives an end user the freedom to view and modify the source code. Typically they are free of cost but the main freedom is that the end user can view and modify the source code. This means that talented programmers who find ways to improve the source code can contribute. It means that companies that need a tool, say a webserver, can utilize Apache rather than paying for a commercial tool. In open source we all work together to get our jobs done. The value is in the access to quality tools without restrictions. In closed source products we pay someone else to solve our problems. They may or may not have our best interest in mind, or our needs and the needs for revenue may collide. The Open source tools are Linux, Apache, MySQL and PHP. In many ways they can be used as a replacement or alternative to IDE's such as J2EE, ASP.NET. Linux - This is the operating system (O/S) of the LAMP architecture and serves as foundation for the rest of the applications used in the architecture. Linux, which refers to the Linux kernel that is a Unix-like operating system kernel, can be seen in many different "flavors" of operating system distributions that utilize the linux kernel to include Fedora, Ubuntu, Knoppix, OpenSUSE, etc. The majority of the distributions (along with the Linux kernel itself) is released under the GNU General Public License (GPL) and developed by contributors worldwide. Apache - Apache refers to the Apache HTTP Server that is a web server that can be run on Unix-like systems (Linux for example), Microsoft Windows, Novell NetWare, Mac OS X and other operating systems. The Apache web server has played a major role in the success of the web by being a direct competitor to early proprietary web servers and opening the path for individuals and organizations to place their own "voice" on the web with little to no cost. The Apache Software Foundation, which is a non-profit corporation to support Apache software projects, develops and maintains the actual code (with a large number of open community of developers). The software itself is released under the Apache License which identifies the Apache HTTP Server as free software. MySQL - MySQL refers to the multithreaded, multi-user SQL database management system which has more than 10 million installations worldwide. Supported by MySQL AB, a company which is dual headquartered in Uppsala, Sweden and Cupertino, California, USA maintains the mysql DBMS system and holds the copyright to most of the codebase. The MySQL DBMS acts as the database component that provides the back-end to a large number of the web applications in place today. MySQL has been a large player in such web applications as online stores, social networking sites, wiki's, etc. PHP - PHP refers to the programming language that is used in the design of a large number of dynamic web pages. PHP is a reflective programming language, meaning the program code can be modified in the process of being executed based on its runtime behavior. This is ideal for the dynamic and interactive nature of the web. The rights to the PHP falls under a group called the "The PHP Group" and the ability to use the software is based on the PHP License, which according the Free Software Foundation is a license that identifies itself as being free software.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-3

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

32

2.3

Apache Server
Being one of the components of the LAMP architecture, it is important to ensure that the Apache Server is installed and running on the Linux distribution being used. The easiest and least intrusive way of checking this is by opening a web browser on the local system and attempting to view the localhost web location. If there is a positive response when opening localhost from the web browser, then the Apache HTTP server is installed and running on the system. If the response is a web error, then the Apache HTTP is not running properly or not installed on the system. Downloading the Software The Apache Software Foundation is responsible for maintaining and supporting the Apache HTTP Server. Its website is http://www.apache.org which provides the details associated with the product lines that it offers and further information to install, configure and run the Apache HTTP Server on a wide range of operating systems. For the purpose of this course, the focus will be on installing and executing the Apache HTTP Server on the Linux distribution being used in the classroom environment. Installing the Software Once the files are downloaded to the operating system, it is time to extract the download file to an appropriate location for the server to execute from. In the linux environment, the choice used for the classrooms will be the /usr/local directory. This will be the location for all the software that will be installed in this class. Configuring the Install Script The next step is to configure the Apache HTTPd source tree for the Linux operating system and any additional specific requirements needed. The configuration of the install script is accomplished using the script configure included in the root directory of the distribution. There are multiple installation options that can be manipulated during the configuration. These configuration options are beyond the scope of this class. For class purposes, the default options will be chosen by running just the configure command without any options. Build the Package The next step is to build the various parts which form the Apache HTTPd package by simply running the make command. Due to the fact that the make command will build a base configuration it will take several minutes to compile. The actual time it takes to compile will vary widely depending on the hardware and the number of modules that have been enabled. Once the package has been made with the make command, it is now time to install the package using make install. Once this step is accomplished, a directory called apache2 will be created that will house the apache server files. Configuring The Apache server is configured by placing directives (which pass optional settings into the Apache server) in plain text configuration files. By default, the main configuration file that the Apache server will look for is called httpd.conf. This file is located in the apache2/conf directory by default. The majority of configuration options associated with this file are beyond the scope of this class and the default httpd.conf directives will be used.

Static vs. Dynamic Modules Apache can load static modules or they can be loaded dynamically. Dynamic is more common in the last few years. It takes less time to load a dynamic module. In order to see what modules are installed apache has an info and a status module. We will enable those modules and use them to make sure we have all the tools that we need. Mod status and Mod info display the output as a web page so we will need to make sure that the modules are loaded and that we have configured apache to deliver a "virtual URL " to display the content.

Instructor Notes: It may be more advantageous to show the websites where a person would download the files; ______________________________________________________________________________________________ however, the actual files should be downloaded by you (prior to the start of class) and made available locally to the students. This applies to all the files that will be downloaded for this chapter (Apache, MySQL, PHP). ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-4

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

Starting and Testing the Server To start the Apache server, choose the apache2/bin directory. This directory contains the files associated with executing the components of the Apache server. The Apache server can be started by executing apachectl start from this directory. To test if the Apache server is working on the system, open a web browser on the local system and attempt to open http://localhost. If an error appears, the system is not configured properly and the steps should be repeated to determine the problem. If a web page appears, the server is running properly.

Lab 2-A
In this exercise you will determine if the Apache HTTP Server is currently running on the local operating system. If the Apache HTTP Server is not installed, you will follow the steps required to download and install the latest version.

ACTION (You Do)


1. In your web browser, attempt to open the localhost web page.

COMPUTER RESPONSE / Comments


If http://localhost displays a web page, then the Apache server is installed on your system and no additional steps in this lab are required. However, if an error is returned, complete the remaining steps to install the Apache server on your system. This will open the download page for the Apache HTTPd Server. The downloaded file will take some time to download and patience should be expected. Note: The instructor may have already downloaded this file and made it available in a local file system, check with the instructor before downloading. This will extract the file downloaded in step 3 into the /usr/local directory making a new subdirectory labeled httpd-#.#.#.

2. In your web browser's toolbar text area, type: httpd.apache.org/download.cgi 3. In the best available version section, choose the tar & zipped Unix Source link (httpd#.#.#.tar.gz) and save the file to the /tmp directory. 4. In the /usr/local directory, type the following: tar -xvf /tmp/httpd-#.#.#.tar.gz replacing the #.#.# with the exact file identifier downloaded in step 3. 5. In the /usr/local/httpd-#.#.# directory, execute the following command: ./configure --prefix=/usr/local/ apache2 --enable-mods-shared= most 6. In the /usr/local/httpd-#.#.# directory, execute the following command: make 7. In the /usr/local/httpd-#.#.# directory, execute the following command:

This step configures the Apache HTTPd source tree for your specific operating system with the root directory for the Apache server being the apache2 subdirectory in the /usr/local directory. In addition, the enablemods-shared=most tells the apache install script to build most of the available loadable modules. This step builds the various parts which form the Apache HTTPd install package.

This step will actually install the Apache server install package. Once this step is accomplished, a directory called apache2 should be created in the /usr/local make install directory that houses the apache server files. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-5

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

ACTION (You Do)


8. With the apache server files completed, there are a few configuration options that must be entered into the httpd.conf file before we are completed with the Apache step of the LAMP installation. However, a best practice is to make copies of existing configuration files prior to changing them. In the /usr/local/apache2/conf directory, create a copy of the httpd.conf file by entering the following command: cp ./httpd.conf httpd.conf.bak 9. With the original configuration copied it is time to edit the httpd.conf file using your favorite editor. For this example the vi editor will be used: vi httpd.conf 10. First things that need to be addressed are the modules and their status (will they be loaded). The two modules that need to be loaded (among many) are mod_info and mod_status. You can search for the mod_info module by typing in vi the following: /mod_info.so You can locate the mod_status module in the httpd.config file by typing in vi the following: /mod_status.so 11. The next step is add the "Virtual URL's" for status and info to the httpd.conf file. Locate the end of the file and add the following lines: <Location /info> SetHandler server-info </Location> <Location /status > SetHandler server-status </Location> 12. Save your changes to the httpd.conf and exit the vi program.

COMPUTER RESPONSE / Comments


The original httpd.conf is now copied to httpd.conf.bak giving us the ability to go pack and start over if need be (without having to remember all the changes that we made to the file). In addition, adding components and then testing them before going on to adding the next component is not a bad approach if your configuration files continue to cause you problems.

vi stands for visual editor and is the default editor that comes with the Linux operating systems. This editor will allow us to make modifications to the httpd.conf file and complete the apache server setup. Note: Refer to Appendix B for a simple list of vi commands if you are unfamiliar with this program. If these lines are commented out (the start of the line contains a pound sign:#), please remove the comment. If you do not see this lines then add them. If you do not see mod_info.so or mod_status.so in your modules directory then contact your instructor

The first section is responsible for allowing mod_info's output to be available. mod_info provides a detailed configuration and module information for your server (corresponding to modules, mostly) in display-order that are hyper-linked. The second section is responsible for allowing mod_status' output to be available. mod_status provides a representation of your web server's internal state and the comings and goings of its child processes. The changes are saved to the file.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-6

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

ACTION (You Do)


13. Test the configuration file for typos by typing the following in the /usr/local/apache2/bin directory: ./apachectl configtest 14. Once the configuration test of the httpd.conf file responds with "syntax OK", it is now time to start the server by executing the following command: ./apachectl start 15. Open the web browser on your system and attempt to browse to http://localhost/info and http://localhost/status which refers to the apache server running on your system. 16. Stop the Apache server after ensuring that it is properly configured and running by typing the following command: ./apachectl stop

COMPUTER RESPONSE / Comments


If the response is not "syntax OK" then return to the httpd.conf file and correct the error.

This will start the Apache HTTPd server on your system. Note: If an error is shown after executing this command that says "Could not reliably determine the server's fully qualified domain name ...", simply ignore this error for class purposes. This is stating that Apache does not know what server name to listen for. If both of the web pages come up and provide information about the server, then apache was configured correctly and is executing properly. If an error appears, ask your instructor for assistance. This will stop the Apache HTTPd server on the system. This step is important when installing the next two components of the LAMP architecture.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-7

Developing Dynamic Web Applications with MySQL and PHP


33

Chapter 2 - LAMP

2.4

MySQL Server
Being another of the components of the LAMP architecture, it is important to ensure that the MySQL Server is installed and running on the Linux distribution being used. Downloading the Software MySQL AB is responsible for maintaining and supporting the MySQL Relation Database Server. Its website is http://www.mysql.com which provides the details associated with the product lines that it offers and further information to install, configure and run the MySQL Server on a wide range of operating systems. For the purpose of this course, the focus will be on installing and executing the MySQL 5.1 Server on the Linux distribution being used in the classroom environment. Installing the Software There are multiple methods for installing the MySQL Server on the operating system being used. For Linux, the easiest and least cumbersome is using a non-RPM distribution. These files can be located under the "Linux (non RPM packages) downloads" section. These files are called binary distributions that have already been compiled to work on the operating system that is selected. These files are tar files that have been compressed (tar.gz). Extracting the files is the extent of installing the actual MySQL binaries onto the operating system. Setting the MySQL user The MySQL server should not be run as root but instead should be run as another user whose sole purpose is to execute the MySQL server. This can be accomplished by creating a user called mysql that is assigned to a group called mysql. Once the user is created, all the data directory (/usr/local/mysql/data) should be assigned to this user and group. In addition, the mysql directory should at least be assigned to the mysql group (root can still own the directory). Initializing the MySQL databases There are a few databases that must be initialized prior to running MySQL for the first time. These databases include the mysql database which is used to control the security of all the databases on the server and test database which can be used for testing the server. There is a built in script to accomplish this step (/usr/local/mysql/scripts/mysql_install_db). Starting and Testing the Server With the MySQL binaries installed and the initial databases installed it is time to start the server. MySQL provides multiple ways to start the server, but the safest and most user friendly is using the mysqld_safe script located in the /usr/local/mysql/bin directory. This script should be run as the mysql user by executing the following conditions: /usr/local/mysql/bin/mysql_script -u mysql & After starting the MySQL server, the MySQL client (/usr/local/mysql/bin/mysql) can be run to interface with the server itself. Root Password?

After the MySQL server is started for the first time, it is important to set a root password. MySQL, by default, does not have a password assigned to the root password that is given complete access to all the databases; including the mysql database that controls all the authentication for the databases. To set the root password initially, execute the following command: /usr/local/mysql/bin/mysqladmin -u root password new_password

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-8

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

Lab 2-B
In this exercise you will determine if the MySQL Server is currently running on the local operating system. If the MySQL Server is not installed, you will follow the steps required to download and install the latest version.

ACTION (You Do)


1. To determine if MySQL is installed on your system, enter the following command in the O/S terminal window: whereis mysql

COMPUTER RESPONSE / Comments


A directory will be shown where MySQL is installed (similar to the one listed below) if the system has MySQL installed. mysql: /usr/local/mysql If MySQL is installed already, you can either skip the remaining steps or contact your instructor to provide assistance in removing MySQL from your system so you can have practice in installing MySQL.

2. In your web browser's toolbar text area, type: dev.mysql.com/downloads

This will open the download page for the MySQL Server. Note: Ensure that the downloads panel in the left corner of the page has the 5.1 version of the server selected. If not, click on the 5.1 link under the Downloads section.

3. Choose the Download >> link under the "I Can Do It MySelf" column.

This is the link for the Community Server which will be used for class purposes. The Enterprise Server is the server that is recommended for production use systems, but in the case of this class, we will use the Community Server addition. This link will place you in the Linux (non RPM Packages) section where you will be able to download the MySQL binary distribution. This step will perform the actual download of the MySQL installation files (mysql5.1.#.*.tar.gz). This will extract the file downloaded in step 5 into the /usr/local directory making a new subdirectory labeled mysql-5.1.#.*.

4. Choose the Linux (non RPM Packages) link from the list of available operating system downloads. 5. Choose the download link to the left of the proper operating system that your system is running. 6. In the /usr/local directory, type the following: tar -xvf /tmp/ mysql-5.1.#.*.tar.gz replacing the /tmp/mysql5.1.#.*.tar.gz with the exact file identifier downloaded in step 5 along with the exact location of the download.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-9

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

ACTION (You Do)


7. Create a symbolic link directory to the newly mysql directory just created that will be easier to work with: ln -s mysql-5.1.#.* mysql replacing the mysql-5.1.#.* with the exact file directory name created in step 6. 8. With MySQL installed (accessed though the mysql directory just created), it is time to prepare for running MySQL. The first thing that needs to be done is creating a group that MySQL will run under by typing the following: /usr/sbin/groupadd mysql 9. With the mysql group created, it is now time to create a mysql user assigned to this group by typing the following command: /usr/sbin/useradd -g mysql mysql 10. MySQL initially has no databases installed. This can be corrected by typing the following command in /usr/local/mysql directory: ./scripts/mysql_install_db 11. Now it is time to change the ownership of MySQL directories to ensure a level of security when running MySQL. This is accomplished by typing the following commands: chown -R root:mysql /usr/local/mysql chown -R mysql:mysql /usr/local/mysql/data 12. The following file should be edited to add the mysql library files to the program start-up: cd /etc/ld.so.conf.d echo /usr/local/mysql/lib > mysql.conf

COMPUTER RESPONSE / Comments


This will create a directory called mysql which will be easier to work with when dealing with the MySQL server.

To ensure security with MySQL, it is important to not run the server as root. This step creates a group called mysql that will only be used for running the MySQL server.

This user, mysql, will be the user that the MySQL server will run under.

This script will not only install the mysql and test database, but will also provide additional information on running the MySQL server. These commands provide the ownership changes required to provide a level of security when running the MySQL server.

On most Linux systems, the list of directories automatically searched during program start-up is stored in the file /etc/ld.so.conf. By adding MySQL to this configuration file you assure that its library files are easily accessible.

13. With all the steps completed, it is time to actually start the MySQL server. Type the following command to start the MySQL server: cd /usr/local/mysql ./bin/mysqld_safe -u mysql &

The operating system will display the following information (or something similar) if the server is started: Starting mysqld daemon with databases from /usr/local/mysql/data

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-10

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

ACTION (You Do)


14. Another big issue that is important for security is the root password. By default, there is no root password. This can be corrected by issuing the following command (with training being the new password): /usr/local/mysql/bin/mysqadmin -u root password training 15. To ensure that MySQL is running as expected, type the following command to login to the MySQL client: /usr/local/mysql/bin/mysql -uroot -p 16. At the Enter password: prompt, type in the password that was assigned to the user root in step 14, training.

COMPUTER RESPONSE / Comments


This is a step that is missed by many administrators that install MySQL. By changing the password immediately upon installation, this potential security hole is closed.

The MySQL client is a tool that allows us to interact with the MySQL databases directly. The actual command that was issued basically said that we are logging in as root (-uroot) and want to be prompted for the password (-p). The following lines (or something similar) will be displayed if you were able to login correctly to the MySQL client: Welcome to mysql monitor. Commands end with ; or \g Your MySQL connection id is 2 Server version: 5.1.# MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql>

17. To give you a taste of MySQL, enter the following command in the MySQL client window: SHOW DATABASES;

The following will be displayed showing the databases that are initially installed: +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | test | +--------------------+ The MySQL client window will be closed and the operation system prompt will be displayed.

18. To quit the MySQL client window, type the following command in the MySQL client window: quit;

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-11

Developing Dynamic Web Applications with MySQL and PHP


34

Chapter 2 - LAMP

2.5

PHP
With PHP being the final component of the LAMP architecture to be setup, it is important to ensure that PHP is installed and running on the Linux distribution being used. The majority of this course will be based on PHP and setting up the service correctly at this point will minimize problems in the long run. Similar to the process of installing the Apache server, PHP should be compiled for the server that it will be running on. Downloading the Software The sole implementation of PHP is produced by "The PHP Group" and released under the PHP License. There are many locations in which the source code for PHP can be obtained; however, php.net provides the most current and up to date version. Just like the other components of the LAMP architecture that have been discussed in this course, PHP can be compiled to work on many different platforms. For the purpose of this course, the focus will be on installing and running PHP on Linux. Installing the Software Once the files are downloaded to the operating system, it is time to extract the download file to an appropriate location for the server to execute from. In the linux environment, the choice used for the classrooms will be the /usr/local directory. This will be the location for all the software that will be installed in this class. Configuring the Install Script The next step is to configure the PHP source tree for the Linux operating system and any additional specific requirements needed. The configuration of the install script is accomplished using the script configure included in the root directory of the distribution. There are multiple installation options that can be manipulated during the configuration. These configuration options are beyond the scope of this class. For class purposes, the default options will be chosen by running just the configure command with the basic options associated with the Apache2 server and MySQL. Build the Package The next step is to build the various parts which form the PHP package by simply running the make command. Due to the fact that the make command will build a base configuration it will take several minutes to compile. The actual time it takes to compile will vary widely depending on the hardware and the number of modules that have been enabled. Once the package has been made with the make command, it is now time to install the package using make install. Once this step is accomplished, a directory called php will be created that will house the PHP files. Configuring PHP PHP is configured through an initialization file (php.ini) which can contain multiple options to support the PHP implementation for your server. The most common options to be addressed in this file is the location of the document root for the Apache server and components to add additional layers of security to the implementation.

Instructor Notes: Once the PHP is installed, it is ready for use and does not require any additional start up options. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-12

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

Lab 2-C
In this exercise you will determine if the PHP programming language is currently running on the local operating system. If the PHP programming language is not installed, you will follow the steps required to download and install the latest version.

ACTION (You Do)


1. To determine if PHP is installed on your system, enter the following command in the O/S terminal window: whereis php

COMPUTER RESPONSE / Comments


A directory will be shown where PHP is installed (similar to the one listed below) if the system has PHP installed. php: /usr/local/php If PHP is installed already, you can either skip the remaining steps or contact your instructor to provide assistance in removing PHP from your system so you can have practice in installing PHP.

2. In the toolbar text area, type: http://www.php.net/downloads.php

This will open the official download page for the PHP programming application.

3. Under the Complete Source Code heading, choose the link for the latest PHP (tar.gz) file. 4. Choose the best (usually in close physical proximity) link to download the file and save the file to the /tmp directory. 5. In the /usr/local directory, type the following: tar -xvf /tmp/ php-5.#.#.*.tar.gz replacing the /tmp/php-5.#.#.*.tar.gz with the exact file identifier downloaded in step 4 along with the exact location of the download. 6. In the newly created directory, issue the following command: ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2 /bin/apxs --with-mysql=/usr/local /mysql --withmysqli=/usr/local/mysql/bin/mysql _config

This link will open a list of mirror sites for the download of the required file. This step will perform the actual download of the MySQL installation files (php5.#.#.*.tar.gz). This will extract the file downloaded in step 5 into the /usr/local directory making a new subdirectory labeled mysql-5.1.#.*.

This step configures the PHP source tree for your specific operating system with the root directory for PHP being the php subdirectory in the /usr/local directory. In addition, the --with-apxs2 and --with-mysql tells the configurations script where the other components of LAMP are located.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-13

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

ACTION (You Do)


7. When the configuration script finishes, execute the following command: make 8. When the make script finishes, execute the following command: make install 9. In the /usr/local/php-5.#.#, execute the following command to create the default preconfigured initial setup: cp php.ini-recommended /usr/local/php/lib/php.ini 10. In the php.ini file just created, edit the file (using a program such as vi) to change the doc_root setting: doc_root="/usr/local/apache2/htdocs" 11. Another configuration option that should be changed in the php.ini file created in step 9, is allowing file uploads using PHP by changing the following setting: file_uploads=On 12. Change the follow directives: error_handler = E_ALL | E_STRICT display_error = On

COMPUTER RESPONSE / Comments


This step builds the various parts which form the PHP install package. This step will actually install the PHP package. Once this step is accomplished, a directory called php should be created in the /usr/local directory that houses the PHP files. There are multiple pre-configured settings for a PHP install that you can use as an initial setup. php.ini-recommended is the most secure and rightfully identified in the name as the recommended one. This location identifies the document root directory for the local Apache web server.

If there is no need to upload files, this should be set to Off. By turning Off the capability to upload files using PHP, you set PHP to safe mode and place an additional level of security on the server. In this training, we will use the file upload function and must have this set to On. The error_handler setting ths will provide the most warnings and notices. Code that run cleanly with this setting has a far greater likelihood being portable. The display_error should be set to off for a production server. The changes are saved to the file.

13. Save your changes to the php.ini file and exit the editing program you were using to make the changes. 14. In the /usr/local/apache2/conf directory, edit the httpd.conf file. Using the tools of vi, locate the end of the DirectoryIndex section and modify the configuration line to read: DirectoryIndex index.html index.html.var index.php

This will ensure that files named index.html.var and index.php will be identified as the default pages for your html directories along with the standard index.html. Note: Anytime changes are made to the httpd.conf file, it is important to comment what changes took place to include the date, by whom, what was modified/added and why. These comments should be entered near the changes that were made.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-14

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

ACTION (You Do)


15. After making the changes in step 13, search for the AddType configuration options under the mime_module section of the configuration file. Locate the end of this section and add the following line: AddType application/x-httpd-php .php 16. Save your changes to the httpd.conf and exit the vi program.

COMPUTER RESPONSE / Comments


This setting will ensure that any time the apache server is asked to execute a file with a .php extension it will use the proper server components to manage those files.

The changes are saved to the file. Any requests to execute PHP files on the apache server will now be completed.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-15

Developing Dynamic Web Applications with MySQL and PHP


35

Chapter 2 - LAMP

2.6

Putting It All Together


Now that all the components of the LAMP architecture are set up, it is time to test each of the components and verify that everything is working correctly. Restarting Apache Apache was shutdown during the installation of MySQL and PHP and should be started back up to provide the web services necessary to test the PHP installation. To start the Apache server again, choose the apache2/bin directory. This directory contains the files associated with executing the components of the Apache server. The Apache server can be started by executing apachectl start from this directory. Testing PHP With the Apache server back up an running, it is time to test the installation of PHP on the server. This is accomplished by creating a test PHP file in the /usr/local/apache2/htdocs directory. This file (which is usually called test.php) will contain a PHP command (<?php phpinfo(); ?>) that will display all the configuration information associated with the local PHP installation. Automatic Starts of Apache and MySQL Up to this point, Apache and MySQL were manually being started and would need to continue to be manually started every time the operating system was restarted. This is not the most effective approach for many reasons, least of them being they are easy to forget at start up time when needing to be started manually. Linux (along with practically every other operating system) has the capability to start applications when the operating system is loaded (during planned or unexpected restarts). In Linux, this is accomplished by placing a copy of the start up executable files into the /etc/init.d directory. In addition, some additional steps such as making the new files executable and executing a Linux tool (update-rc.d) to ensure that all the proper links on the operating system are made to ensure each component is started when the operating system starts up. Updating the Exectuable Paths

We now have apache and all the associated executables in our /usr/local/apache2/bin directory. Our life would be easier if we could type apachectl instead of the full path over and over again. In addition, the same is true for running the mysql client. In order to do that we edit an environment variable called path. A number of files are read when we log in. One of them is /etc/profile but that requires that we login to activate. /etc/bash.bashrc is a good place, each new console that is launched reads /etc/bash.bashrc and thus adding the following lines to our /etc/bash.bashrc file will prevent us from needing to provide the full path everytime we want to execute a command from these directories: PATH=${PATH}:/usr/local/apache2/bin:/usr/local/mysql/bin Once that file is updated and saved, any new terminal windows (consoles) that start-up will have those in the path allowing mysql and/or apachectl to called without the paths preceding them.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-16

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

Lab 2-D
In this exercise you will complete the final steps of setting up the LAMP architecture along with testing the setup. In addition, you will configure the operating system to start up MySQL and Apache automatically when it starts up.

ACTION (You Do)


1. In the /etc/ directory, edit the following file: vi bash.bashrc

COMPUTER RESPONSE / Comments


There are a couple of files that modify your PATH. They all work but some are read all the time for everyone, some are read for each user. /etc/bash.bashrc only works for bash but it is automatic when a console is launched, no global logout required (unlike the profile files). The path for the apache server and the MySQL server binary directories is added to the path preventing us from needing to precede each command with the full path. This will give you access to using the "path-less" approach.

2. Locate the end of the file and add the following and then save and close the file: PATH=${PATH}:/usr/local/apache/bin: /usr/local/mysql/bin 3. To be able to use the "path-less" approach to executing apache and mysql commands, shut down the current terminal window and open a new one. 4. Execute the following command (from any directory due to our PATH having the binary directory of Apache): apachectl start 5. In the document root directory of Apache, located at /usr/local/apache2/htdocs, create a new file called test.php containing the following line of code: <?php phpinfo(); ?> Close and save the file. 6. In your web browser, call up the following URL: http://localhost/test.php 7. In the operating system terminal window, copy the mysql.server file to the /etc/init.d directory to ensure that MySQL will start when the operating system starts: cp /usr/local/mysql/ support-files/mysql.server /etc/init.d/mysql

This will restart the Apache server.

This file will display all the configuration options of PHP when called from the http://localhost directory in the web browser.

This will display multiple configuration options showing that PHP, Apache and MySQL are working. This step will copy the MySQL startup file to the /etc/init.d which is a directory containing initialization and termination scripts for changing init states.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-17

Developing Dynamic Web Applications with MySQL and PHP

Chapter 2 - LAMP

ACTION (You Do)


8. Add the ability for the new file in the /etc/init.d directory to be executed: chmod +x /etc/init.d/mysql 9. To complete the process of MySQL being started when the operating system is started, execute the following command: chkconfig -add mysql 10. For Apache, the process of ensuring that the web server starts up on the operating system start up is similar to MySQL. The first step is to make a copy of the apachectl executable in the /etc/init.d directory: chkconfig -add httpd 11. Add the ability for the new file in the /etc/init.d directory to be executed: chmod +x /etc/init.d/httpd 12. To complete the process of MySQL being started when the operating system is started, execute the following command: update-rc.d httpd defaults 13. At this point, you can shut down your operating system and restart it to check to see if the LAMP architecture starts up as expected.

COMPUTER RESPONSE / Comments


This will give the new file created, /etc/init.d/mysql to be executable thus allowing it to execute when the operating system starts up. update-rc.d is a utility (on Debian operating systems) that creates all the appropriate links to ensure that a file is executed on start up. This step will copy the Apache startup file to the /etc/init.d which is the same directory where the MySQL startup script was placed.

This will make the new file created ( /etc/init.d/httpd) to be executable thus allowing it to execute when the operation system starts up. update-rc.d will create all the appropriate links to ensure that httpd is executed on start up.

Once you have restarted your operating system, complete step 3 to test if everything is working.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-18

Developing Dynamic Web Applications with MySQL and PHP


36

Chapter 2 - LAMP

2.7

Chapter Summary
In this chapter, you have learned to: Explain the LAMP architecture The acronym LAMP stands for a group of independent open-source software and tools that when used together allow for the execution, development and deployment of dynamic websites and servers. The tools used reflect the acronym name: Linux, Apache, MySQL and PHP. Being one of the components of the LAMP architecture, it is important to ensure that the Apache Server is installed and running on the Linux distribution being used. MySQL AB is responsible for maintaining and supporting the MySQL Relation Database Server. Its website is http://www.mysql.com which provides the details associated with the product lines that it offers and further information to install, configure and run the MySQL Server on a wide range of operating systems. The sole implementation of PHP is produced by "The PHP Group" and released under the PHP License.

Verify that the Apache Server is installed and running

Verify that MySQL is installed and running

Verify that PHP is installed and running

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 2-19

Developing Dynamic Web Applications with MySQL and PHP

37

CHAPTER 3
38

PHP FOUNDATIONS

Developing Dynamic Web Applications with MySQL and PHP


39

Chapter 3 - PHP Foundations

3
3.1

PHP FOUNDATIONS
Learning Objectives
This chapter provides the foundations knowledge necessary to utilize the basic components of PHP to build more complex web applications. At the completion of this chapter, you will exhibit strong knowledge of PHP foundations by being able to: Delimit PHP code within HTML Comment PHP code Construct Feedback to users through tool interfaces and requested responses Utilize the Data Types available in PHP Utilize Key Control Statements Develop Reusable Code with user defined functions

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-1

Developing Dynamic Web Applications with MySQL and PHP


40

Chapter 3 - PHP Foundations

3.2

Delimiting PHP Code


PHP was originally designed to be used in conjunction with a web server, and in the case of the LAMP architecture, the Apache Web Server. PHP applications are designed embedding PHP scripts within a web page along with its HTML. Unlike standard HTML pages which are sent directly from the web server to the end user, PHP files are first interpreted by the PHP application which then converts the PHP script into another form for display. This process eliminates the end user from being able to see the original PHP script that was embedded in the HTML and provides true interaction in HTML files. This process is similar to proprietary applications such as ASP and Coldfusion; however, PHP is Open Source and crossplatform. PHP Tags PHP scripts are distinguished from the HTML scripts by using delimiting characters that tell the server to execute the PHP application to interpret that which is contained in the code. There are four ways to accomplish this; however, the first two listed below are the safest for portability and conflict prevention: Default Syntax - The default syntax is starting the PHP script with <?php and closing out the script with ?>. The following example demonstrates how this would look within HTML code: <html><head><title>PHP Default Syntax</title></head> <body> <h3>PHP Default Syntax</h3> <?php print "This is an example of using PHP Default Syntax"; ?> </body></html> Script Syntax - Due to limitations with certain HTML editors, PHP added the ability to support a mainstream delimiter variant, <script>. The following example demonstrates how this would look: <script language="php"> print "This is an example of using PHP script delimiting syntax"; </script> Short Tags - Due to the fact that many programmers are interested in minimizing the amount of code that needs to be written to accomplish a task, PHP implemented a shorter delimiter syntax to support this desire. Instead of needing to type <?php to start the PHP script, programmers can simply type <? to start the PHP script. The following example demonstrates how this would look: <? print "This is an example of using PHP Short Tag Syntax"; ?> ASP-Style - There are many PHP programmers that have experience with other similar programming languages, such as ASP. ASP delimits code using <% and %>. PHP has provided support for this type of delimiting. The following example demonstrates how this would look: <% print "This is an example of using ASP-Style delimiting syntax"; %>

Instructor Notes: Short-Tag delimiters may be convenient, but they can clash with XML and XHTML. The Default Syntax is the type of delimiting that will be used throughout this course and the one that should be recommended. Short tags are also discouraged by the PHP community, PHP developers and Zend. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-2

Developing Dynamic Web Applications with MySQL and PHP


41

Chapter 3 - PHP Foundations

3.3

Comments
When it comes to commenting code, the consensus is it is necessary but the reality is it rarely is done. It has been said that commenting code is like cleaning the bathroom - no one ever wants to do it but a clean bathroom creates a more pleasant experience for all that will need to use it. There are many types of commenting strategies with each having advantages and disadvantages over each other. The key is to comment, how that is accomplished is best worked within a team environment and calls for a great deal of flexibility. The following are types of typical commenting that should be considered along with how they would be implemented inside of PHP code: Code Commenting This form of commenting is not considered traditional commenting (in the sense of creating remarks to support the code) but is closer related to good programming design principles. This best practice approach to coding involves using coding names that describe the action that is taking place. $MarriageDate = "July 14, 1970"; function deleteOrder (orderID, actionDate); These examples show that the variable or function name give a description of what is being performed. Before abbreviating any code identifiers, make sure that they are descriptive enough so that others who would need to read the code would understand their meaning upon first glance. Any time that needs to be devoted to deciphering a given naming convention is clearly a waste of time and should be considered over any advantage of minimizing the extra key strokes required by the initial programmers. InLine Commenting The most basic form of commenting is that which is referred to as inline or single line commenting. This type of commenting has its history in C++ and has become the standard approach to commenting for many programmers (when they comment). PHP supports this type of commenting by using two consecutive forward slashes (//) preceding any comments added. $MarriageDate = "July 14, 1970"; // Official Marriage Date
// This function will provide the code required to delete an order

function deleteOrder (orderID, actionDate); With inline comments, there is no need to delimit the comments conclusion, the carriage return (\n) performs that action. Shell Syntax InLine commenting can also be accomplished by using the pound sign (#) versus the two consecutive forward slashes (//) preceding any comments added. Both are acceptable and work interchangeably; however, for consistency one style should be chosen over the other. Switching back and forth between the two styles is acceptable but is not a best practice when others are reading your code.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-3

Developing Dynamic Web Applications with MySQL and PHP Muliple-Line Commenting

Chapter 3 - PHP Foundations

It is possible to use inline commenting to create a more verbose and descriptive comment; however, there is an alternative when a comment requires the use of multiple lines. By preceding comments with a forward slash followed by an asterisk (/*) and then closing out the comments with an asterisk followed by a forward slash (*/) multiple lines of comments can be added to the code. /* Script General Information File Name: default.php Creator: Joe Smith, +1(313) 443-4433, joe@smith.com Date Created: 2007/04/11 Purpose: The default script for all scripts created by Joe Smith Last Update: 2007/05/01 */ As shown here, this type of commenting is extremely useful where the comments do not directly correlate with any component of the code, but the code in general. HTML Comment Tag The commenting types up to this point addressed the commenting capabilities in PHP code; however, due to the fact that PHP code is embedded in HTML code it is useful to understand HTML's commenting capabilities. In HTML, commenting is available by creating a comment tag which consists of a less than character followed by an exclamation point and two dashes (<!--) and then closed with two dashes and a greater than symbol (-->). <!-- The following PHP Code produces the order id that will be displayed to the end user --> <?php $OrderID = date(Ymd)."110"; echo "The order number for this order is ",$OrderID; ?> This type of commenting can be useful; however, unlike PHP commenting, that will not be visible to the end user when the web page is displayed, HTML commenting can be seen in the source of the web page.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-4

Developing Dynamic Web Applications with MySQL and PHP


42

Chapter 3 - PHP Foundations

3.4

Construct Feedback
The strength of the web has been the ability for practically anyone to provide information (accurate or not) to anyone who is interested in viewing the web pages that contain that information. With HTML, the static nature of the information being displayed limits the amount of true customization that can be provided; however, PHP provides truly dynamic content by creating custom content each time the web page is displayed. To accomplish this display of information, PHP has four functions that make this happen: print() - This statement is designed to provide user feedback; in other words, this function "prints" content to the HTML code which in turn will be displayed on the web page when called. The print() function can display both raw strings and variables. <?php
print('<p>This is the standard use of the print function.</p>'); print '<p>However, the parentheses are not necessary.</p>'; $var = "print"; print "<p>Variables can also be included with the $var function.</p>"; print '<p>Another way to add a variable to a ' . $var . ' function is to concatenate it to the strings</p>';

?> As shown above, there are multiple ways to use the print function. In addition, breaking the function components across multiple lines is acceptable. The function will continue to read the components until it reaches the semi-colon delimiter (;) which tells the function to complete the process. echo - The echo function is similar to the print function in that it can "print" content to the HTML code; however, it can not be used in more complex expressions because it returns a void versus the print function which will return a boolean value. Except for this difference, the echo function is no different than the print function. With that thought in mind, many programmers choose to just use the print function to prevent this limitation as they advance in their programming skills. <?php echo '<p>This is the standard use of the echo function.</p>'; $var = 'echo'; echo "<p>The $functionType function can also use embedded variables.</p>";
echo '<p>However, when concatenating with the ', $functionType,

' function, it is best to use commas to concatenate the strings</p>'; ?>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-5

Developing Dynamic Web Applications with MySQL and PHP


43

Chapter 3 - PHP Foundations

printf() - The printf function performs the same function as the print command with the exception that there is greater control over the formatting of the "printed" text. The printf function works from the standard print approach for "printing" text to HTML: <?php
printf('<p>This is the standard use of the printf function</p>');

?> Of course, the above demonstration does not add any value to the standard print function. But the printf function does not stop there, the following demonstrations show how the format argument can be included to provide a level of formatting to the strings referenced in the printf function: <?php printf('<p>%d Euro = $%01.2f US Dollar</p>', 1, 1.3); printf('<p>My %s paid $%01.2f for my $s</p>', 'Mother', 23.4, "Dog");
printf('<p>However, my %3\$s paid $%2\$01.2f to get away from my

%1\$s</p>', 'Mother', 100.3, 'Dog'); printf('<p>%11s</p>', 'Long text can be limited to a certain number of characters, in this case 11.'); ?> A complete list of supported type specifiers is located in Appendix D. In the case of the third printf function listed above, the location of the string argument can be chosen by placing the location (#$) with the format type. In the case of %3\$s, the third argument was selected and formatted as a string. The reason for the escape character (\) preceding the dollar sign ($) is to ensure that it was considered part of the formatting versus an actual dollar sign as used in the first printf function. sprintf() - The sprintf function performs the same functions as the printf function except it stores the result of the function into a variable. <?php $orderTotal = sprintf('$%01.2f', 123.456); print "The order total is $orderTotal"; ?>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-6

Developing Dynamic Web Applications with MySQL and PHP

Chapter 3 - PHP Foundations

3.5

PHP Data Types


A data type identifies the characteristics that the assigned data will be interpreted by when interacting with the PHP programming language. When a value is assigned a specific data type, the PHP interpreter will work with the data based on the expected type of data it is. For example, 27654 could be considered a numeric data type or it could be considered a string data type, such as in the zip code for a customer. Even though you could perform mathematical equations on the zip code, it would make no sense to do so. Thus, zip codes, even though they look like they would be numeric numbers should be identified as a string data type to eliminate problems such as zip codes that start with zero (ex. 08102). Assigning the correct data type to the expected value is an important part of working with PHP. There are three categories of data types in PHP: Scalar, Compound and Special.

44

3.5.1

Scalar Data Types


A scalar data type is identified as being able to hold one value at a time. In PHP, there are four data types that fall into this category.

Australia
$Country

22
$Temperature

Boolean - A boolean value is a truth value, either 'true' or 'false', often coded 1 and 0, respectively. When a value is assigned the Boolean data type, there are only two responses that the value can be assigned: True (1) or False (0). If a value is assigned anything other than these two values, it will default to True (1). <?php $Wealthy = false; // $Wealthy is false $Wealthy = 1; // $Wealthy is true $Wealthy = 5; // $Wealthy is true $Wealthy = -1; // $Wealthy is true $Wealthy = 0; // $Wealthy is false ?> Integer - An integer is a whole numeric data type (meaning it does not contain any fractions) that can be set to decimal (base 10), octal (base 8) or hexadecimal (base 16). The following demonstrate some of the values that can be assigned the numeric data type: <?php $Temperature = 22; // $Temperature is an integer $x = -45672; // $x is an integer number $y = 0642; // $y is an integer number (octal) $z = 0x5E5B; // $z is an integer number (hexadecimal) ?> The maximum number that can be assigned to an integer is based on the system. 32 bit systems have a maximum signed integer range of -2147483648 to 2147483647. The maximum signed integer value for 64 bit systems is 9223372036854775807. Any value that exceeds the maximum integer size will be assigned the float data type.

Instructor Notes: For integers, if running a 32bit OS on a 64bit CPU, the max integer value will still be 2147483647. It really has more to do with the compilers, math libraries and OS limitations as well as those of ______________________________________________________________________________________________ the cpu type. Note to consider when discussing data types as it will relate to MySQL: PHP always interprets anything returned from mysql as strings. This means that any result returned from mySQL is not truncated nor ______________________________________________________________________________________________ converted because PHP interprets it a string not an integer. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-7

Developing Dynamic Web Applications with MySQL and PHP

Chapter 3 - PHP Foundations

Float - Floating point numbers are any number that has a fractional component or exceed the integer maximum values. This data type is also referred to as floats, doubles or real numbers. Floats are used to represent such numbers as monetary values, distances, weights, scientific notations and a host of other values: <?php $TotalCost = 67.25; // $TotalCost is a float
$Distance = 4.5e5; // $Distance is a float equal to 450000

$Weight = 92.0; $Diff = 2.34E+12; ?>

// $Weight is a float // $Diff is a float (2340000000000)

The size of a floating point number is dependent by the system being used. In addition, floating point numbers are not as accurate as integer numbers when it comes to precision. Even simple numbers like 0.2 and 0.17 can not be converted into their binary equivalents without a loss of precision. With that said, floating point numbers should never be used in comparison operations without building in logic such as rounding numbers prior to the comparison operation or using a tolerance value that would be an acceptable difference between the compared values for comparison operations. String - A string data type is a series of characters that are associated with each other in a defined order. There is no limit to the length of a string data value. The following represent some of the values that can be assigned to a string data type: <?php $Name = 'Jose Vargs'; // $Name is a string $Value = '45.20'; // $Value is a string $Location = "subway\n"; // Contains a character return $x = "This is a 'test'"; // $x is a string $Chapter = '1.2.4' // $Chapter is a string ?> The characters that can be used in PHP string data types are limited to the ISO 8859-1 or Latin-1 character set. This character set allows for 256 (the size of a byte) different possible characters (191 of them that are actually printable); however, there is support in PHP to encode strings to the UTF-8 standard (UTF-8 is a standard mechanism used by Unicode for encoding wide character values into a byte stream).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-8

Developing Dynamic Web Applications with MySQL and PHP


45

Chapter 3 - PHP Foundations

3.5.2

Compound Data Types


A compound data type allows for multiple values to be associated with a single entity. The primary purpose of a compound data type is to act as containers for other kinds of data. In PHP, there are two types of data types that fall under into this category. France 3 Arrays - These are a series of like values Germany 13 $Position 2 c that are assigned to an individual variable Russia 10 $Country 1 $Position b with each individual value in the array being Australia 22 $Country $Position a 0 referenced with a unique identifier. Once $Country $Temperature these values are stored into an array, it is possible to retrieve individual values or to perform multiple actions against the stored values. The following demonstrates the storing and retrieval of an array set:
<?php $Country[0] = "Australia"; // Australia is the first(0) value $Country[1] = "Russia"; // Russia is the second(1) value $Country[2] = "Germany"; // Germany is the third(2) value $Country[3] = "France"; // France is the fourth(3) value // The following will display: Let's go to Germany! print "Let's go to $Country[2]!"; ?>

The above example could be written less explicitly:


<?php $Country = array("Australia", "Russia", "Germany", "France"); print "Let's go to $Country[2]!"; ?>

Rather than using numeric identifiers, array identifiers can be more meaningful when created as in the following examples:
<?php $Capital["Australia"] = "Canberra"; $Capital["Russia"] = "Moscow"; $Capital["Germany"] = "Berlin"; $Capital["France"] = "Paris"; print "The capital of Russia is ".$Capital["Russia"]."!"; ?> <?php $Capital = array( "Australia" => "Canberra", "Russia" => "Moscow", "Germany" => "Berlin", "France" => "Paris"); print "The capital of Russia is ".$Capital["Russia"]."!"; ?>

Instructor Notes: As a bonus further practice at the end of this chapter, the students will be asked to create a multi-dimension array. This of course is a bonus and can be skipped; however, if you wish you can briefly ______________________________________________________________________________________________ describe that PHP does not expressly handle multi-dimension arrays but that it is possible with a little creative coding. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-9

Developing Dynamic Web Applications with MySQL and PHP

Chapter 3 - PHP Foundations

Object - The data type Joe Smith referred to as an object is Contact 321 E. Main Street the key to the object- 113-45-6788 Information Washington, NC 27784 oriented programming paradigm. The object, can be thought of as a "black box" in which information is sent into it, processed and a result is sent out. The developer has no need to know anything about the internal workings of the code thus giving power to the idea of creating and using objects of already-existing code. Up to this point in the discussion of data types, there has been no need to explicitly declare a data type. PHP determines the data type based on the value that is being stored. However, objects must be explicitly declared. This declaration, which includes the object's characteristics and behavior, takes place within a class. The following is an example of an object declaration:
<?php class respect { private $name; function setRespect($name) { $this->name = 'Mr./Ms. '.$name; print $this->name; } } $boss = new respect; $boss->setRespect("Jane Riker"); ?>

In this simple object example, the result of all this coding is a proper title being placed in front of the boss' name. However, this object could be reused over and over again throughout the remained of the application:
<?php $assistant = new respect; $assistant->setRespect("Wes Picard"); ?>

Instructor Notes: This may or may not be the first time the students are seeing object-oriented programming. However, this is not the place to go into a great deal of discussion on object-oriented programming. Later chapters will address such things as encapsulation, inheritance and polymorphism but this section is designed to be a very ______________________________________________________________________________________________ high level introduction. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-10

Developing Dynamic Web Applications with MySQL and PHP


46

Chapter 3 - PHP Foundations

3.5.3

Special Data Types


In almost every programming language, there are data types that serve a distinct purpose but do not associate with any other data type. These data types are usually grouped together based on their independence from any other grouping method. PHP is no exception to this truth; thus the reason that there is a data type heading called special. The two data types that fall under this heading are: Resource - One of the benefits of using PHP is its ability to interact with some external data source: databases, files, network streams, etc. To utilize these external data sources, PHP must create handles that are named when a successful connection is initiated. These handles continue to be the main point of reference for any communication that takes place. When the communication process is completed, the handle is destroyed and the connection is terminated. These handles fall under the resource data type.
<?php $dbLink = mysql_connect ("localhost","root","training") or die("Could not connect to MySQL server"); $query = "SHOW TABLES FROM INFORMATION SCHEMA"; $result = mysql_query($query); While ($row = mysql_fetch_array($result)) { print row[0]."<br>"; } mysql_close(); ?>

In the example above, the $dbLink variable is assigned a resource data type based on the action that is taking place (connecting to the local MySQL database server). If $dbLink was referenced directly, a reference to a resource id would be returned. Null - The term Null is a perplexing concept that is surrounded by a lot of confusion. Null does not mean a blank space or zero; it truly means nothing or no value. In PHP, a variable is identified as a Null data type when: The variable has not been set to any predefined value; thus it has no value. The variable has been assigned the explicit value of Null.
<?php $default = Null; ?>

The variable has been erased using the function unset().


<?php $SSAN = '112-34-5677'; unset($SSAN); ?>

Instructor Notes: This resource data type example shows the basic structure of connecting to a MySQL server, performing a query and then closing the connection to the MySQL server. Of course, this is only a minimal demonstration of the power of MySQL and PHP and the remainder of this course will be designed to expand ______________________________________________________________________________________________ upon this minimal demonstration. Any additional discussion surrounding this code should be held off until ______________________________________________________________________________________________ directly dealt with by the course content. Null can cause lots of confusion for new people to databases and/or programming. It may be wise to spend a ______________________________________________________________________________________________ little bit of time explaining this concept more if there are students still confused. ______________________________________________________________________________________________

Page 3-11

Developing Dynamic Web Applications with MySQL and PHP


47

Chapter 3 - PHP Foundations

3.6

Flow Control Statements


Flow control statements, or instructions, when executed redirect the normal sequence of the original program execution, or the execution logic. When discussing flow control, the reference is to a single thread of execution which is dependent upon instructions that are executed one at a time. Within PHP, two categories of flow control statements can be identified: Conditional these statements alter the normal sequence of the original program execution based on the value of an expression. These expressions can be any expression that is usable within MySQL stored routines and return a value. In MySQL, conditional flow control statements are represented in the if and switch statements. Iterative - these statements provide for the repeated processing of commands based on a condition that must be met. The most common reason to use iterative statements or instructions within a LAMP architecture is to process all the returned rows of a MySQL SELECT statement. Other reasons for an iterative flow control statement to be setup in PHP include: o o Executing more complex mathematical algorithms Processing an external file by looping through each record in that file

In PHP these are represented in the while, do...while, for and foreach statements.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-12

Developing Dynamic Web Applications with MySQL and PHP


48

Chapter 3 - PHP Foundations

3.6.1

if ... else ... elseif


In most programming languages, including PHP, the if statement is the most basic of all choice flow controls or conditional constructs. The syntax resembles that which is listed below:
if (test_condition1) { ... -- statements that execute if test_condition1 is True } else if (test_condition2) { ... -- statements that execute if test_condition2 is True } else { ... -- statements that execute if all preceding test_conditions are False or Unknown }

The minimum that is required for an if statement to be valid is if (test_condition) { ... }. However, a test_condition can result in three different returned values: o True - the statements enclosed within an if condition (or else if) will be executed when the expression results in a true condition. In the case of a numeric value expression (or a value that PHP perceives as numeric), the statement is considered true if the returned results is an absolute value of 1 or greater (this would include positive and negative values). False - when an expression results in a false condition, the statement enclosed is bypassed. A false condition in a numeric value expression (or a value that PHP perceives as numeric) when the returned result is zero (0). Unknown - when an expression can not be evaluated to either a true or false condition, SQL returns an unknown (or null) condition. Most errors in stored routines stem from not developing guards to manage null conditions. The following example demonstrates a common error that can result in misleading and inaccurate results:
<?php $currentDate = time(); if (strtotime($_POST['DateEntered']) > $currentDate) { echo 'That date is in the future'; } elseif (strtotime($_POST['DateEntered']) < $currentDate) { echo 'That date is in the past'; } else { echo 'That is today'; } ?>

In the event that the date is equivalent to today's date or if the date entered can not be evaluated (an unknown condition), the response will be the same 'That is today'. This of course is not an accurate statement and would result in an inaccurate response to the purpose of this date check.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-13

Developing Dynamic Web Applications with MySQL and PHP

Chapter 3 - PHP Foundations

Due to an expression having the ability to return any of these three results (True, False or Unknown), it is crucial to ensure that your coding reflect each of these possibilities. In addition, to addressing this threevalued logic in your if statements (and other flow control statements), there are a number of ways to actually format your statements. The following are all equivalent to each other and will be read by PHP identically:
<?php $currentDate = time(); if (strtotime($_POST['DateEntered']) > $currentDate) { echo 'That date is in the future'; } elseif (strtotime($_POST['DateEntered']) < $currentDate) { echo 'That date is in the past'; } else { echo 'That is today'; } ?> <?php $currentDate = time(); if (strtotime($_POST['DateEntered']) > $currentDate) { echo 'That date is in the future'; } else if (strtotime($_POST['DateEntered']) < $currentDate) { echo 'That date is in the past'; } else { echo 'That is today'; } ?>

Coding Preference As seen here, PHP is very flexible in the format in which the code is actually entered. Any combination of formats can be utilized; however, the most important thing to remember is consistency and a format that works best not only for yourselves but also for others who may have to review the code in the future. Formatting can be a small issue that presents large problems if not discussed and formalized from the very beginning of a project.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-14

Developing Dynamic Web Applications with MySQL and PHP


49

Chapter 3 - PHP Foundations

3.6.2

Switch
The switch statement provides a means of developing complex conditional constructs. The switch choice works on the principle of comparing a given value with specified constants and acting upon the first constant that is matched. If the constants form a compact range then this can be implemented very efficiently as if it were a choice based on whole numbers.
switch(variable) { case option1: -- statements that execute if option1 is equal to variable break; case option2: -- statements that execute if option2 is equal to variable break; default: -- statements that execute if none of the case options matched the variable }

The switch statement is grouped with the if statement based on its logic and the similarities between the two choices. Anything that a switch statement can do, an if statement can also do and vice-versa. In either case, when a condition is found to be TRUE all other choices are ignored (if properly coded with break statements). This can lead to some very interesting coding issues and requires the programmer to see through the process to decipher the error. The following is an example of using the switch statement:
<?php switch($state) { case 'NY': $tax_rate break; case 'TX': $tax_rate break; case 'VA': $tax_rate break; default: $tax_rate ?>

= .05;

= .10;

= .20;

= .0;

Instructor Note: As stated earlier, the if and switch statements are very similar in their capabilities, readability and logic, so when is one better than the other. This question can be best addressed by personal preference; however, there are some fundamental issues that may make the decision more straightforward than that: - Familiarity - if is a more familiar construct for most programmers and it ability to evaluate multiple expressions based on multiple variables tends to be easier to follow and understand. - Readability - switch is slightly more readable when a single expression is being evaluated against a range of values that are static and well-defined. - Consistency - the advantages that one has over the other is minimal and the big question is going to be which ______________________________________________________________________________________________ one is more comfortable to use. Once that decision is made stick with it as much as humanly possible. One of ______________________________________________________________________________________________ the unnerving things that a programmer can do for those that have to follow his work (for a number of reasons including the ultimate departure) is to be inconsistent in your coding style. Swapping back and forth between ______________________________________________________________________________________________ conditional flow statements on a whim with no rhyme or reason is probably the biggest reason to stick with one ______________________________________________________________________________________________ style over another.

Page 3-15

Developing Dynamic Web Applications with MySQL and PHP


50

Chapter 3 - PHP Foundations

3.6.3

While
The while function is the simplest of all the iterative control statements. The statement list within a while statement is repeated as long as the condition evaluated has not been met. The statement list within the while code body can consist of one or more statements. while (expression) { -- statements that execute while the expression evaluates false } It is a best practice to build error detecting logic into any iterative control statement. This error control logic should be built in such a way as to detect an infinite loop. In the following example, simple logic has been built into a while function to detect an infinite loop error: <?php $i = 5; while ($i < 5) { echo '$i <br>'; $i = $i++; if ($i > 20000) { // Break when > 20,000 repititions break; } } ?>

51

3.6.4

Do ... While The do ... while function is based on the while iterative control statement with the difference being the condition is evaluated at the end of the statement execution versus at the beginning. The statement list within a do ... while function is repeated as long as the condition evaluated has not been met. The statement list within the do ... while code body can consist of one or more statements.
do { -- statements that execute while the expression evaluates false and then it iterates through the statements one more time } while (expression);

A do ... while statement will always be guaranteed to run through the statements contained at least once. The following example demonstrates how a do ... while statement works:
<?php $i = 10; do { echo $i * $i; $i = $i+; } while ($i < 5); /* The number 100 will be displayed, even though 10 is not less than 5. If this was a while statement, the statements would not have run at all */ ?>

Instructor Notes: Unless a user has explicitly instructed PHP otherwise via the ignore_user_abort function, the script will stop executing when the user presses the stop button or, by default, after 30 seconds. However, ______________________________________________________________________________________________ having logic built in is more professional and will provide means to debug code easier. Discuss pre and post ______________________________________________________________________________________________ increment/decrement. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-16

Developing Dynamic Web Applications with MySQL and PHP


52

Chapter 3 - PHP Foundations

3.6.5

For
The for function is the more complex sibling of the while function and provides a more streamline and complex looping mechanism. The for function takes three expressions; the first expression is evaluated by default at the first iteration of the loop, the second expression is evaluated at the beginning of each iteration (and determines if the loop will continue) and the third expression is evaluated at the conclusion of each loop. Any of the expressions can be empty and the logic that would take place in the expression can be substituted in the body of the function itself. The statement list within the for code body can consist of one or more statements.
for (expression1; expression2; expression3) { -- statements that execute while the expressions evaluates false }

The following examples demonstrate how the for iterative control statement can work:
<?php for ($ctemp = 0; $ctemp <= 20; $ctemp = $ctemp + 1) { $ftemp = 32 + $ctemp / 5 * 9; echo "$ctemp -> $ftemp<br>"; } ?> <?php for ($ctemp = 0; ; $ctemp = $ctemp + 1) { $ftemp = 32 + $ctemp / 5 * 9; echo "$ctemp -> $ftemp<br>"; if ($ctemp >= 20) break; } ?> <?php $ctemp = 0; for (;;) { $ftemp = 32 + $ctemp / 5 * 9; echo "$ctemp -> $ftemp<br>"; if ($ctemp >= 20) break; $ctemp = $ctemp + 1; } ?>

Instructor Notes: The code $ctemp = $ctemp + 1 could of course be written shorter by just using $ctemp++; however, there are many reasons to not encourage shortcuts like this and encourage more control over the expected results (rather than trusting PHP to handle that control). ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-17

Developing Dynamic Web Applications with MySQL and PHP


53

Chapter 3 - PHP Foundations

3.6.6

Foreach The foreach function is the iterative control statement that is designed specifically for handling arrays (and objects as of PHP 5). There are two ways of using the foreach iterative control statement. The first ways is by looping over the array given by the array_expression and assigning the current array element to the $value variable.
foreach (array_expression as $value) { -- statements that execute until the array reaches the end or a manual break is inserted }

The second way of using the foreach function is similar to the first, except the element value is assigned to a $key variable.
foreach (array_expression as $key => $value) { -- statements that execute until the array reaches the end or a manual break is inserted }

Each time the foreach command is initiated, the internal pointer to the array is reset and each iteration advances the pointer one element. The following examples demonstrate how the foreach iterative control statement can work:
<?php $last_name = array("Smith", "Jones", "Sanchez", "Green"); foreach ($last_name as $individual) { print "Last Name = $individual<br>"; } ?> <?php $wk_temp = array( 'Sunday' => 13, 'Monday' => 12, 'Tuesday' => 11, 'Wednesday' => 13, 'Thursday' => 15, 'Friday' => 17, 'Saturday' => 9); $wk_avg = 0; foreach($wk_temp as $day => $temp) { echo "$day = $temp<br>"; $wk_avg = $wk_avg + $temp; } $wk_avg = $wk_avg / 7; echo "The average temperature for the week was $wk_avg"; ?>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-18

Developing Dynamic Web Applications with MySQL and PHP


54

Chapter 3 - PHP Foundations

3.6.6.1 Break and Continue


With iterative control statements, PHP provides two means of manually interrupting the flow of the loops. These two commands include break (which has already been used in examples up to this point) and continue. The following example demonstrates how these two loop interrupts can be used in iterative control statements: <?php for ($test=1; $test < 10; $test = $test + 1) { if ($test==3) continue; if ($test==6) break; echo "The test number is $test<br>"; } ?> The following output would be displayed when this PHP script was run: The The The The test test test test number number number number is is is is 1 2 4 5

When the $test variable was equal to 3, the script skipped the remain code and performed the next iteration of the for function. This resulted in the number 3 not being printed. In addition, when the $test variable was equal to 6, the break function ended the for function thus resulting in the remainder of the script being missed resulting in the number 6 not being printed.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-19

Developing Dynamic Web Applications with MySQL and PHP


55

Chapter 3 - PHP Foundations

3.7

User Defined Functions


PHP is packed full with many useful built-in functions, such as print() and mysql_query(), which meet a variety of needs. However, there will be times when a non-standard function would best meet the needs of the application that is being built. This is where user defined functions come in handy. The programmer can of course write the same piece of code over and over again in their applications to produce the result or they can create a user defined function that can be reused over and over again. This is the primary advantage of custom functions. The actual code associated with built-in functions consists of the keyword function followed by the function name. Next comes the parentheses, which may contain variable names, and the actual function code itself, enclosed in curly braces:
function function_name () { -- Statements that make up the function code }

The following examples demonstrate some of the uses and capabilities for creating a user defined function:
<?php function hello ($i) { echo "Hello $i!"; } hello('world'); // This would print "Hello world!" ?> <?php function ctable ($i='Test', $b=1, $p=1, $s=1) { print "<table border=$b, cellpadding=$p cellspacing=$s>"; print "<tr><td>$i</td></tr></table>"; } ctable(); /* Would create a HTML table with the word Test in the cell and with the default table structures */ ctable('Hello World!', 2, 3, 3); /* The defaults would be overwritten with the values entered */ ?>

The first example displays a typical function that has a value that is entered ($i) and then used within the function itself. The second example displays how a programmer can assign a default value to be associated with the values to be read. This is eliminates any problems with a function called not having all the required values necessary to execute properly. In addition, to having information sent into a function, it is also possible to have a value returned:
<?php function circumference ($diameter) { $c = $diameter * pi(); return(printf("%01.2f",$c)); } circumference(3); // This would return 9.42 ?>

Instructor Notes: The built-in function pi() translates to 3.14159265359 in PHP. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-20

Developing Dynamic Web Applications with MySQL and PHP


56

Chapter 3 - PHP Foundations

Lab 3-A
In this further practice, you will create a stored routine that will test the comparison operators in PHP. 1. Create a procedure called comp_ops that has three (3) potential outcomes: 2. If the first value (var_a) and the second value (var_b) are not equal, the procedure needs to display a statement stating that. If the first value (var_a) and the second value (var_b) are equal, the procedure needs to display a statement stating that.

If a solution does not fit in either of the two (2) previous outcomes, then a statement should be displayed stating that the solution is unknown. Test the comp_ops function with the following values: 3, 2 2, 2

3.

2, NULL Create a function called c_length that returns the value of a right triangles longest side based on input (from the end user) for the other two sides. Hint: The square root function in PHP is sqrt().

4.

Test the c_length function with the following values: 3, 4

11,15 Bonus: Using arrays, create an HTML table that displays a times table based on a number entered. Once created, test with the numbers 3, 5, and 10. The following demonstrates an idea of what the final outcome should look like: 1 2 3 4 5 1 1 2 3 4 5 2 2 4 6 8 10 3 3 6 9 12 15 4 4 8 12 16 20 5 5 10 15 20 25

Hint: To create a dynamic array, use ${"identifier".$value}.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-21

Developing Dynamic Web Applications with MySQL and PHP


57

Chapter 3 - PHP Foundations

3.8

Chapter Summary
In this chapter, you have learned to: Delimit PHP code within HTML PHP scripts are distinguished from the HTML scripts by using delimiting characters that tell the server to execute the PHP application to interpret that which is contained in the code. There are four ways to accomplish this; default syntax, script syntax, short syntax and ASP-style syntax. There are many types of commenting strategies with each having advantages and disadvantages over each other. The key is to comment, how that is accomplished is best worked within a team environment and calls for a great deal of flexibility. The following are types of typical commenting that should be considered along with how they would be implemented inside of PHP code: Code Commenting, Inline Commenting, Multiple Line Commenting and HTML commenting. With HTML, the static nature of the information being displayed limits the amount of true customization that can be provided; however, PHP provides truly dynamic content by creating custom content each time the web page is displayed. To accomplish this display of information, PHP has four functions that make this happen: print(), echo, printf() and sprintf(). A data type identifies the characteristics that the assigned data will be interpreted by when interacting with the PHP programming language. There are three categories of data types in PHP: Scalar, Compound and Special. Flow control statements, or instructions, when executed redirect the normal sequence of the original program execution, or the execution logic. When discussing flow control, the reference is to a single thread of execution which is dependent upon instructions that are executed one at a time. Within PHP, two categories of flow control statements can be identified: conditional and iterative. There will be times when a non-standard function would best meet the needs of the application that is being built. This is where user defined functions come in handy. The programmer can of course write the same piece of code over and over again in their applications to produce the result or they can create a user defined function that can be reused over and over again. This is the primary advantage of custom functions.

Comment PHP code

Construct Feedback to users through tool interfaces and requested responses

Utilize the Data Types available in PHP

Utilize Key Control Statements

Develop Reusable Code with user defined functions

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 3-22

Developing Dynamic Web Applications with MySQL and PHP

58

CHAPTER 4 MYSQL FOUNDATIONS


59

Developing Dynamic Web Applications with MySQL and PHP


60

Chapter 4 - MySQL Foundations

4
4.1

MYSQL FOUNDATIONS
Learning Objectives
This chapter provides the foundational knowledge to understand the basic components of MySQL for the development of fully dynamic and database-driven sites. At the completion of this chapter, you will exhibit knowledge of MySQL by being able to: Describe the General Architecture of MySQL Describe the SQL Parser and Storage Engine Tiers Interact with MySQL using the mysql client Interact with MySQL using the MySQL Query Browser

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-1

Developing Dynamic Web Applications with MySQL and PHP


61

Chapter 4 - MySQL Foundations

4.2

MySQL General Architecture


MySQL operates in a networked environment using a client/server architecture. In other words, a central program acts as a server, and various client programs connect to the server to make requests. A MySQL installation has the following major components: MySQL Server, Client programs and MySQL nonclient utilities.

4.2.1

MySQL Server MySQL Server, or mysqld, is the database server program. The server manages access to the actual database (schema) on disk and in memory. MySQL Server is multi-threaded and supports many simultaneous client connections. Clients can connect via several connection protocols. For managing database contents, the MySQL server features a modular architecture that supports multiple storage engines that handle different types of tables (for example, it supports both transactional and non-transactional tables). Keep in mind the difference between a server and a host. The server is software (the MySQL server program mysqld). Server characteristics include its version number, whether certain features are included or excluded, and so forth. The host is the physical machine on which the server program runs. Host characteristics include its hardware configuration, the operating system running on the machine, its network addresses, and so forth.

4.2.2

Client Programs These are programs that are used for communicating with the server to manipulate the databases that are managed by the server. MySQL AB provides several client programs. The following list describes a few of them: o o o MySQL Query Browser and MySQL Administrator are graphical interfaces to the server. mysql is a command-line program that acts as a text-based front end for the server. It's used for issuing queries and viewing the results interactively from a terminal window. Other command-line clients include mysqlimport for importing data files, mysqldump for making backups, mysqladmin for server administration, and mysqlcheck for checking the integrity of the database files.

MySQL Client/Server Model

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-2

Developing Dynamic Web Applications with MySQL and PHP

Chapter 4 - MySQL Foundations

MySQL runs on many varieties of Windows, Unix, and Linux, but client/server communication is not limited to environments where all computers run the same operating system. Client programs can connect to a server running on the same host or a different host, and the client and server host need not have the same operating system. For example, client programs can be used on Windows to connect to a server that is running on Linux. Most of the concepts discussed here apply universally to any system on which MySQL runs. Platformspecific information is so indicated. Unless otherwise specified, Unix as used here includes Linux and other Unix-like operating systems.

Instructor Notes: There are many commercial and open source applications available that are compatible with MySQL, but we do not support any others than discussed in this chapter.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-3

Developing Dynamic Web Applications with MySQL and PHP


62

Chapter 4 - MySQL Foundations

4.3

SQL Parser and Storage Engine Tiers


A client retrieves data from tables or changes data in tables by sending requests to the server in the form of SQL statements. The server executes each statement using a two-tier processing model: The upper tier includes the SQL parser and optimizer. The lower tier comprises a set of storage engines.

For the most part, the SQL tier is free of dependencies on which the storage engine manages any given table. This means that clients normally need not be concerned about which engines are involved in processing SQL statements, and can access and manipulate tables using statements that are the same no matter which engine manages them. Exceptions to this engine-independence of SQL statements include the following: CREATE TABLE has an ENGINE option that enables you to specify which storage engine to use on a per-table basis. ALTER TABLE has an ENGINE option that enables you to convert a table to use a different storage engine. Some index types are available only for particular storage engines. For example, only the MyISAM engine supports full-text or spatial indexes. COMMIT and ROLLBACK have an effect only for tables managed by transactional storage engines such as InnoDB.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-4

Developing Dynamic Web Applications with MySQL and PHP


63

Chapter 4 - MySQL Foundations

4.3.1

Storage Engine Breakdown


The following diagram represents a simplified view of the MySQL server and its interaction with the storage engines.

MySQL
Database Management Level

Parse

Optimize

Retrieve

1
Store

Pluggable Storage Engines

MyISAM

InnoDB

MySQL Cluster

Memory

Other ...

The following properties are storage engine dependant: Storage Medium Each table uses its own method of storing the data it contains. Transactional Capabilities Certain storage engines handle transactional processing which ensures that integrity of a database is maintained during the processing of multiple SQL statements. Locking Each storage engines handles the processes of the synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution. Backup and Recovery Based on the storage medium used, the backup of the table data and the recovery of that data can be distinct. Optimization There are specific issues associated with each storage engine for the optimization of the storage of the data and retrieval of the data through the MySQL server. Special Features There are a number of features that exist only in certain engine types to include full-text search, referential integrity and the ability to handle spatial data.

Most of the MySQL server operates in the same way no matter what storage engine is used: all the usual SQL commands are independent of the storage engine. Naturally, the optimizer may need to make different choices depending on the storage engine, but this is all handled through a standardized interface (API) which each storage engine supports.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-5

Developing Dynamic Web Applications with MySQL and PHP


64

Chapter 4 - MySQL Foundations

4.4

The mysql Client


This section discusses mysql, a general-purpose client program for issuing queries and retrieving their results. It can be used interactively or in batch mode to read queries from a file.

4.4.1

Using mysql Interactively


The mysql client program enables the sending of queries to the MySQL server with any results being displayed in the same interface. It can be used interactively or it can read query input from a file in batch mode: Interactive mode is useful for day-to-day usage, for quick one-time queries, and for testing how queries work. Batch mode is useful for running queries that have been prewritten and stored in a file. It's especially valuable for issuing a complex series of queries that's difficult to enter manually, or queries that need to be run automatically by a job scheduler without user intervention.

MySQL statements such as the version query, shown below as executed within the mysql client, can also be run from the shell command prompt as part of the mysql client startup;
mysql> SELECT VERSION(); +-----------------+ | VERSION() | +-----------------+ | 5.0.41-log | +-----------------+

You can execute a statement directly from the command line by using the -e or --execute option:
shell> mysql -u user_name -ppassword -e "SELECT VERSION()" +-----------------+ | VERSION() | +-----------------+ | 5.0.41-log | +-----------------+

No statement terminator is necessary unless the string following -e consists of multiple statements. In that case, separate the statements by semicolon characters.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-6

Developing Dynamic Web Applications with MySQL and PHP


65

Chapter 4 - MySQL Foundations

4.4.2

Statement Terminators
There are numerous terminators that can be used in the mysql client to end a statement. Two terminators are the semicolon character (';') and the \g sequence. They're equivalent and may be used interchangeably:
mysql> SELECT VERSION(), DATABASE(); +-----------------+--------------------+ | VERSION() | DATABASE() | +-----------------+--------------------+ | 5.0.40-log | INFORMATION_SCHEMA | +-----------------+--------------------+

The \G sequence also terminates queries, but causes mysql to display query results in a vertical style that shows each output row with each column value on a separate line:
mysql> SELECT VERSION(), DATABASE()\G ************************** 1. row ************************** VERSION(): 5.0.40-log DATABASE(): INFORMATION_SCHEMA

The \G terminator is especially useful if a query produces very wide output lines because vertical format can make the result much easier to read. The mysql client allows a single query to be entered using multiple input lines. This makes it easier to issue a long query because you can enter it over the course of several lines. mysql will wait until it sees the statement terminator before sending the query to the server to be executed. For example:
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE -> FROM INFORMATION_SCHEMA.TABLES -> WHERE TABLE_NAME LIKE 'E%'; +--------------------+------------+-------------+ | TABLE_SCHEMA | TABLE_NAME | TABLE_TYPE | +--------------------+------------+-------------+ | information_schema | ENGINES | SYSTEM VIEW | | information_schema | EVENTS | SYSTEM VIEW | | mysql | event | BASE TABLE | +--------------------+------------+-------------+ 3 rows in set (#.## sec)

In the preceding example, mysql changes the prompt from mysql> to -> to provide feedback that it's still waiting to see the end of the statement. If a statement results in an error, mysql displays the following error message:
mysql> This is an invalid statement; ERROR 1064 (42000): You have an error in your SQL syntax.

If it is necessary to cancel a statement once mysql has already received some of the input, enter \c and mysql will cancel the statement and return the mysql> prompt:
mysql> SELECT * FROM INFORMATION_SCHEMA > WHERE \c mysql>

To quit mysql, use \q, QUIT, or EXIT: mysql> \q

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-7

Developing Dynamic Web Applications with MySQL and PHP

Chapter 4 - MySQL Foundations

Lab 4-A
This lab requires you to use the MySQL command line client in order to invoke the mysql client interactively. ACTION (You Do) 1. In the mysql bin directory, invoke the mysql client interactively using the --execute option, which will show the current time upon startup. mysql -u root -p -e "SELECT CURRENT_TIME()" COMPUTER RESPONSE / Comment When prompted for the password to use, use the password provided by the instructor (if not already provided). Instead of returning the mysql prompt and entering the mysql client, this command will merely enter mysql in order to execute the statement and give its standard output. The prompt will return to the shell command prompt. When prompted for the password to use, use the password used in step 1.

2. Login into the mysql client by typing the following command at the shell command prompt: mysql -uroot -p 3. At the mysql prompt, enter a multiple statement query for retrieving the current date and current time: SELECT CURRENT_DATE(), CURRENT_TIME(); 4. At the mysql> prompt, enter the same statement as in step 3, but direct the output to vertical format: SELECT CURRENT_DATE(), CURRENT_TIME()\G 5. At the mysql> prompt, type the following: SHOW DATABASES; 6. At the mysql> prompt, type the following: SHOW TABLES FROM INFORMATION_SCHEMA;

Returns the date and time in table output format.

Returns the date and time in vertical output format.

This command will list the current databases that are available in the MySQL server. This command will show all the tables that are associated with the INFORMATION_SCHEMA database. INFORMATION_SCHEMA is the information database, the place that stores information about all the other databases that the MySQL server maintains. Returns default shell prompt.

7. Quit out of the mysql client session.

Instructor Notes: There are a few commands that have not been introduced yet; however, they are placed here to show other commands that can be used within MySQL. These commands will be expanded upon in future chapters. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-8

Developing Dynamic Web Applications with MySQL and PHP


66

Chapter 4 - MySQL Foundations

4.5

MySQL Query Browser


MySQL Query Browser is a cross-platform GUI client program that's intuitive and easy to use. It provides a graphical interface to the MySQL server for querying and analyzing data. The MySQL Query Browser provides a Connection dialog that enables a connection to a MySQL server. This section describes how to use the Connection dialog and the Main Query Browser GUI.

4.5.1

Using the Connection Dialog


MySQL Query Browser presents a Connection dialog when it starts or when the New Instance Connection is selected from the File menu. Connecting to a MySQL server can be accomplished either by filling in the connection dialog box fields with the parameters required to connect to a server or selecting from among any predefined connection profiles. Connection Dialog Window:

To connect to a MySQL server by specifying connection parameters directly, fill in the appropriate fields beginning with the Username field and click the OK button. To connect using the parameters stored in a connection profile, select the profile from the Connection drop-down list and click the OK button.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-9

Developing Dynamic Web Applications with MySQL and PHP

Chapter 4 - MySQL Foundations

4.5.2

The MySQL Query Browser Window


The main MySQL Query Browser window is divided up into several sections: Query Toolbar The query toolbar is where queries can be created and executed. It is composed of three navigation buttons (Go Back, Next, Refresh), the query area, two action buttons (Execute and Stop), and a status indicator. o Advanced Toolbar - The advanced toolbar contains three sets of buttons: the Transaction Buttons (Start, Commit, Rollback), the query management buttons (Explain, Compare), and the query building buttons (Select, From, Where, and so on.) The Advanced Toolbar is only visible when the Show advanced toolbars and Show composer buttons toolbar options in the Browser Options screen are checked. o Results Area - All query results are displayed in the result area. Multiple tabs can be active at one time, allowing multiple queries to be worked on. The result area can be split vertically and horizontally for performing comparisons, and queries in different parts of a split result area can be joined together for master-detail analysis. o Object Browser - The object browser is part of the sidebar and allows for the management of the databases, bookmarks, and history. Databases and tables can be chosen to query, in addition to the ability to add commonly-used queries to a collection of bookmarks, and browse through previously issued queries in order to use them again. If there are many schemata on your MySQL server, the search field with the magnifying glass icon may be handy for filtering the schemata. Typing in t or T, for example, will set the filter to schemata whose names begin with a t. The filter works in a case-insensitive fashion. Filter schemata can also use the wild card (?) to stand in for any single character and (*) for zero to any number of characters. For example the string *boo?* will find schemata with the names books, coursebooks, and bookings. o Information Browser - The Information Browser is part of the sidebar and is used to look up built-in functions, and to manage queries that contain parameters. One example of this is when establishing a master-detail pair of queries. The data in the master query is available as parameters to the detail query. Using the View menu, most of these sections can be displayed and hidden by checking and unchecking the elements. o

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-10

Developing Dynamic Web Applications with MySQL and PHP

Chapter 4 - MySQL Foundations

Lab 4-B
In this exercise you will install the MySQL GUI Tools bundle and run the MySQL Query Browser. ACTION (You Do) 1. From a web browser go to the MySQL downloads web page:
0H

COMPUTER RESPONSE / Comment Opens MySQL Downloads web page.

http://dev.mysql.com/downloads/ Opens MySQL GUI Tools Downloads web page.

2. In downloads web page, scroll down to the MySQL Tools section. Select MySQL GUI Tools. 3. Select Generic X86 Linux TAR (bundled dependencies) Pick a Mirror.

This build of the GUI tools will work on the majority of Linux 32-bit operating systems. If there is a better build to select from the list, please do so. The Select a Mirror web page opens. * Instructor will tell you which mirror is best for the location. This step will perform the actual download of the MySQL GUI installation files (mysql-gui-tools5.0r#-linux-i386.tar.gz) to the default download directory for your setup. This is most likely the desktop for the majority of Linux operation systems.

4. Scroll to lower portion of page and select the appropriate HTTP mirror for your location.*

5. Open a terminal window and change directory to the ~/Desktop directory (or the directory where the GUI tarball was downloaded to), type the following: tar --directory=/opt -xzvf mysqlgui-tools-5.0r#-linuxi386.tar.gz replacing the mysql-gui-tools-5.0r#linux-i386.tar.gz with the exact file identifier downloaded in step 4. 6. Open the MySQL Query Browser by typing the following command in the terminal window: /opt/mysql-gui-tools-5.0/mysqlquery-browser & 7. In Connect to MySQL Server window, enter; Server Host: localhost Username: root Password: <password> Default Database: <leave blank>

This will extract the file downloaded in step 4 into the /opt directory making a new subdirectory labeled mysql-gui-tools-5.0.

This will open the Connect to MySQL Server window.

Use the password that has been used up to this point. The MySQL Query Browser GUI window is opened and displayed.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-11

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 8. In the Query Toolbar section, type in the following command and then left-click the Execute button: SELECT CURRENT_DATE(), CURRENT_TIME() 9. In the Query Toolbar section, type in the following command and then left-click the Execute button: SHOW TABLES FROM INFORMATION_SCHEMA 10. In the Object Browser window, double-click on the INFORMATION_SCHEMA database text. 11. Close the Query Browser window using the pull-down menu; File > Quit

Chapter 4 - MySQL Foundations

COMPUTER RESPONSE / Comment The current date and time is displayed in the Results Area. You will notice that the terminator (;) used in the mysql client is not necessary. In addition, using the vertical display terminator (\G) will result in an error. The tables located in the INFORMATION_SCHEMA database are displayed in the Results Area.

This will expand the INFORMATION_SCHEMA database and list the tables that are located within the database. The Query Browser window is closed.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-12

Developing Dynamic Web Applications with MySQL and PHP


67

Chapter 4 - MySQL Foundations

4.6

Chapter Summary
In this chapter, you have learned to: Describe the General Architecture of MySQL MySQL operates in a networked environment using a client/server architecture. In other words, a central program acts as a server, and various client programs connect to the server to make requests. A MySQL installation has the following major components: MySQL Server, Client programs and MySQL non-client utilities. A client retrieves data from tables or changes data in tables by sending requests to the server in the form of SQL statements. The server executes each statement using a two-tier processing model: The upper tier includes the SQL parser and optimizer and the lower tier comprises a set of storage engines. The mysql client is a general-purpose client program for issuing queries and retrieving their results. It can be used interactively or in batch mode to read queries from a file. The MySQL Query Browser is a graphical tool provided by MySQL AB for creating, executing, and optimizing queries in a graphical environment.

Describe the SQL Parser and Storage Engine Tiers

Interact with MySQL using the mysql client Interact with MySQL using the MySQL Query Browser

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 4-13

Developing Dynamic Web Applications with MySQL and PHP

68

CHAPTER 5 MANAGING DATABASES

69

Developing Dynamic Web Applications with MySQL and PHP


70

Chapter 5 - Managing Databases

5
5.1

MANAGING DATABASES
Learning Objectives
This chapter provides the foundational knowledge to manage databases within MySQL. At the completion of this chapter, you will exhibit knowledge of MySQL by being able to: Describe Database Properties Implement Good Design Practices in database projects Utilize MySQL Identifiers Create Databases Alter Databases Drop Databases

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-1

Developing Dynamic Web Applications with MySQL and PHP


71

Chapter 5 - Managing Databases

5.2

Database Properties
The heart of any database is the tables, because the tables contain the data that is used to provide information to the end users. Tables are contained in databases, and in MySQL each database has an associated "data directory" to store all the physical components of the database, to include tables. This physical representation on disk of the tables is dependent on the type of storage engine that the table is utilizing; however, every table, no matter of the type of storage engine that is being used, contains a format file (table_name.frm) which describes the table definition and structure. In addition to the physical representation of the table, there is also the better known logical aspect of the table. This logical aspect is represented in rows and columns. Rows within a table, consist of a collection of values that describe an entity (ex. an employee). Columns within a table, consist of a collection of similar data among rows (ex. employee surnames). The intersection of row and column contains individual data items called values. Values are always atomic, in that each position in a table may contain only one datum (piece of data). Without the ability to obtain information from the database, there is no need for the data to be stored. However, the tables are of little value unless they are contained in a unified and associated manner that allow for the storage, retrieval and manipulation of the data. This is where the database comes in. For its part, the database can be thought of as the container for the tables (which are the containers for the data). In MySQL, databases manage their associated components in locations called "data directories". These data directories (meaning there can be more than one database that the MySQL server can manage) are located in a central sub-directory of the mysql installation and can be seen through the operating system on which the MySQL Server is running. MySQL "data directories" have the following common structures: Data Directory - In MySQL, there is a parent directory for all the databases that are managed by that instance of the MySQL Server. Database Name - The database name given to the represent the database in the MySQL server is also the name of the associated data sub-directory. This limits the naming conventions that can be used when giving databases a name. Database Components - The data directory is responsible for managing the majority of component associated with the associated database in the MySQL server. This includes such components as the tables, stored procedures, triggers, views, etc. Database Character Set Support - Each database is defined with a default character set and collation (a character set is a set of symbols and encodings and a collation is a set of rules for comparing characters in a character set). This behavior ensures that each table created within the database takes on the same characteristics associated with the default values; however, tables themselves can also be created with different character sets and collations than their database container. Database Hierarchy - Databases are "flat" in the sense that they can not be nested, meaning a database can not contain a database itself. Unlimited Databases - The MySQL server has no limit on the number of databases that it can contain; however, the operating system may limit the number of sub-directories that a directory can contain thus limiting the number of databases that can be created.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-2

Developing Dynamic Web Applications with MySQL and PHP

Chapter 5 - Managing Databases

Database or Schema? From its conception, MySQL has used the term "Database" to refer to the container that manages the tables and other database components. This is a common term in the industry and is not by any means against the norm. However, the word "Schema", which comes from the Greek word "" (skhma) which when translated means "plan", has come to be associated with databases. A database schema is basically the plan (or description) of the structure of a database. Thus the words, "Database" and "Schema" are used interchangeably in the database community. However, the SQL standard is to use "Schema". For consistency, the word "database" will be used unless otherwise noted.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-3

Developing Dynamic Web Applications with MySQL and PHP


72

Chapter 5 - Managing Databases

5.3

Database Design Practices


In database discussions, it is common to hear the term normalization or database design come up. However, for the most parts these discussions revolve around splitting up the data that is stored between different tables to improve performance and to eliminate duplication. This is extremely important and should be discussed in any discussion on tables but for the most part the discussions do not involve splitting up data between databases. This is either assumed or just not put into practice as often as it should be. Either way, it is important to consider when designing an application that will need to access data. Information Commonality MySQL Server Data could be defined as the actual values that are stored in the Inventory Human Resource database itself and are static until Database Database Non-Common Information they are changed by some process (either manually or automated). Data by itself is useless if not processed in such a way as to give it meaning. Information, on the other hand, is data processed in such a way as to give it meaning and is constantly changing based on the data stored. In addition, the majority of data collected can be processed in multiple ways to provide multiple meaningful outputs. In databases, many developers look at the data that is contained versus the information that the data is designed to provide. Databases should be developed in such a way that each database produces a common set of information. Tables that would hold data associated with human resource information should not be contained in the same database as tables that would contain parts for aircrafts in an airline database system. If there is a need for the data in the inventory database to interact with data in the human resource database to provide the proper information, the MySQL server can pull data from the tables holding the data (even though they are in two different databases) to provide such information. Exclusive Data In such situations where there are separate entities that utilize the same data structures, separating out the data may be the safest and most reliable way to ensure data integrity. An example would be an accounting firm that is responsible for the payroll of two or three companies. The application that would be created to support such as system could utilize the same data structures but have separate databases containing the actual data for each company. This would eliminate any chance that data from one company could interact with data from another company which would create an insecure and potentially precarious situation. This would require time and energy put MySQL Server into ensuring that the database and its underlying components were solid Company B Company C Company A enough to avoid the need for Payroll Database Payroll Database Payroll Database structural changes after implentation. Copying database structures from one database to another is an easy process in MySQL; however, any future changes would have to be done in the individual databases separately.

73

______________________________________________________________________________________________ Instructor Notes: This section is designed to get the students to think about using databases properly but by no ______________________________________________________________________________________________ means is to be a complete course on database design. If this becomes a large topic for discussion, suggest taking this offline or even better make recommendations for more detailed course that cover such topics (preferably courses ______________________________________________________________________________________________ MySQL offers). ______________________________________________________________________________________________

Page 5-4

Developing Dynamic Web Applications with MySQL and PHP


74

Chapter 5 - Managing Databases

5.4

MySQL Identifiers
The are five kinds of identifiers that need to be considered in MySQL: databases, tables, columns, indexes and aliases. Databases, as stated are the containers for the tables and other associated database components. Tables hold the data that is used to produce information. Columns are the individual entities of the tables that contain the smallest portion of the data. Indexes in databases refer to the data structures that improve the speed of operations in a table. Aliases are temporary names assigned to database components. The identifiers that can be assigned to each component have their limitations: Size - The following table describes the max length each database identifier can be assigned: Identifier Database Table Column Index Alias Maximum Length 64 Bytes 64 Bytes 64 Bytes 64 Bytes 255 Bytes

The length of the identifier is in bytes, not characters. The maximum length will depend on the byte count of all the characters used and should be taken into consideration if using multi-byte characters in the identifier names. Case Sensitivity - In MySQL, databases correspond to directories within the data directory. Each table within a database corresponds to at least one file within the database directory (and possibly more, depending on the storage engine). Consequently, the case sensitivity of the underlying operating system determines the case sensitivity of database and table names. This means database and table names are case sensitive in most varieties of Unix, and not case sensitive in Windows. Although database and table names are not case sensitive on some platforms, database or table names should not be referred to using different cases within the same statement. The following statement would not work because it refers to a table both as my_table and as MY_TABLE: mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1; Character Restrictions - It is best practice to include only alphanumeric characters (and underscore or dashes) in the identifier names; however, other characters can be used if no other way is acceptable. Here is a list or restrictions that also need to be considered in such an event: No identifier can contain ASCII 0 (0x00) or a byte with a value of 255 The use of identifier quote characters in identifiers is permitted, although it is best to avoid doing so if possible Database, table, and column names should not end with space characters Before MySQL 5.1.6, database names and table names cannot contain /, \, ., or characters that are not allowed in a directory name Identifiers may begin with a digit but unless quoted may not consist solely of digits It is recommended that names of the form Me or MeN, where M and N are integers. For example, avoid using 1e or 2e2 as identifiers, because an expression such as 1e+3 is ambiguous. Depending on context, it might be interpreted as the expression 1e + 3 or as the number 1e+3.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-5

Developing Dynamic Web Applications with MySQL and PHP


75

Chapter 5 - Managing Databases

5.5

Creating Databases
To create a new database, use the CREATE DATABASE statement. The following statement creates a database named my_db:
CREATE DATABASE my_db;

If an attempt is made to create a database that already exists, an error occurs. To ensure that the database exists, add an IF NOT EXISTS clause to the statement:
CREATE DATABASE IF NOT EXISTS my_db;

With the additional clause, the statement creates the database only if it does not already exist. Otherwise, the statement does nothing and no error occurs. This can be useful in applications that need to ensure that a given database is available, without disrupting any existing database with the same name. Optional Clauses The CREATE DATABASE statement has two optional clauses, CHARACTER SET and COLLATE, that assign a default character set and collation for the database. If given, they appear at the end of the statement following the database name. The following statement specifies that the mydb database has a default character set of utf8 and collation of utf8_danish_ci:
CREATE DATABASE my_db CHARACTER SET utf8 COLLATE utf8_danish_ci;

The default character set and collation for the database are used as the defaults for tables created in the database for which no explicit character set or collation of their own are specified. The database defaults are stored in the db.opt file in the database directory. Note: CHARACTER SET is really a column setting. By giving the table or the database a character set, it just affects the columns upon creation. Using the Database Creating a database has no effect on which database currently is selected as the default database. To make the new database the default database, issue a USE statement: USE my_db; After a database has been created, it can be populated with objects such as tables or stored routines. The CREATE statement for tables is discussed in a later chapter. Displaying Database Structure The easiest way to display the database structure (as far as the database container) is to issue a SHOW CREATE DATABASE command. This command shows the CREATE DATABASE statement that was used to create the database (or could be used to recreate the database structure):
mysql> SHOW CREATE DATABASE my_db\G ************************* 1. row ************************* Database: my_db Create Database: CREATE DATABASE `my_db` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_danish_ci */

Note: SCHEMA can be interchanged with DATABASE to perform the above statements. (i.e., CREATE SCHEMA mydb;) Problems When a CREATE DATABASE command fails, the two most common problems are insufficient or incorrect permissions, or an attempt to create a database that already exists. Instructor Notes: Of course databases could be created via the mysqladmin command line interface; however, the easier solution is of course just using the mysql client and thus the one that should be addressed. If need be, you can ______________________________________________________________________________________________ feel free to address the mysqladmin command line interface. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-6

Developing Dynamic Web Applications with MySQL and PHP


76

Chapter 5 - Managing Databases

5.6

Drop a Database
When a database is no longer needed, it can be removed with DROP DATABASE: DROP DATABASE my_db; It is an error if the database does not exist. To cause a warning instead, include an IF EXISTS clause; DROP DATABASE IF EXISTS my_db; Any warning generated when IF EXISTS is used can be displayed with SHOW WARNINGS. Warning vs. Errors

Within MySQL, there are two levels of problem feedback that the server returns to the user. The first is called a warning, and it does exactly that. It warns the end user that there were problems associated with the transaction the just submitted, but it still performs the transaction commands to the best of its ability. To view a specific (and sometimes not so specific) explanation of the warning, use the SHOW WARNINGS command to view the last warning that was sent to the end user. The second level of problem feedback is called an error and aborts the transaction that was submitted. Whenever an error is encountered, the commands that were in the last transaction are not completed. To view a specific (and sometimes not so specific) explanation of the error, use the SHOW ERRORS command to view the last error that was sent to the end user. SHOW WARNINGS also displays error level feedback that was captured. DROP DATABASE does not require the database to be empty. When dropping the database, MySQL removes any objects that it contains; such as tables, stored procedures, triggers, etc. A successful DROP DATABASE returns a row count that indicates the number of tables dropped. (This actually is the number of .frm files removed, which amounts to the same thing.) Use the SHOW DATABASES command to verify that the database has been dropped.

5.6.1

CAUTION: When Using DROP DATABASE


A database is represented by a directory under the data directory. The server deletes only files and directories that it can identify as having been created by itself (for example, .frm files or RAID directories). It does not delete other files and directories. If a non-table files have been placed in that directory, those files are not deleted by the DROP DATABASE command. This results in failure to remove the database directory and DROP DATABASE fails. In that case, the database will continue to be listed by SHOW DATABASES. To correct this problem, manually remove the database directory and any files within it.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-7

Developing Dynamic Web Applications with MySQL and PHP

Chapter 5 - Managing Databases

Lab 5-A
In this exercise you will use the CREATE DATABASE statement. This will require a MySQL command line client and access to the mysql server. ACTION (You Do) 1. Log in to the mysql client (if not already). COMPUTER RESPONSE / Comment It is easier and more advantageous to design the database components in the MySQL client versus trying to complete the tasks through the PHP interface. Returns Query OK, 0 rows affected (#.## sec) when complete.

2. Create a new database called 'db_test' by entering the following command in the mysql client: CREATE DATABASE db_test; 3. Show the list of current databases by entering the following command in the mysql client: SHOW DATABASES; 4. Show the structure of the creation of db_test database by entering the following command in the mysql client: SHOW CREATE DATABASE db_test; 5. In the mysql client, type the following: USE db_test;

Returns a list of databases. Note that db_test is on the list. Displays the entire CREATE DATABASE statement that is used by the mysql client.

This statement sets the current database to be used to the db_test database. This would support creating database components (tables, triggers, stored procedures) within the database without having to precede the component names with the database name. This is the directory that maintains the database information used by MySQL. A listing of this database will reveal sub-directories associated to every database being maintained by the MySQL server. Note: You may have to login as a superuser to view this directory.

6. In an operating system terminal window, change to the /usr/local/mysql/data directory.

7. In the operating system terminal window opened, change into the db_test directory and view the contents of the db.opt file contained within it by typing the following: more db.opt 8. In mysql client, drop the db_test database by issuing the following SQL command: DROP DATABASE db_test;

A listing of the default character set and collation that has been assigned to the database is displayed.

Due to the fact that there were no tables created under this database, there are no rows that were affected by dropping the table.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-8

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 9. Verify that the database has been deleted by entering the following command in the mysql client: SHOW DATABASES; 10. Exit the mysql client by entering the following command: Quit 11. View the contents of the /usr/local/mysql /data directory again and verify that the subdirectory that was associated with the db_test database has been removed. If it has not been removed, use the operating system commands to remove it.

Chapter 5 - Managing Databases

COMPUTER RESPONSE / Comment Returns a list of databases. The db_test database should no longer be in the list.

The mysql client is closed and you are returned to the operating system terminal window. Once a database has been dropped in MySQL, the directory associated with the database is removed also. If it is not completely removed, operating system commands will be able to complete the task.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-9

Developing Dynamic Web Applications with MySQL and PHP


77

Chapter 5 - Managing Databases

Lab 5-B
In this exercise, you will create a database called photo_album that will be the first step in the creation of an online photo album web application. Throughout the course, you will complete an online photo album that will utilize many of the skills you will learn in this course. The following graphic is a representation of what the final product will look like:

1. 2. 3. 4. 5. 6.

Login in to the mysql client using the login name and password provided by your instructor. View the existing databases that the MySQL Server is maintaining. There should be only three databases that the MySQL Server is maintaining: INFORMATION_SCHEMA, mysql and test. Remove any additional databases that exist. Create a new database called photo_album. Using the mysql client, verify that the database was created. View the contents of the /usr/local/mysql/data directory. Is there a new sub-directory associated with the database just created?

7. View the db.opt file located in the associated sub-directory to view the details of the database. ______________________________________________________________________________________________ ______________________________________________________________________________________________ Instructor Notes: The image displayed is of the final product for the course (view_images9.php). It is designed to be functional but not pretty. Each of the further practices will build upon each other and produce this outcome. Feel ______________________________________________________________________________________________ free to explain the web page to the students to let them know what they will be building. ______________________________________________________________________________________________

Page 5-10

Developing Dynamic Web Applications with MySQL and PHP


78

Chapter 5 - Managing Databases

5.7

Chapter Summary
In this chapter, you have learned to: Describe Database Properties In MySQL, databases manage their associated components in locations called "data directories". These data directories (meaning there can be more than one database that the MySQL server can manage) are located in a central sub-directory of the mysql installation and can be seen through the operating system on which the MySQL Server is running. Good design practices, including what should and should not be grouped together in a single database, is important to consider when designing an application that will need to access data. The are five kinds of identifiers that need to be considered in MySQL: databases, tables, columns, indexes and aliases. These identifiers have limitations to include size, case sensitivity and character restrictions. To create a new database, use the CREATE DATABASE statement. The CREATE DATABASE statement has two optional clauses, CHARACTER SET and COLLATE, that assign a default character set and collation for the database. When you no longer need a database, you can remove it with DROP DATABASE. DROP DATABASE does not require the database to be empty. When dropping the database, MySQL removes any objects that it contains; such as tables, stored procedures, triggers, etc.

Implement Good Design Practices in Database Projects

Utilize MySQL Identifiers

Create MySQL Databases

Drop MySQL Databases

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 5-11

Developing Dynamic Web Applications with MySQL and PHP

79

CHAPTER 6 MANAGING DATABASE TABLES

80

Developing Dynamic Web Applications with MySQL and PHP


81

Chapter 6 - Managing Database Tables

6
6.1

MANAGING DATABASE TABLES


Learning Objectives
This chapter provides the methods and tools needed to create and manage MySQL database tables. At the completion of this chapter, you will be able to: Define Table Properties List the Most Common Storage Engines Available Assign the Appropriate Data Type to Table Entities Create a Table Alter a Table Remove a Table Explain and Use Indexes Assign and Utilize Foreign Keys

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-1

Developing Dynamic Web Applications with MySQL and PHP


82

Chapter 6 - Managing Database Tables

6.2

Table Properties
The heart of any database is the tables, because the tables contain the data that is used to provide information to the end users. Tables are contained in databases, and in MySQL each database has an associated "data directory" to store all the physical components of the database, to include tables. This physical representation on disk of the tables is dependent on the type of storage engine that the table is utilizing; however, every table, no matter of the type of storage engine that is being used, contains a format file (table_name.frm) which describes the table definition and structure. In addition to the physical representation of the table, there is also the better known logical aspect of the table. This logical aspect is represented in rows and columns. Rows within a table, consist of a collection of values that describe an entity (ex. an employee). Columns within a table, consist of a collection of similar data among rows (ex. employee surnames). The intersection of row and column contains individual data items called values. Values are always atomic, in that each position in a table may contain only one datum (piece of data).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-2

Developing Dynamic Web Applications with MySQL and PHP


83

Chapter 6 - Managing Database Tables

6.2.1

Storage Engines
When creating a table in MySQL, the storage engine that will be used has to be chosen. If one is not chosen, MySQL uses the default storage engine chosen in the configuration of the server. MySQL supports several storage engines that act as handlers for different table types. MySQL storage engines include both those that handle transaction-safe tables and those that handle non-transaction-safe tables. There are numerous storage engines that MySQL supports; however the most common storage types that are used with PHP are listed below: MyISAM - This storage engine is supported in all MySQL configurations and is the default storage engine for all new tables created (when a specific storage engine is not assigned) in the majority of default installations. This storage engine manages non-transactional tables. It provides high-speed storage and retrieval, as well as fulltext searching capabilities. MyISAM is a disk based storage engine. Aiming for very low overhead, it does not support transactions. InnoDB - InnoDB is also disk based, but offers versioned, fully ACID transactional capabilities. InnoDB requires more disk space than MyISAM to store its data, and this increased overhead is compensated by more aggressive use of memory caching, in order to attain high speeds. InnoDB is included by default in all MySQL 5.0 binary distributions. Memory (formerly called "Heap") - This storage engine provides in-memory (utilizes only RAM) tables. Special algorithms are used that make optimal use of this environment. It is very fast. Like MyISAM, the Memory storage engine handles non-transactional tables, and is also included in MySQL by default. NDB - This is the MySQL Cluster Storage engine which connects to a cluster of nodes, offering high availability through redundancy, high performance through fragmentation (partitioning) of data across multiple node groups, and excellent scalability through the combination of these two. Prior to MySQL 5.1, NDB used main-memory only, with logging to disk. Table Limits

The MySQL server has no limits overall on the number of tables that can be created in a database; however, there are limits within the storage engine type itself or on in the operating system that contains the MySQL server. InnoDB, for example, limits the number of tables that can be created for the entire database to 2 million tables. This means that one database server can not contain more the 2 million tables across one database or multiple databases. This is because all InnoDB tables are stored in a central files in the operating system and not separated out by database. MyISAM tables on the other hand do not have any such limitations; however, the operating system can oppose limits on the number of files that can be stored on disk or in an individual subdirectory.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-3

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

Lab 6-A
In this exercise you will view the complete list of storage engines that can be used with the MySQL server currently running. In addition, you will load a database called 'world' that will be used as an example database for the training. ACTION (You Do) 1. Log in to the mysql client (if not already). COMPUTER RESPONSE / Comment It is easier and more advantageous to design the database components in the MySQL client versus trying to complete the tasks through the PHP interface. This command will list all the storage engines that are available for use in the MySQL server. Each storage engine listing includes the storage engine name, if it is supported in the server, a description of the storage engine and if it supports transactions (XA and savepoints are ACID compliant components and will only be seen in storage engines that fully support transactions). Returns Query OK, 0 rows affected (#.## sec) when complete. This will create the database "container" for the tables that will be created in the next few steps. This command tells the mysql client to use the world database for any commands that will be executed from this point on. This command SHOW TABLES, which will be discussed in greater detail later in the chapter, lists all the tables that are located in the database that is being utilized. In this case, there are no tables associated with the world database at this point. This command will load a predefined SQL script that builds three tables and loads these tables with data.

2.

In the mysql client window, type the following command: SHOW ENGINES\G

3. Create a new database called 'world' by entering the following command in the mysql client: CREATE DATABASE world; 4. In the mysql client, type the following to utilize the database just created: USE world; 5. In the mysql client, type the following to show all the tables that are located in the world database: SHOW TABLES; 6. In the mysql client, type the following command to load the world database with the tables that will be used in examples throughout the remainder of the course: SOURCE /tmp/world.sql 7. In the mysql client, type the following to show all the tables that are now located in the world database: SHOW TABLES;

The SHOW TABLES now shows three tables in the world database: City, Country and CountryLanguage. These tables and there associated properties will be used as examples throughout the remainder of this course.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-4

Developing Dynamic Web Applications with MySQL and PHP


84

Chapter 6 - Managing Database Tables

6.3

MySQL Data Types


Before going to deep into the creation of tables, it is important to understand the data types that can be used within MySQL. These data types will be assigned to the columns that will make up the MySQL tables and will need to be understood, not only for ensuring the proper data is being stored but also to ensure a database that performs well. One of the biggest problems associated with database performance is poor design, especially in the choice of data types that are used in the columns. In MySQL the data types available can be broken down into three major categories: Numeric String Temporal Numeric values (Integers, Floating-Point, Fixed-Point and Bit-field) Text or binary data Time and dates

Within each category there are numerous specific data types that use varying amounts of memory and disk space, thus having varying effects on performance. Choosing the best data type for the column has a rather small effect on performance in an individual record, but as the database grows these small effects can lead to larger effects. This should be taken into account early in the design process, before they become performance issues. ABC's of Data Types A data type refers to what kind of data a value can hold and how that data is stored. When determining the data type that a value should contain, the following "ABC's" should be considered: A -- Apt - the data needs to be represented in the type most fitting the entity it represents B -- Brief - if you choose the smallest fitting size it saves storage space and helps performance C -- Complete - the type needs to include the best guess for max size this data set will ever grow

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-5

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

6.3.1

Numeric Data Type


For storing numeric data, MySQL provides integer data types, floating-point types that store approximatevalue (real) numbers, a fixed-point type that stores exact-value (real) numbers, and a BIT type for bit-field values. When numeric data type is chosen, consider the following factors: The range of values the data type represents The amount of storage space that column values require The column precision and scale for floating-point and fixed-point values Precision and scale are terms that apply to floating-point and fixed-point values, which can have both an integer part and a fractional part. Precision is the number of significant digits. Scale is the number of digits to the right of the decimal point. Integer Data Type The integer data types are summarized in the following table, which indicates the amount of storage per value that each type requires as well as its range. For integer values declared with the UNSIGNED attribute, negative values are not allowed, and the high end of the range shifts upward to approximately double the maximum positive value of the signed range. Storage Required TINYINT 1 byte SMALLINT 2 bytes MEDIUMINT 3 bytes INT 4 bytes Type BIGINT 8 bytes Signed Range 128 to 127 32,768 to 32,767 8,388,608 to 8,388,607 2,147,683,648 to 2,147,483,647 9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 Unsigned Range 0 to 255 0 to 65,535 0 to 16,777,215 0 to 4,294,967,295 0 to 18,446,744,073,709,551,615

Floating-Point Types The floating-point data types include FLOAT and DOUBLE. Each of these types may be used to represent approximate-value numbers that have an integer part, a fractional part, or both. FLOAT and DOUBLE data types represent values in the native binary floating-point format (IEEE 754) used by the server host's CPU. This is a very efficient type for storage and computation, but values are subject to rounding error. Type FLOAT DOUBLE Storage Required 4 bytes 8 bytes Signed Range -3.402823466E+38 to -1.175494351E-38 -1.7976931348623157E+308 to -2.2250738585072014E-308 Unsigned Range 0 and 1.175494351E-38 to 3.402823466E+38 0 and 2.2250738585072014E-308 to 1.7976931348623157E+308

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-6

Developing Dynamic Web Applications with MySQL and PHP Fixed-Point Types

Chapter 6 - Managing Database Tables

The fixed-point data type is DECIMAL. It is used to represent exact-value numbers that have an integer part, a fractional part, or both. DECIMAL uses a fixed-decimal storage format: All values in a DECIMAL column have the same number of decimal places and are stored exactly as given when possible. DECIMAL values are not processed quite as efficiently as FLOAT or DOUBLE values (which use the processor's native binary format), but DECIMAL values are not subject to rounding error, so they are more accurate. In other words, there is an accuracy versus speed tradeoff in choosing which type to use. For example, the DECIMAL data type is a popular choice for financial applications involving currency calculations, because accuracy is most important. The amount of storage required for DECIMAL column values depends on the precision and scale. Approximately four bytes are required per nine digits on each side of the decimal point. The maximum range is the same as for DOUBLE; the effective range for a given DECIMAL column is determined by precision and scale. NUMERIC Data Type The NUMERIC data type in MySQL is a synonym for DECIMAL. (If a column is declared as NUMERIC, MySQL uses DECIMAL in the definition.) Standard SQL allows for a difference between the two types, but in MySQL they are the same. In standard SQL, the precision for NUMERIC must be exactly the number of digits given in the column definition. The precision for DECIMAL must be at least that many digits but is allowed to be more. In MySQL, the precision is exactly as given, for both types. BIT Types The BIT data type represents bit-field values. BIT column specifications take a width indicating the number of bits per value, from 1 to 64 bits. For a BIT(n) column, the range of values is 0 to 2 n 1, and the storage requirement is approximately INT((n+7)/8) bytes per value. BIT columns can also be assigned values using numeric expressions. To write literal bit values in binary format, the literal-value notation b'val' can be used, where val indicates a value consisting of the binary digits 0 and 1. For example, b'1111' equals 15 and b'1000000' equals 64. Rule of thumb for storage size: n=8 takes 1 Byte.

Instructor Notes: In any application, memory usage is an area that must be managed properly to ensure good performance. If memory usage is not considered early on, the consequences can be devastating as the ______________________________________________________________________________________________ application grows. Data types is one of those areas where a small memory problem can become a big one as the data grows. Taking the time in the very beginning to discuss how data types affect memory is important to ______________________________________________________________________________________________ anyone involved in developing web applications (or any type of application with MySQL). ______________________________________________________________________________________________ Fixed-Point numerical types storage/comparison changed in 5.0. Older versions did comparisons/math using DOUBLES, which makes them not exact. The BIT type new in version 5.0.3 ______________________________________________________________________________________________

Page 6-7

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

6.3.2

String Data Types


A string data type is a data type modeled on the idea of a formal string. They are commonly used to store text or binary data. Types are available to hold values of varying maximum lengths and can be chosen according to if the values are to be treated as text, binary or integer. Strings are such an important and useful data type that they are implemented in nearly every programming language. Comparison Values
Text (Non-Binary)

Type
CHAR VARCHAR TEXT BINARY VARBINARY BLOB ENUM SET

Description
Fixed-length character string Variable-length character string Variable-length character string Fixed-length binary string Variable-length binary string Variable-length binary string Enumeration consisting of a fixed set of legal values Set consisting of a fixed set of legal values

Binary

Integer

Text String Type Summary For the storage requirement values, M represents the maximum length of a column. L represents the actual length of a given value, which may be 0 to M. Type
CHAR(M) TINYTEXT TEXT LONGTEXT

Storage Required
M characters L characters + 1 byte L characters + 2 bytes L characters + 4 bytes

Maximum Length
255 characters 255 characters 65,535 characters 16,777,215 characters 4,294,967,295 characters

VARCHAR(M) L characters plus 1 or 2 bytes 65,535 characters (subject to limitations)

MEDIUMTEXT L characters + 3 bytes

Binary String Type Summary For the storage requirement values, M represents the maximum length of a column. L represents the actual length of a given value, which may be 0 to M. Type
BINARY(M) TINYBLOB BLOB MEDIUMBLOB LONGBLOB

Storage Required
M bytes L + 1 bytes L + 2 bytes L + 3 bytes L + 4 bytes 255 bytes

Maximum Length
65,535 bytes (subject to limitations) 255 bytes 65,535 bytes 16,777,215 bytes 4,294,967,295 bytes

VARBINARY(M) L bytes plus 1 or 2 bytes

Integer Values Type


ENUM SET

Storage Required
2^n values = n Bits 1 value = 1 Bit

Maximum Length
65,535 distinct values 64 members

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-8

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

6.3.3

Temporal Data Types


Date and time data types are referred to as temporal data types. MySQL provides data types for storing different kinds of temporal information. In the following descriptions, the terms YYYY, MM, DD, hh, mm, and ss stand for a year, month, day of month, hour, minute, and second value, respectively. Type DATE TIME Storage Required 3 bytes 3 bytes Range '1000-01-01' to '9999-12-31' '-838:59:59' to '838:59:59' '1000-01-01 00:00:00' to '9999-12-31 23:59:59' '1970-01-01 00:00:00' to mid-year 2037 1901 to 2155 (for YEAR(4)), 1970 to 2069 (for YEAR(2))

DATETIME 8 bytes TIMESTAMP 4 bytes YEAR 1 byte

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-9

Developing Dynamic Web Applications with MySQL and PHP


85

Chapter 6 - Managing Database Tables

6.4

Creating Database Tables


After the database structure is designed and the database has been created, individual tables can be added. Using accurate assignment of data types and their associated options, tables can be added to the database. The command syntax is shown below, including the various column and table options; CREATE TABLE <table> ( <column name> <column type> [<column options>], [<column name> <column type> [<column options>],,] [<index list>] )[<table options>]; Example: mysql> CREATE TABLE CountryLanguage ( -> CountryCode CHAR(3) NOT NULL, -> Language CHAR(30) NOT NULL, -> IsOfficial ENUM('True', 'False') NOT NULL DEFAULT 'False', -> Percentage FLOAT(3,1) NOT NULL, -> PRIMARY KEY(Country, Language) -> )ENGINE = MyISAM COMMENT='Lists Language Spoken'; A line-by-line description of the above CREATE TABLE statement:

1. The table being created will be given the name CountryLanguage - this is the beginning of a
grouping of column definitions that ends on the line 7 beginning with ") ENGINE = ..."

2. CountryCode--column in the table with a datatype of Char (size of 3) that cannot have an unknown
or NULL value, and the comma (,) means continue defining columns

3. Language--another column of a datatype CHAR and a length of 30 that also can not have an
unknown or NULL value

4. IsOfficial--column name ENUM is a datatype with only the values of True or False ('True' , 'False')
and NOT NULL means each row must be true or false not (unknown) If the value is unknown it will list as false by the phrase DEFAULT 'False' 5. Percentagecolumn with a datatype of FLOAT and values assigned at 3 total digits with 1 digit to the right of the decimal, cannot have NULL values 6. PRIMARY KEY--defines the type of index and what columns it applies, in this case a combo of both Country and Language to define a unique identifier of each row or each entity 7. ) is the closing of a group of definitions describing the column names and index, ENGINE defines the pluggable storage engine used to manage the data and retrieve the data. (MyISAM in this case), COMMENT is phrases used by the person defining the table to explain the table (the purpose is to list the languages used in each given country), the ; means execute this command and create the table CountryLanguage.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-10

Developing Dynamic Web Applications with MySQL and PHP


86

Chapter 6 - Managing Database Tables

6.4.1

Displaying Table Creation Information


The SHOW CREATE TABLE can be used to view the exact statement that was used to create an existing table. This can be helpful in understanding the structure of a table. It can also be used as a basis for the syntax to create a new table. For example to show CREATE TABLE command to create the city table use the following statement; mysql> SHOW CREATE TABLE CountryLanguage\G *************************** 1. row *************************** Table: CountryLanguage Create Table: CREATE TABLE `countrylanguage` ( `Country` char(3) NOT NULL, `Language` char(30) NOT NULL, `IsOfficial` enum('True','False') NOT NULL DEFAULT 'False', `Percentage` float(3,1) NOT NULL, PRIMARY KEY (`Country`,`Language`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Lists Language Spoken' 1 row in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-11

Developing Dynamic Web Applications with MySQL and PHP


87

Chapter 6 - Managing Database Tables

6.4.2

Table Properties
MySQL manages tables using storage engines, each of which handles tables that have a given set of characteristics. Different storage engines have differing performance characteristics, and can be chosen based on which engine most closely matches the characteristics that are needed. For example, a table may require transactional capabilities and guaranteed data integrity even if a crash occurs, or it may require a very fast lookup table stored in memory for which the contents can be lost in a crash and reloaded at the next server startup. With MySQL, these choices can be made on a per-table basis. Any given table is managed by a particular storage engine. Options can be added to the CREATE TABLE command in order to control the manner in which the entire table is handled. ENGINE={MyISAM | InnoDB | MEMORY} Indicates the storage engine to be used for the table MyISAM is the default storage engine (unless --default-storage-engine has been set) COMMENT='<comment>' Up to 60 characters of free form text CHARACTER SET=<character set> Specifies the character set for the table Precede with DEFAULT to assign the default character set Can be shortened to CHARSET COLLATE=<collation_name> Specifies the collation for the table Precede with DEFAULT to assign the default collation

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-12

Developing Dynamic Web Applications with MySQL and PHP


88

Chapter 6 - Managing Database Tables

6.4.3

Column Options
A table must have at least one column. Each column has to have a name and a data type. And there are several options for column data that can be used as part of the table creation command. These options modify how MySQL handles the associated column. Such as the following; NULL Allows values stored as NULL The default option NOT NULL Disallows NULL values Saves response time and in some cases disk space A necessity for a PRIMARY KEY DEFAULT If no value is specified by the user at insertion of new data, this data will be stored in the field AUTO_INCREMENT Only works for Integer data type columns Automatically generates a unique, positive number sequence for each row in a table (for UNIQUE or PRIMARY KEY columns) Using NULL will insert the next available number instead Not specifying a value for the column will also work Cannot exceed the upper limit of the specific data type (i.e. 255 for a TINYINT) If rows are deleted containing values at the high end of a sequence, those values are not reused (for specific storage engine tables) KEYS A primary key is a clause assigned to a column that uniquely identifies a single row in the table. A primary key cannot contain NULL values. A foreign key is a column in a table that references the primary key of another table. A unique key is similar to a primary key, except that it can be allowed to contain NULL values. Each non-NULL value uniquely identifies a single row in the table. Example: CREATE TABLE CountryLanguage` ( `CountryCode` char(3) NOT NULL, `Language` char(30) NOT NULL, `IsOfficial` enum('T','F') NOT NULL DEFAULT 'False', `Percentage` float(4,1) NOT NULL DEFAULT '0.0', PRIMARY KEY (`CountryCode`,`Language`) );

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-13

Developing Dynamic Web Applications with MySQL and PHP


89

Chapter 6 - Managing Database Tables

6.4.4

Temporary Tables
It is sometimes useful to create tables for temporary use. This can be done by using the CREATE TEMPORARY TABLE command rather than CREATE TABLE. A temporary table differs from a nontemporary table in the following ways: It's visible only to the client (and connection) that created it and may be used only by that client (and connection). This means that different clients (even with different connections) can create temporary tables that have the same name and no conflict occurs. A temporary table exists only for the duration of the connection in which it was created. The server drops a temporary table automatically when the client connection ends if the client has not already dropped it. A temporary table may have the same name as a non-temporary table. The non-temporary table becomes hidden to the client that created the temporary table as long as the temporary table exists. A temporary table can be renamed only with ALTER TABLE. The RENAME TABLE command can not be used.

In this example a temporary table is created from the existing City table, which contains the names of all the cities in Texas (US); CREATE TEMPORARY TABLE texas SELECT Name FROM City WHERE District='Texas';

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-14

Developing Dynamic Web Applications with MySQL and PHP


90

Chapter 6 - Managing Database Tables

6.5

Altering Tables
After creating a table, there might be a change of requirements that forces changes to the structure of the table. If that happens, the table's structure can be modified without having to re-create the table. This section addresses some of the methods available for modifying the table structure and data.

6.5.1

Add Columns
For example, to add a column named Id to the eu_countries table, the following statement can be issued:
ALTER TABLE eu_countries ADD Id INT(6) NOT NULL;

That ALTER TABLE/ADD statement changes the table structure as follows:


mysql> DESCRIBE eu_countries; +----------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+---------------+------+-----+---------+-------+ | name | char(52) | NO | | NULL | | | new_population | decimal(12,1) | NO | | 0.0 | | | id | int(6) | NO | | NULL | | +----------------+---------------+------+-----+---------+-------+ 3 rows in set (#.## sec)

Note: Column names within a table must be unique, so columns with the same name can not be added as one that already exists in the table. Also, column names are not case sensitive, so if the table already contains a column named id, a new column can not be added using any of these names: ID, id, Id, or iD. They all are considered to be the same. To add a column at a specific position within a table row, use FIRST or AFTER col_name. The default is to add the column last. Adding a column to a table does not populate the rows with standard values (unless a default value or auto_increment is selected). In a query, they will appear as default or NULL (if allowed) values:
mysql> SELECT * FROM eu_countries; +------------------------+---------------+----+ | Name | NewPopulation | Id | +------------------------+---------------+----+ | Albania | 5101800.0 | 0 | | Andorra | 117000.0 | 0 | | Austria | 12137700.0 | 0 | | Belgium | 15358500.0 | 0 | | Bulgaria | 12286350.0 | 0 | | Bosnia and Herzegovina | 5958000.0 | 0 | : : : : +------------------------+---------------+----+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-15

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

6.5.2

Remove Columns
To drop a column, use a DROP clause that names the column to be removed:
ALTER TABLE eu_countries DROP id;

The above ALTER TABLE/DROP statement changes the table structure as follows:
+----------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+---------------+------+-----+---------+-------+ | name | char(52) | NO | | NULL | | | new_population | decimal(12,1) | NO | | 0.0 | | +----------------+---------------+------+-----+---------+-------+

6.5.3

Modifying Columns
One method to alter a column definition is to use a MODIFY clause. The name of the column to be changed must be specified, followed by its new definition. Assume that the ID column's data type must be changed from INT to BIGINT, to allow the table to accommodate larger identification numbers. In addition, the column needs to be changed to UNSIGNED to disallow negative values. The following statement accomplishes this task:
ALTER TABLE eu_countries MODIFY new_population BIGINT(12) NOT NULL;

That ALTER TABLE statement changes the table structure as follows:


+----------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+---------------+------+-----+---------+-------+ | name | char(52) | NO | | NULL | | | new_population | decimal(12,0) | NO | | NULL | | +----------------+---------------+------+-----+---------+-------+

To disallow NULL in the column, the column definition provided for MODIFY must include the NOT NULL attribute, even if the column was originally defined with NOT NULL. This is true for other column attributes as well. If they are not specified explicitly, the new definition won't carry them over from the old definition. The above ALTER TABLE/MODIFY statement changes the table row contents as follows:
+------------------------+----------------+ | name | new_population | +------------------------+----------------+ | Albania | 5101800 | | Andorra | 117000 | | Austria | 12137700 | | Belgium | 15358500 | | Bulgaria | 12286350 | | Bosnia and Herzegovina | 5958000 | : : : +------------------------+----------------+

Note: MySQL will sometimes try to fit existing data in to the new datatype by applying data type conversions.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-16

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

6.5.4

Changing Columns
The second way to alter a column definition is to use a CHANGE clause. The CHANGE clause enables the modification of both the column's definition and its name. To use this clause, specify the CHANGE keyword, followed by the column's existing name, its new name, and its new definition, in that order. Note that this means the existing name must be specified twice to change only the column definition (and not the name). For example, change the last_name column from CHAR(30) to CHAR(40) without renaming the column as follows: ALTER TABLE head_of_state CHANGE last_name last_name CHAR(40) NOT NULL; To change the name as well (for example, to Surname), provide the new name following the existing name: ALTER TABLE head_of_state CHANGE last_name Surname CHAR(40) NOT NULL; To change a column at a specific position within a table row, use FIRST or AFTER col_name. The default is to change the last column.

91

6.5.5

Renaming Tables
Renaming a table changes neither a table's structure nor its contents. The following statement renames table t1 to t2: ALTER TABLE t1 RENAME TO t2; Another way to rename a table is by using the RENAME TABLE statement: RENAME TABLE t1 TO t2; RENAME TABLE has an advantage over ALTER TABLE in that it can perform multiple table renames in a single operation. One use for this feature is to swap the names of two tables: RENAME TABLE t1 TO tmp, t2 TO t1, tmp TO t2; For TEMPORARY tables, RENAME TABLE does not work. The ALTER TABLE command must be used instead.

6.5.6

Emptying Tables
To remove records from a table without removing the table itself, use the DELETE or TRUNCATE TABLE statement. Either of the following statements completely empties the named table: DELETE FROM t; TRUNCATE TABLE t; DELETE takes an optional WHERE clause that identifies which records to remove. This is useful when only a given subset of records from a table need to be deleted. The following statement removes only those records from t that have a status column value of 'expired', in order by the id column and output limited to 4 rows: DELETE FROM t WHERE status = 'expired' ORDER BY id LIMIT 4; TRUNCATE also will reset the metadata held within the format files of the table being truncated ( .frm ) such as the AUTO_INCREMENT starting value.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-17

Developing Dynamic Web Applications with MySQL and PHP


92

Chapter 6 - Managing Database Tables

6.6

Drop Tables
DROP TABLE removes one or more tables. All table data and the table definition are removed, so be careful with this statement!
DROP [TEMPORARY] TABLE [IF EXISTS] table1;

Use IF EXISTS to prevent an error from occurring for tables that do not exist. An error is generated for each non-existent table when using IF EXISTS. The TEMPORARY keyword has the following effects: 1. 2. The statement drops only TEMPORARY tables. The statement does not end an ongoing transaction

Using TEMPORARY is a good way to ensure that non-TEMPORARY table is not deleted by accident. DROP TABLE examples:
DROP TABLE table1; DROP TABLE IF EXISTS table1; DROP TEMPORARY TABLE eu_countries_temp;

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-18

Developing Dynamic Web Applications with MySQL and PHP


93

Chapter 6 - Managing Database Tables

6.7

Table Indexing
When a row is inserted into a table, the database server does not attempt to put the data in any particular location within the table. Instead, the server simply places the data in the next available location within the file. When a query is sent against the table therefore, the server will need to inspect every row of the table to answer the query. Tables in MySQL can grow very large, and as a table gets bigger, retrievals from it become slower. An index in MySQL serves to assist in finding row data more quickly and easily, much like an index in the back of a technical manual. Database indexes are used to locate rows in a table. Indexes are special structures that, unlike normal tables, are kept in a specific order. Instead of containing all of the data about an entity, however, an index contains only the column(s) used to locate rows in the data table. It also contains information describing where the rows are physically located. Usually, all the indexes required are created when the tables are created. Indexes can be created on single columns or multiple columns (composite indexes). For example, the phone number for an individual in a phone book would use a single index, whereas the last_name and first_name would be grouped together as a composite index. Types of Indexes: MySQL supports several general types of indexes: PRIMARY KEY 1. Only one PRIMARY KEY is allowed per table 2. Uniquely identifies a single row in the table 3. No NULL values are allowed 4. If a duplicate value is INSERTed or UPDATED MySQL will return an error UNIQUE (same rules as the PRIMARY KEY with two exceptions) 1. Allows values stored as NULL 2. Can have multiple UNIQUE indexes in a table 3. Each NON-NULL value uniquely identifies a single row in a table INDEX - Allows multiple identical values Example:
CREATE TABLE `countrylanguage` ( `CountryCode` char(3) NOT NULL default '', `Language` char(30) NOT NULL default '', `IsOfficial` enum('T','F') NOT NULL default 'F', `Percentage` float(4,1) NOT NULL default '0.0', PRIMARY KEY (`CountryCode`,`Language`) ) ENGINE=MyISAM COMMENT 'Lists Languages Spoken'

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-19

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

94

Indexing Tips: Declare a NOT NULL indexed column if possible. NULL requires additional server decisions and can be processed more simply and faster. Avoid over indexing; don't index a column just because it can be indexed. If a column is never going to be referred to in comparisons, then there's no need to index it. Every index created slows down table updates. If a row is inserted, an entry must be added to each of the table's indexes. An index on a column that has very few distinct values is unlikely to do much good. Choose unique and non-unique indexes appropriately. The choice may be influenced by the data type of a column and the level of distinctness. Index a column prefix rather than the entire column. Shortening the length of the key values can improve performance by reducing the amount of disk I/O needed. Avoid creating multiple indexes that overlap (have the same initial columns). SHOW INDEX: To view the status of indexes in a table use the following statement; SHOW INDEX FROM <table>; Example:
mysql> SHOW INDEX FROM countrylanguage\G *************************** 1. row *************************** Table: countrylanguage Non_unique: 0 Key_name: PRIMARY Seq_in_index: 1 Column_name: CountryCode Collation: A Cardinality: NULL Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: *************************** 2. row *************************** Table: countrylanguage Non_unique: 0 Key_name: PRIMARY Seq_in_index: 2 Column_name: Language Collation: A Cardinality: 984 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: 2 rows in set (0.16 sec)

The result of the SHOW INDEX command done on the CountryLanguage table lists two indexes; CountryCode and Language. This confirms the setting of a composite index in the CREATE TABLE command (shown previously). Each specified index will be listed using this statement.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-20

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

6.8

Foreign Keys
A foreign key relationship allows for the declaration of an index in one table to be related to an index in another. It also allows for the placing of constraints on what may be done to the tables in the relationship. The database enforces the rules of this relationship to maintain referential integrity. Using Foreign Keys with InnoDB The InnoDB storage engine supports the use of foreign keys (unlike other storage engines). This capability enables the declaration of relationships between columns in different tables, and InnoDB maintains integrity between the tables by prohibiting operations that violate those relationships. For example, the following restrictions must be addressed: A table must contain only records with ID values that are known in another reference table. If an ID in the referenced table is changed, the ID in all matching records in the referencing table must be changed to match. If a record with a given ID in the referenced table is deleted, all records with the matching ID in the referencing table must also be deleted.

95

The following example demonstrates some of the ways in which InnoDB provides referential integrity between tables. It shows how to define a foreign key relationship that enforces the requirements just described. The example is based on the implicit relationship between the Country and City tables in the world database: Each Country record has a Code column that specifies a unique country code. Each City record has a CountryCode column that matches the code for the country in which the city is located.

The relationship is only implicit because Country and City are MyISAM tables: MyISAM does not have any syntax for specifying the relationship explicitly and provides no means for enforcing it. This means that Code value could be changed in the Country table and any City records with the corresponding country code would not be changed to match. A Country table row could be deleted but the corresponding City records would not be deleted. In either case, the City records would become orphaned because there is no longer any corresponding Country table record for them. InnoDB does not allow these types of referential integrity failures to occur.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-21

Developing Dynamic Web Applications with MySQL and PHP


96

Chapter 6 - Managing Database Tables

To define a country-city relationship explicitly, derive a couple of InnoDB tables from the MyISAM tables. We'll call these tables country_parent and city_child to illustrate that the country records are the parent records and the city records are the child records that depend on them: CREATE TABLE country_parent ( code CHAR(3) NOT NULL, name CHAR(52) NOT NULL, PRIMARY KEY (code) ) ENGINE = InnoDB; CREATE TABLE city_child ( id INT NOT NULL AUTO_INCREMENT, name CHAR(35) NOT NULL, country_code CHAR(3) NOT NULL, PRIMARY KEY (ID), INDEX (country_code), FOREIGN KEY (country_code) REFERENCES country_parent (code) ON UPDATE CASCADE ON DELETE CASCADE ) ENGINE = InnoDB; In these two tables, the column and PRIMARY KEY definitions are the same as in the original Country and City tables. The parts of the syntax that differ from the original tables are the ENGINE table option, which specifies the InnoDB storage engine, and the INDEX and FOREIGN KEY definitions for the CountryCode column in the city_child table. Why InnoDB? It's necessary to use InnoDB because that is the only storage engine that supports foreign keys. (You can specify a FOREIGN KEY clause for other table types, but it would simply be ignored.)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-22

Developing Dynamic Web Applications with MySQL and PHP


97

Chapter 6 - Managing Database Tables

Foreign Key Clause The FOREIGN KEY clause has several parts: It names the column in the referring table (country_code). It names the code column in the country_parent table as the referenced column. This column is the foreign key. It specifies what actions to take if records are modified in the referenced table. The foreign key definition shown specifies the CASCADE action for both UPDATE and DELETE operations. This means that changes in the parent table are cascaded down to the child table. If a code value is changed in the country_parent table, InnoDB changes any corresponding city_child records with that value in the country_code column to match. If a country_parent record is deleted, InnoDB also deletes any city_child records with the same country code. (InnoDB supports actions other than CASCADE, but they are not covered here. Instead of CASCADE a SET NULL or RESTRICT can be specified. In a foreign key relationship, the referring column and the referenced column should have the same data type, and both must be indexed. (If the referring column has no index, InnoDB creates an index on it automatically.) The ON UPDATE and ON DELETE parts are optional. If they are ommitted, InnoDB simply disallows attempts to update or delete code values in the country_parent table if there are city_child records that refer to them.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-23

Developing Dynamic Web Applications with MySQL and PHP

Chapter 6 - Managing Database Tables

Lab 6-B
In this exercise you will interact with the world database and utilize some of the commands that were presented in this chapter. ACTION (You Do) 1. Log in to the mysql client (if not already). COMPUTER RESPONSE / Comment It is easier and more advantageous to design the database components in the MySQL client versus trying to complete the tasks through the PHP interface. If the world database is not available (or not present), please refer to Lab 6-A to create and load the database with the components that will be needed to complete the remainder of this lab. A representation of the City table creation statement is shown.

2. In the mysql client, type the following to use the world database: USE world; 3. Show the create statement for the City table in the world database using the vertical output format option by typing the following in the mysql client: SHOW CREATE TABLE City\G 4. Switch to the test database by typing the following command in the mysql client: USE test; 5. Create a table using the mysql client called 'db' which will use the storage engine InnoDB and add a comment of 'Create Table lab': CREATE TABLE db (name char (10)) ENGINE InnoDB COMMENT 'Create Table lab'; 6. Show the create statement for the db table in the test database using the vertical output format option by typing the following in the mysql client: SHOW CREATE TABLE db\G

Sets the current database to use the test database.

Returns an OK message if the table is created successfully.

A representation of the db table creation statement is shown. Confirm that the table property settings are correct.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-24

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 7. In the test database, create a new MyISAM table called altering with one column called foo which is data type text by typing the following in the mysql client: CREATE TABLE altering (foo text) ENGINE=MyISAM; 8. Use the DESCRIBE command to show the current structure of the altering table by typing the following in the mysql client: DESCRIBE altering; 9. Add a column to the altering table called id, with a data type of tinyint at a width of 4 digits that will not accept null values by typing the following in the mysql client: ALTER TABLE altering ADD id TINYINT(4) NOT NULL; 10. Use the DESCRIBE command to show the structure of the altering table now by typing the following into the mysql client: DESCRIBE altering; 11. Remove the id column from the altering table by typing the following in the mysql client: ALTER TABLE altering DROP id; 12. Use the DESCRIBE command to show the current structure of the altering table by typing the following in the mysql client: DESCRIBE altering; 13. Modify the foo column from the altering table; change the data type to char with a width of 8 and no longer allow it to accept null values by typing the following in the mysql client: ALTER TABLE altering MODIFY foo char(8) NOT NULL; 14. Use the DESCRIBE command to show the current structure of the altering table by typing the following in the mysql client: DESCRIBE altering; 15. Rename the altering table to foo typing the following in the mysql client:

Chapter 6 - Managing Database Tables

COMPUTER RESPONSE / Comment Returns an OK message if the table is created successfully.

Confirm that the foo column has been created with the text data type.

Returns an OK message if the table was altered successfully.

Confirm that the id column has been added with the proper attributes.

Returns an OK message if the table was altered successfully. Confirm that the id column has been removed.

Returns an OK message if the table was altered successfully.

Confirm that the Id column has been modified with the proper values.

Returns OK if the table was renamed successfully

RENAME TABLE altering TO foo; ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-25

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 16. Verify the altering table was changed to foo by typing the following in the mysql client: SHOW TABLES; 17. Remove the db table and show the list of tables again by typing the following commands in the mysql client: DROP TABLE db; SHOW TABLES; 18. Remove the foo table and show the list of tables again by typing the following commands in the mysql client: DROP TABLE foo; SHOW TABLES; 19. Change the database to world by typing the following in the mysql client: USE world; 20. Create the two tables, using the mysql client, listed below (country_parent and city_child): mysql> CREATE TABLE country_parent -> (code CHAR(3) NOT NULL, -> name CHAR(52) NOT NULL, -> PRIMARY KEY (code) -> ) ENGINE = InnoDB; and mysql> CREATE TABLE city_child -> (id INT NOT NULL AUTO_INCREMENT, -> name CHAR(35) NOT NULL, -> country_code CHAR(3)NOT NULL, -> PRIMARY KEY (id), -> INDEX (country_code), -> FOREIGN KEY (country_code) -> REFERENCES country_parent (code) -> ON UPDATE CASCADE -> ON DELETE CASCADE -> ) ENGINE = InnoDB;

Chapter 6 - Managing Database Tables

COMPUTER RESPONSE / Comment Confirm that the altering table was renamed to the foo table. The first SQL statement will return an OK message if the table was deleted. The second SQL statement will list the tables currently in the test database. Verify that the db table has been removed.

The first SQL statement will return an OK message if the table was deleted. The second SQL statement will list the tables currently in the test database. Verify that the foo table has been removed.

Sets the current database to use the world database.

These two tables define the country-city relationship explicitly. We'll call these tables country_parent and city_child to illustrate that the country records are the parent records and the city records are the child records that depend on them.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-26

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 21. View the create statement for both tables to confirm the index settings: mysql> SHOW CREATE TABLE country_parent\G and mysql> SHOW CREATE TABLE city_child\G

Chapter 6 - Managing Database Tables

COMPUTER RESPONSE / Comment The two SQL statements show the attributes for both tables, including the index/key settings, as specified by the CREATE TABLE statements.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-27

Developing Dynamic Web Applications with MySQL and PHP


98

Chapter 6 - Managing Database Tables

Lab 6-C
In this exercise, you will create the tables that will be associated with our online photo album web application.

1. 2. 3. 4.

Login in to the mysql client using the login name and password provided by your instructor. View the existing databases that the MySQL Server is maintaining. Utilize the photo_album database. Create the first table called customers that will store the information related to the customers who have purchased access to the online photo album. The table will contain the following columns: email_customer f_name l_name addr1 addr2 addr_city addr_state addr_zip primary_phone secondary_phone term_date active_customer customers VARCHAR(50) NOT NULL DEFAULT '', PRIMARY KEY VARCHAR(20) NOT NULL DEFAULT '' VARCHAR(30) NOT NULL DEFAULT '' VARCHAR(30) NOT NULL DEFAULT '' VARCHAR(30) NULL VARCHAR(25) NOT NULL DEFAULT '' CHAR(3) NOT NULL DEFAULT '' CHAR(10) NOT NULL DEFAULT '' CHAR(12) NOT NULL DEFAULT '' CHAR(12) NULL DATE NOT NULL DEFAULT 0 ENUM('True', 'False') NOT NULL DEFAULT 'True'

5.

Create the second table called logins that will contain the login authentication data. Each customer will be able to have up to 5 logins for their site (this could be given to family and friends to access their photos). The table will contain the following columns: login_name email_customer f_name l_name passwd last_login active_login VARCHAR(30) VARCHAR(50) VARCHAR(20) VARCHAR(30) VARCHAR(30) DATETIME ENUM('True', 'False') logins NOT NULL DEFAULT '', PRIMARY KEY NOT NULL DEFAULT '', FOREIGN KEY NOT NULL DEFAULT '' NOT NULL DEFAULT '' NOT NULL DEFAULT '' NOT NULL DEFAULT 0 NOT NULL DEFAULT 'True'

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-28

Developing Dynamic Web Applications with MySQL and PHP 6.

Chapter 6 - Managing Database Tables

Create the third table called images that will contain the information about the photos. The image information will include information to connect the images to other tables, the size of the image and the name of the image that was stored. Later in the course, the code will be created to upload these images with the image information being stored in the database. The table will contain the following columns: images AUTO_INCREMENT NOT NULL, PRIMARY KEY NOT NULL DEFAULT '' NOT NULL DEFAULT '' NOT NULL DEFAULT '' NOT NULL DEFAULT '' NOT NULL DEFAULT 0 NOT NULL DEFAULT 'True'

id_image login_name image_size image_name file_name image_date active_image 7.

INT, UNSIGNED VARCHAR(30) VARCHAR(30) VARCHAR(60) VARCHAR(60) DATE ENUM('True', 'False')

Create the last table called comments that will be used to keep track of the comments attached to each picture. Each login associated with the images will be able to provide comments against the picture. The table will contain the following columns: comments AUTO_INCREMENT NOT NULL, PRIMARY INT, UNSIGNED KEY VARCHAR(30) NOT NULL DEFAULT '' INT, UNSIGNED NOT NULL TEXT NOT NULL DEFAULT '' TIMESTAMP NOT NULL ENUM('True', 'False') NOT NULL DEFAULT 'True'

id_comment login_name id_image comments log_date active_comment 8. 9.

View the list of tables located in the photo_album database. Review the details of each table created and verify that the tables were designed properly. If they are not correct, use the ALTER TABLE command to make the changes to correct the problems.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-29

Developing Dynamic Web Applications with MySQL and PHP


99

Chapter 6 - Managing Database Tables

6.9

Chapter Summary
In this chapter, you have learned to: Define Table Properties Tables are contained in databases, and in MySQL each database has an associated "data directory" to store all the physical components of the database, to include tables. In addition to the physical representation of the table, there is also the better known logical aspect of the table. This logical aspect is represented in rows and columns. There are numerous storage engines that MySQL supports; however the most common storage types that are used with PHP are MyISAM, InnoDB, NDB and MEMORY. In MySQL the data types available can be broken down into three major categories: Numeric, String and Temporal After the database structure is designed and the database has been created, individual tables can be added. Using accurate assignment of data types and their associated options, tables can be added to the database. After creating a table, there might be a change of requirements that forces changes to the structure of the table. If that happens, the table's structure can be modified without having to re-create the table. DROP TABLE removes one or more tables. All table data and the table definition are removed, so be careful with this statement! An index in MySQL serves to assist in finding row data more quickly and easily, much like an index in the back of a technical manual. Database indexes are used to locate rows in a table. Indexes are special structures that, unlike normal tables, are kept in a specific order. Instead of containing all of the data about an entity, however, an index contains only the column(s) used to locate rows in the data table. It also contains information describing where the rows are physically located. Usually, all the indexes required are created when the tables are created. The InnoDB storage engine supports the use of foreign keys (unlike other storage engines). This capability enables the declaration of relationships between columns in different tables, and InnoDB maintains integrity between the tables by prohibiting operations that violate those relationships.

List the Most Common Storage Engines Available

Understand MySQL Data Types

Create a Table

Alter a Table

Remove a Table

Explain and Use Indexes

Assign and Utilize Foreign Keys

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 6-30

Developing Dynamic Web Applications with MySQL and PHP

101

CHAPTER 7 SQL SELECT COMMANDS

100

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

102

7
7.1

SQL SELECT COMMANDS


Learning Objectives
This chapter provides the methods and tools needed to utilize SQL query commands for the purpose of retrieving data from the MySQL Database. At the completion of this chapter, you will be able to: Execute Table Data Queries Using the SELECT Statement Retrieve Summary Data Using Aggregate Queries

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-1

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

103

7.2

SELECT Statements
The SELECT statement is primarily used to retrieve zero or more rows from one or more tables in a database. In MySQL, SELECT is the most commonly used DML (Data Manipulation Language) command. In specifying a SELECT query, the user specifies a description of the desired result set. It is built with optional clauses that specify how and what data to retrieve. The general command syntax is shown below; SELECT [<clause options>] <column list> [FROM] <table> [<clause options>]; Basic SELECT statement example using world database (and the result data):
mysql> SELECT Name FROM Country; +--------------------------------------+ | Name | +--------------------------------------+ | Afghanistan | | Netherlands | | Netherlands Antilles | | Albania | ... | French Southern Territories | | Unites States Minor Outlying Islands | +--------------------------------------+ 239 rows in set (#.## sec)

The above example shows a typical query, which retrieves all the rows in a given column, from a specific table. Multiple columns can be listed in a query, as well. SELECT can also be used to complete arithmetic operations, like this simple addition calculation;
mysql> SELECT 1+2; +-----+ | 1+2 | +-----+ | 3 | +-----+ 1 row in set (#.## sec) 104

Basic Uses of SELECT There are many clauses, and combinations thereof, that can be used with a SELECT statement to yield particular table query results. They range from very basic, commonly-used options to very specialized and complex. The following basic, optional clauses will be covered in this section: Clauses DISTINCT FROM WHERE ORDER BY LIMIT Definition Eliminates duplicate row data Specifies what table(s) to retrieve data from Decides what data to show Sorts data by specified order criteria Reduces the amount of records received

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-2

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

Example of SELECT statement with clauses: SELECT DISTINCT values_to_display FROM table_name WHERE expression ORDER BY how_to_sort LIMIT row_count; The above syntax shows the correct order and usage of each of the above optional clauses. This statement is specifically selecting distinct data rows from a named table, where some expression defines what data to show and it is ordered by a sorting criteria, and the number of rows to be retrieved is limited by some number. Note: It is important to keep the clauses in their proper order of precedence. Otherwise, the result will be an error. SELECT Tips The database and proper table names can be case-sensitive, but commands (and clauses) are not. Only if the system (host) is set as case-sensitive When issuing statements using the command line client, you may use \c to abort a command A \G at the end of a command (in place of the ;) will return SELECT results in output by the row, instead of the default of a tabular formathelps when output would be too wide for screen

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-3

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

7.2.1

SELECT with DISTINCT If a query returns a result that contains duplicate rows, the duplicates can be removed to produce a result set in which every row is unique. To do this, include the clause DISTINCT after SELECT and before the column list. Caution needs to be present when using DISTINCT due to the fact that DISTINCT will compare whole rows when processing. In the case below, the query results in a set that includes duplicate rows:
mysql> SELECT Continent FROM Country; +---------------+ | Continent | +---------------+ | Asia | | Europe | | North America | | Europe | | Africa | | Oceania | ... | Antarctica | | Oceania | +---------------+ 239 rows in set (#.## sec)

By adding DISTINCT to the statement, the duplicates are removed and only unique rows are returned:
mysql> SELECT DISTINCT Continent FROM Country; +---------------+ | Continent | +---------------+ | Asia | | Europe | | North America | | Africa | | Oceania | | South America | | Antarctica | +---------------+ 7 rows in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-4

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

DISTINCT NULL Values DISTINCT treats all NULL values within a given column as having the same value. Suppose that a table t contains the following rows:
mysql> SELECT i, j FROM t; +-------------+ | i | j | +-------------+ | 1 | 2 | | 1 | NULL | | 1 | NULL | +-------------+

For purposes of DISTINCT, the NULL values in the second column are the same, so the second and third rows are identical. Adding DISTINCT to the query eliminates one of them as a duplicate:
mysql> SELECT DISTINCT i, j FROM t; +-------------+ | i | j | +-------------+ | 1 | 2 | | 1 | NULL | +-------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-5

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

7.2.2

SELECT with WHERE The WHERE clause is the mechanism for filtering out unwanted rows from the result set. Rows can be selected by looking for column values that satisfy various criteria, and different types of values can be filtered out. In the statement below, the query is selecting information from three columns, from a given table with a clause where a specific city name is to be used. In other words, it is answering the question"What is the ID and district for the city of New York?", as follows;
mysql> SELECT ID, Name, District FROM City -> WHERE Name = 'New York'; +------+----------+----------+ | ID | Name | District | +------+----------+----------+ | 3793 | New York | New York | +------+----------+----------+ 1 row in set (#.## sec)

Expressions in WHERE clauses can use the following types of operators; Arithmetic -- for calculation Comparison for comparison of column and row data, needed for each (smart) WHERE condition Logical to combine different WHERE conditions Arithmetic Operators Perform mathematical operations on column entity values. Operator + * / DIV % Comparison Operators Compare column entity values. Operator < <= = <=> <> or != >= > BETWEEN x AND Y Definition Less than Less than or equal to Equal to Equal to (works even for NULL values) Not equal to Greater than or equal to Greater than Indicate a range of numerical values Definition Addition Subtraction Multiplication Division Integer Division Modulo (remainder after division)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-6

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

Logical Operators Combine different conditions. Operator AND OR XOR NOT Definition Logical AND Logical OR Logical exclusive-OR Logical negation

Additional options in WHERE expressions; IN is equivalent to a list of comparisons with OR NULL values can be filtered by using IS NULL (WHERE column_name IS NULL) Parenthesis can also be used to group parts of an expression Operators can be performed using constants, table columns and function calls It is also possible to search for combinations of values The example below uses a few of the operators and techniques mentioned above (on the Country table):
mysql> SELECT Name, Population FROM Country -> WHERE Population > 50000000 AND -> (Continent = 'Europe' OR Code ='USA'); +--------------------+------------+ | Name | Population | +--------------------+------------+ | United Kingdom | 59623400 | | Italy | 57680000 | | France | 59225700 | | Germany | 82164700 | | Ukraine | 50456000 | | Russian Federation | 146934000 | | United States | 278357000 | +--------------------+------------+ 7 rows in set (#.## sec)

This example demonstrates the use of the IN clause is a WHERE expression to apply the query to a list of entities;
mysql> SELECT ID, Name, District FROM city -> WHERE Name IN ('New York', 'Rochester', 'Syracuse'); +------+-----------+----------+ | ID | Name | District | +------+-----------+----------+ | 3793 | New York | New York | | 3871 | Rochester | New York | | 3935 | Syracuse | New York | +------+-----------+----------+ 3 rows in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-7

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

7.2.3

SELECT with ORDER BY By default, the rows in the result set produced by a SELECT statement are returned by the server to the client in no particular order. When a query is issued, the server is free to return the rows in any convenient order. This order can be affected by factors such as the order in which the rows are actually stored in the table, or which indexes are used to process the query. If the output rows need to be returned in a specific order, include an ORDER BY clause that indicates how to sort the results. There is no guarantee about the order in which the server returns rows, unless the order is specified. To do so, add an ORDER BY clause to the statement that defines the sort order desired. Single Column Sorts The following example returns country names (in the Country table of the world database) alphabetically by Country Name;
mysql> SELECT Name FROM Country ORDER BY Name; +---------------------+ | Name | +---------------------+ | Afghanistan | | Albania | | Algeria | | American Samoa | | Andorra | | Angola | | Anguilla | | Antarctica | | Antigua and Barbuda | | Argentina | ...

Ordering the ORDER BY Ascending order is the default sort order in an ORDER BY clause. The order in which the results are ordered can be controlled with the keywords ASC (Ascending) or DESC (Descending) following the column names. Ascending means that the lowest value first. The statement below sorts the names of the countries in order by descending alphabetical order;
mysql> SELECT Name FROM Country ORDER BY Name DESC; +----------------------+ | Name | +----------------------+ | Zimbabwe | | Zambia | | Yugoslavia | | Yemen | | Western Sahara | | Wallis and Futuna | | Virgin Islands, U.S. | ...

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-8

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

Multiple Column Sorts Multiple columns can also be sorted simultaneously with differing sorting orders. This is accomplished by separating the column names with a comma, as in the following example;
mysql> SELECT Name, Continent FROM Country -> ORDER BY Continent DESC, Name ASC; +------------------+---------------+ | Name | Continent | +------------------+---------------+ | Argentina | South America | | Bolivia | South America | | Brazil | South America | | Chile | South America | ... | Uzbekistan | Asia | | Vietnam | Asia | | Yemen | Asia | +------------------+---------------+ 239 rows in set (#.## sec)

Note: In the above example, the Continent column is data type ENUM, therefore it is ordered by number of placement in list, not alphabetically.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-9

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

7.2.4

SELECT with LIMIT When a query returns many rows, but only a few of them needs to be seen, add a LIMIT clause. This is a MySQL option that allows the output of a query to be limited to the first rows of the result that would otherwise be returned. The LIMIT clause may be given with either one or two arguments: LIMIT row_count LIMIT skip_count, row_count Each argument must be represented as an integer constant. Expressions, user variables, and so forth can not be used. First Rows from the Beginning When followed by a single integer, row_count, LIMIT returns the first row_count rows from the beginning of the result set. To select just the first 8 rows of a result set, use LIMIT 8;
mysql> SELECT ID, Name FROM City LIMIT 8; +----+----------------+ | ID | Name | +----+----------------+ | 1 | Kabul | | 2 | Qandahar | | 3 | Herat | | 4 | Mazar-e-Sharif | | 5 | Amsterdam | | 6 | Rotterdam | | 7 | Haag | | 8 | Utrecht | +----+----------------+ 8 rows in set (#.## sec)

Skipping Rows When followed by two integers, skip_count and row_count, LIMIT skips the first skip_count rows from the beginning of the result set, and then returns the next row_count rows. To skip the first 20 rows of a result set and then retrieve the next 8, use the following;
mysql> SELECT ID, Name FROM City LIMIT 20,8; +----+----------------+ | ID | Name | +----+----------------+ | 21 | Amersfoort | | 22 | Maastricht | | 23 | Dordrecht | | 24 | Leiden | | 25 | Haarlemmermeer | | 26 | Zoetermeer | | 27 | Emmen | | 28 | Zwolle | +----+----------------+ 8 rows in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-10

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

Limit with ORDER BY LIMIT is especially useful in conjunction with the ORDER BY clause, to put the rows in a particular order. When they are used together, MySQL applies ORDER BY first and then LIMIT. One common use for this is to find the row containing the smallest or largest values in a particular column. For example, to find a row table t containing the smallest id value, use this statement; SELECT * FROM t ORDER BY id LIMIT 1; The following query selects the first 5 highest country populations;
mysql> SELECT Name, Population FROM Country -> ORDER BY population DESC LIMIT 5; +--------------------+------------+ | name | population | +--------------------+------------+ | China | 1277558000 | | India | 1013662000 | | United States | 278357000 | | Indonesia | 212107000 | | Brazil | 170115000 | +--------------------+------------+ 5 rows in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-11

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

105

7.2.5

SELECT with MySQL Query Browser The primary purpose of the MySQL Query Browser is to provide a graphical user interface for performing table queries, such as those covered in this section. All the above SELECT queries can also be executed from the Query Browser GUI window.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-12

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

106

7.3

Aggregating Query Results


A SELECT statement can produce a list of rows that match a given set of conditions. This list provides the details about the selected rows. However, to know about the overall characteristics of the rows, a summary can be more valuable. Aggregate functions (also known as Summary functions) perform summary operations on a set of values, such as counting, averaging, or finding minimum or maximum values. They calculate a single value based on a group of values. However, the resulting value is based only on nonNULL values from the selected rows (with the exception that COUNT(*) counts all rows). Functions such as AVG() that calculate summary values for groups are known as aggregate functions because they are based on aggregates or groups of values. There are several aggregate functions. Some of the most common are as follows; Aggregate Functions MIN() MAX() SUM() AVG() STD() COUNT() GROUP_CONCAT() Definition Find the smallest value Find the largest value Summarize numeric value totals Summarize numeric value averages Returns the standard deviation Counts rows, non-null values, or the number of distinct values Concatenates a set of strings to produce a single string

All the functions can be used with the DISTINCT keyword (although it's useless for MAX() and MIN()). In the following example the COUNT(*) function is being used to get a count of all rows in the Country table of the world database; mysql> SELECT COUNT(*) FROM Country; +----------+ | COUNT(*) | +----------+ | 239 | +----------+ 1 row in set (#.## sec) Now specifying a count of Capital yields a different result, due to the fact that not every country has a Capital associated with it. Therefore, the NULL values are not included in the count; mysql> SELECT COUNT(Capital) FROM Country; +----------------+ | COUNT(Capital) | +----------------+ | 232 | +----------------+ 1 row in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-13

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

Lab 7-A
In this exercise you will perform SELECT commands against the world database to reinforce the knowledge you have just received. If you do not have the world database loaded, please do so now (contact your instructor if you are unsure how to accomplish this.) ACTION (You Do) 1. In the world database, issue a SELECT statement which will retrieve the Continent column from the Country table by typing the following in the mysql client: SELECT Continent FROM Country; COMPUTER RESPONSE / Comment Will return a list 239 continents, one for each country. (Notice that the list does not show the name of the country and many continents are repeated several times.) Note: If you are not sure of the login name or password to login into the mysql client, please contact your instructor for assistance. You will notice that the same number of records is returned, but now the result is two columns with the Name and Continent headings.

2. Issue the same SELECT statement and add the country Name to the column list by typing the following in the mysql client: SELECT Continent, Name FROM Country; 3. Issue a SELECT statement which will retrieve all the Region column data from the Country table by typing the following in the mysql client: SELECT Region FROM Country; 4. Issue a SELECT statement which will retrieve only the distinct Region column data from the Country table by typing the following in the mysql client: SELECT DISTINCT Region FROM Country; 5. Issue a SELECT/WHERE statement which will retrieve all columns from the City table where the id number of 3875 by typing the following in the mysql client: SELECT * FROM City WHERE ID = 3875;

Will return a list 239 regions, one for each country. (Notice that many regions are repeated several times.)

Will return a list 25 distinct regions. (Notice that no regions are repeated.)

This SELECT statement will return a single row of data associated with the specified id.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-14

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

ACTION (You Do) 6. Issue a SELECT/WHERE statement which will retrieve names from the Country table where the population is less than 1000 by typing the following in the mysql client: SELECT Name FROM Country WHERE Population < 1000; 7. Issue a SELECT/ORDER BY statement which will retrieve the name of all cities from the City table in descending order by name by typing the following in the mysql client: SELECT Name FROM City ORDER BY Name DESC; 8. Issue a SELECT/ORDER BY statement which will retrieve the CountryCode and language from the CountryLanguage table where the language is Swedish, in descending order by country code by typing the following in the mysql client: SELECT CountryCode, Language FROM CountryLanguage WHERE Language = 'Swedish' ORDER BY CountryCode DESC; 9. Issue a SELECT/LIMIT statement which will retrieve the name of the cities from the City table in ascending order by name with a limit of 10 rows to return by typing the following in the mysql client: SELECT ID, Name FROM City ORDER BY Name ASC LIMIT 10; 10. Issue a SELECT/LIMIT statement which will retrieve the CountryCode and language from the CountryLanguage table where the language is Chinese, in descending order by percentage, limit result to 2 rows by typing the following in the mysql client: SELECT CountryCode, Language FROM CountryLanguage WHERE Language = 'Chinese' ORDER BY CountryCode DESC LIMIT 2;

COMPUTER RESPONSE / Comment This SELECT statement returns the list of country names that fit the criteria specified.

This SELECT statement returns a list of all city names in descending alphabetical order.

This SELECT statement returns a two column list of country codes and corresponding languages in descending alphabetical order by country codes. Will return a 4 row list.

This SELECT statement returns a list of 10 city names in ascending alphabetical order; however, the ID's are not in order and are not sequential.

This SELECT statement returns a two column list of country codes and corresponding languages in descending alphabetical order by country codes. Will return a 2 row list; +-------------+----------+ | CountryCode | Language | +-------------+----------+ | CHN | Chinese | | SGP | Chinese | +-------------+----------+ 2 rows in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-15

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

ACTION (You Do) 11. Issue a SELECT/LIMIT statement which will retrieve all columns for countries where the GNP that is greater than the old GNP, in order by country name, with a limit of 3 rows by typing the following in the mysql client: SELECT * FROM Country WHERE GNP > GNPOld ORDER BY Name LIMIT 3\G 12. Open the MySQL Query Browser and connect using the following information: Server Host: localhost Username: root Password: <password>* Default Database: world 13. Execute the following SELECT/FROM statement within the Query Browser: SELECT Continent FROM Country

COMPUTER RESPONSE / Comment This SELECT statement returns all country table data for three countries (3 rows).

Opens the MySQL Query Browser GUI window, with the world database opened in the Schemata field on the right-hand side. The password is the same password as used when logging into the mysql client. If you are not sure of the password, please contact your instructor for assistance. Enter the statement within the open field at the topcenter of the window. Use the green Execute button to the right of the field to perform the query. The results will appear in the Resultset 1 window below the command field, and should be identical to those in step 1. (Use the scroll bars to scroll both horizontally and vertically, if needed.)

14. Execute the following SELECT/DISTINCT within the Query Browser: SELECT DISTINCT Region FROM Country 15. Execute the following SELECT/WHERE statement from within the Query Browser: SELECT * FROM City WHERE ID = 3875 16. Execute the following SELECT/ORDER BY statement from within the Query Browser: SELECT Name FROM City ORDER BY Name DESC 17. Execute the following SELECT/LIMIT statement from within the Query Browser: SELECT Name FROM City ORDER BY Name ASC LIMIT 10;

Enter and execute the statement. The results will appear in the Resultset 1 window, and should be identical to those in step 3.

Enter and execute the statement. The results will appear in the Resultset 1 window, and should be identical to those in step 5. Enter and execute the statement. The results will appear in the Resultset 1 window, and should be identical to those in step 7.

Enter and execute the statement. The results will appear in the Resultset 1 window, and should be identical to those in step 9.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-16

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

107

Lab 7-B
In this exercise, you will load data into the tables associated with the photo_album database. Once loaded, you will perform SELECT statements against the data using the tools taught in this chapter: 1. 2. 3. 4. 5. 6. 7. Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). In the photo_album database, load the /tmp/photo_album.sql data file into the database. Perform an aggregate select against each table to count the number of records located in each table. Using the customers table, list the customers who are active from closest to farthest termination date (term_date). Using the logins table, list those with active logins and have logged in during the month of April 2007. Using the images table, list the active file names (file_name) from the most recent date to the oldest dates (image_date). Using the comments table, list the user with the most active comments.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-17

Developing Dynamic Web Applications with MySQL and PHP

Chapter 7 - SQL Select Commands

108

7.4

Chapter Summary
In this chapter, you have learned to: Execute table data Queries Using the SELECT statement The SELECT statement is primarily used to retrieve zero or more rows from one or more tables in a database. In MySQL, SELECT is the most commonly used DML (Data Manipulation Language) command. In specifying a SELECT query, the user specifies a description of the desired result set. It is built with optional clauses that specify how and what data to retrieve. A SELECT statement can produce a list of rows that match a given set of conditions. This list provides the details about the selected rows. However, to know about the overall characteristics of the rows, a summary can be more valuable. Aggregate functions (also known as Summary functions) perform summary operations on a set of values, such as counting, averaging, or finding minimum or maximum values. They calculate a single value based on a group of values.

Retrieve Summary Data using Aggregate Queries

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 7-18

Developing Dynamic Web Applications with MySQL and PHP

110

CHAPTER 8 SQL EXPRESSIONS


109

Developing Dynamic Web Applications with MySQL and PHP


111

Chapter 8- SQL Expressions

8
8.1

SQL EXPRESSIONS
Learning Objectives
This chapter provides the methods and tools needed to utilize SQL expressions. At the completion of this chapter, you will be able to: Use Numeric, String and Temporal values in Expressions List the types of Functions that can be used in Expressions

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-1

Developing Dynamic Web Applications with MySQL and PHP


112

Chapter 8- SQL Expressions

8.2

SQL Expressions
Expressions are a common element of SQL statements, and they occur in many contexts. For example, expressions often occur in the WHERE clause of SELECT, DELETE, or UPDATE statements to identify which records to retrieve, delete, or update. But expressions may be used in many other places; for example, in the output column list of a SELECT statement, or in ORDER BY or GROUP BY clauses. Terms of expressions consist of constants (literal numbers, strings, dates, and times), NULL values, references to table columns, and function calls. Terms may be combined using operators into more complex expressions. Many types of operators are available, such as those for arithmetic, comparison, logical, and pattern-matching operations. Here are some examples of expressions: The following statement refers to table columns to select country names and populations from the Country table:
SELECT Name, Population FROM Country;

Literal data values that aren't stored in a table can be worked with directly. The following statement refers to several literal values: an integer, an exact-value decimal value, an approximate-value floating-point value in scientific notation, and a string value:
SELECT 14, -312.82, 4.32E-03, 'I am a string';

Another way to produce data values is by invoking functions. This statement calls functions that return the current date and a server version string:
SELECT CURDATE(), VERSION();

All these types of values can be combined into more complex expressions to produce other values of interest. The following statement demonstrates this:
mysql> SELECT Name, TRUNCATE(Population/SurfaceArea,2) AS 'people/sq. km', -> IF(GNP > GNPOld,'Increasing','Not increasing') AS 'GNP Trend' -> FROM Country ORDER BY Name LIMIT 10; +---------------------+---------------+----------------+ | Name | people/sq. km | GNP Trend | +---------------------+---------------+----------------+ | Afghanistan | 34.84 | Not increasing | | Albania | 118.31 | Increasing | | Algeria | 13.21 | Increasing | | American Samoa | 341.70 | Not increasing | | Andorra | 166.66 | Not increasing | | Angola | 10.32 | Not increasing | | Anguilla | 83.33 | Not increasing | | Antarctica | 0.00 | Not increasing | | Antigua and Barbuda | 153.84 | Increasing | | Argentina | 13.31 | Increasing | +---------------------+---------------+----------------+

The expressions in the preceding statement uses these types of values: Table columns: Name, Population, SurfaceArea, GNP, and GNPOld. (GNP means gross national product.) Literal values: 'Increasing', 'Not increasing', and the column aliases are all string constants. Functions: The numeric function TRUNCATE() formats the population/area ratio to two decimal places, and the logical function IF() tests the expression in its first argument and returns its second or third argument depending on whether the expression is true or false.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-2

Developing Dynamic Web Applications with MySQL and PHP


113

Chapter 8- SQL Expressions

8.2.1

Numeric Expressions Numbers can be exact-value literals or approximate-value literals. Exact-value literals are used just as given in SQL statements when possible and thus are not subject to the inexactness produced by rounding error. On the other hand, approximate-value literals are subject to rounding error and may not necessarily be used exactly as given. Exact-value literals are written with no exponent. Approximate-value literals are written in scientific notation with an exponent. For example, the numeric values -43, 368.93, and .00214 are exact values, whereas -4.3E1, 3.6893E2, and 2.14E-3 are approximate values. Even though the two sets of numbers look like they have the same values, internally they are represented in different ways: Exact-value numbers - These numbers are integer values with no fractional part after the decimal point or decimal values with a fractional part. They're represented internally like an integer or DECIMAL data type. Operations on integers are performed with the precision of BIGINT values (that is, 64 bits). Operations on decimal values have a precision of up to 64 decimal digits. Currently, the scale for decimal values allows up to 30 decimal digits after the decimal point. Approximate-value literals - These numbers are represented as floating-point numbers (like the DOUBLE data type) and have a mantissa and exponent. The mantissa allows up to 53 bits of precision, which is about 15 decimal digits. Null Values - Any numerical expression including NULL, will return a null value (with the exception of some NULL -safe operations) Exact/Approximate Values When numbers are used in an arithmetic or comparison operation, the result of the operation may depend on whether it involves exact or approximate values. Consider the following two comparisons: mysql> SELECT 1.1 + 2.2 = 3.3, 1.1E0 + 2.2E0 = 3.3E0; +-----------------+-----------------------+ | 1.1 + 2.2 = 3.3 | 1.1E0 + 2.2E0 = 3.3E0 | +-----------------+-----------------------+ | 1 | 0 | +-----------------+-----------------------+ In the first expression, exact values are used, so the comparison involves exact calculations. In the second expression, approximate values are used and rounding error is possible. This illustrates that when approximate values are used in comparisons, do not expect exact-value precision. The internal representation of floating-point numbers inherently allows for the possibility of a rounding error. 'Numeric Strings' If numbers are mixed with strings in numeric context, MySQL converts the strings to numbers and performs a numeric operation: mysql> SELECT 1 + '1', 1 = '1'; +---------+---------+ | 1 + '1' | 1 = '1' | +---------+---------+ | 2 | 1 | +---------+---------+

114

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-3

Developing Dynamic Web Applications with MySQL and PHP


115

Chapter 8- SQL Expressions

8.2.2

String Expressions Literal strings in expressions are written as quoted values. By default, either single quotes or double quotes can be used, although single quotes are more standard. Also, if the ANSI_QUOTES SQL mode is enabled, double quotes are interpreted as identifier-quoting characters, so literal strings can be quoted only with single quotes. The data types for representing strings in tables include CHAR, VARCHAR and the TEXT and BLOB types. The type chosen to be used depends on factors such as the maximum length of values and whether fixed-length or variable-length values are required. Direct use of strings in expressions occurs primarily in comparison operations. Otherwise, most string operations are performed by using functions. The usual comparison operators apply to string values (=, <>, <, BETWEEN, and so forth): Operator < <= = <=> <> or != >= > BETWEEN <x AND Y> Definition Less than Less than or equal to Equal to Equal to (works even for NULL values) Not equal to Greater than or equal to Greater than Indicate a range of numerical values

116

CONCAT String concatenation is done with the CONCAT() function:


mysql> SELECT CONCAT('abc','def'); +---------------------+ | CONCAT('abc','def') | +---------------------+ | abcdef | +---------------------+

Instructor Notes: More examples...


mysql> SELECT concat(name, ' is in ', district) FROM city LIMIT 5; +-----------------------------------+ | concat(name, ' is in ', district) | +-----------------------------------+ | Kabul is in Kabol | ... 5 rows in set (#.## sec) mysql> SELECT concat_ws(' ', name, district, countrycode) FROM city LIMIT 5; +---------------------------------------------+ ______________________________________________________________________________________________ | concat_ws(' ', name, district, countrycode) | +---------------------------------------------+ ______________________________________________________________________________________________ | Kabul Kabol AFG | | Qandahar Qandahar AFG | ______________________________________________________________________________________________ ... ______________________________________________________________________________________________ 5 rows in set (#.## sec)

Page 8-4

Developing Dynamic Web Applications with MySQL and PHP OR (||) or CONCAT

Chapter 8- SQL Expressions

The || operator is treated as the logical OR operator by default, but can be used for string concatenation if PIPES_AS_CONCAT SQL mode is enabled:
mysql> SELECT 'abc' || 'def'; +----------------+ | 'abc' || 'def' | +----------------+ | 0 | +----------------+ 1 row in set, 2 warnings (#.## sec) 117 mysql> SET sql_mode = 'PIPES_AS_CONCAT'; Query OK, 0 rows affected (#.## sec) mysql> SELECT 'abc' || 'def'; +----------------+ | 'abc' || 'def' | +----------------+ | abcdef | +----------------+

In the first SELECT statement, || performs a logical OR operation. This is a numeric operation, so MySQL converts the strings in the expression to numbers first. Neither looks like a number, so MySQL converts them to zero, which is why there is a warning count of two. The resulting operands for the operation are zero, so the result also is zero. After PIPES_AS_CONCAT is enabled, || produces a string concatenation instead.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-5

Developing Dynamic Web Applications with MySQL and PHP


118

Chapter 8- SQL Expressions

Case Sensitivity in String Comparisons String comparisons are somewhat more complex than numeric or temporal comparisons. A letter in uppercase may compare as the same or different than the same letter in lowercase, and a letter with one type of accent may be considered the same or different than that letter with another type of accent. Character Sets and Collations - String expressions contain characters from a particular character set, which is associated with one of the collations (sorting orders) available for the character set. Characters may consist of single or multiple bytes. A collation can be case insensitive (lettercase is not significant) or case sensitive (lettercase is significant).

The rules that govern string comparison apply in several ways. They determine the result of comparisons performed explicitly with operators such as = and <, and comparisons performed implicitly by ORDER BY, GROUP BY, and DISTINCT operations. The default character set and collation for literal strings depend on the values of the character_set_connection and collation_connection system variables. The default character set is latin1. The default collation is latin1_swedish_ci, which is case insensitive as indicated by the _ci at the end of the collation name. Assuming these connection settings, literal strings are not case sensitive by default. The comparing strings that differ only in lettercase can be seen in the following example:
mysql> SELECT 'Hello' = 'hello'; +-------------------+ | 'Hello' = 'hello' | +-------------------+ | 1 | +-------------------+

A given collation might cause certain accented characters to compare the same as other characters. For example, '' and 'ue' are different in the default latin1_swedish_ci collation, but with the latin1_german2_ci collation (German phone-book collation), they have the same sort value and thus compare as equal:
mysql> SELECT 'Mller' = 'Mueller'; +----------------------+ | 'Mller' = 'Mueller' | +----------------------+ | 0 | +----------------------+ mysql> SET collation_connection = latin1_german2_ci; mysql> SELECT 'Mller' = 'Mueller'; +----------------------+ | 'Mller' = 'Mueller' | +----------------------+ | 1 | +----------------------+

119

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-6

Developing Dynamic Web Applications with MySQL and PHP


120

Chapter 8- SQL Expressions

Using LIKE for Pattern Matching Operators such as = and != are useful for finding values that are equal to or not equal to a specific exact comparison value. When it's necessary to find values based on similarity instead, a pattern match is useful. To perform a pattern match, use value LIKE 'pattern', where value is the value to test and 'pattern' is a pattern string that describes the general form of values to match. Patterns used with the LIKE pattern-matching operator can contain two special characters (called metacharacters or wildcards) that stand for something other than themselves: Percent (%) Character - The percent character matches any sequence of zero or more characters. For example, the pattern 'a%' matches any string that begins with 'a', '%b' matches any string that ends with 'b', and '%c%' matches any string that contains a 'c'. The pattern '%' matches any string, including empty strings.

Underscore ( '_' ) Character - The underscore character matches any single character. 'd_g' matches strings such as 'dig', 'dog', and 'd@g'. Because '_' matches any single character, it matches itself and the pattern 'd_g' also matches the string 'd_g'. A pattern can use these metacharacters in combination. For example, '_%' matches any string containing at least one character.
121

For example, to list all countries with names that start with 'United';
mysql> SELECT Name FROM Country -> WHERE Name LIKE 'United%'; +--------------------------------------+ | Name | +--------------------------------------+ | United Arab Emirates | | United Kingdom | | United States Minor Outlying Islands | | United States | +--------------------------------------+

To invert a pattern match, use NOT LIKE rather than LIKE:


mysql> SELECT Name FROM Country -> WHERE Name NOT LIKE 'United%'; +----------------------------------------------+ | Name | +----------------------------------------------+ | Aruba | | Afghanistan | | Angola | ... | South Africa | | Zambia | | Zimbabwe | +----------------------------------------------+ 235 rows in set (#.## sec)

Note: The NOT LIKE results in a list which is 4 short of the total Country list (239), since the specified pattern matched items have been left out.
122

8.2.3

Temporal Expressions Temporal values include dates, times, and date/time values that have both a date and time. More specialized temporal types are timestamp (commonly used for recording current date and time) and year (for temporal values that require a resolution only to year units).

______________________________________________________________________________________________ ______________________________________________________________________________________________ Instructor Notes: If you need more complex string pattern matching, you can use RLIKE and REGX. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-7

Developing Dynamic Web Applications with MySQL and PHP

Chapter 8- SQL Expressions

Direct use of temporal values in expressions occurs primarily in comparison operations, or in arithmetic operations that add an interval to or subtract an interval from a temporal value. Otherwise, most temporal value operations are performed by using functions. Temporal data may be generated via any of the following means: Copying data from an existing date, datetime, or time column Executing a built-in function that returns a date, datetime, or time column Building a string representation of the temporal data to be evaluated by the server Date Components: Type Default Format DATE YYYY-MM-DD TIME HH:MM:SS DATETIME YYYY-MM-DD HH:MI:SS TIMESTAMP YYYY-MM-DD HH:MI:SS YEAR YYYY The usual comparison operators apply to temporal values (=, <>, <, BETWEEN, and so forth). To perform interval arithmetic, use the INTERVAL keyword and a unit value:
mysql> SELECT '2010-01-01' + INTERVAL 10 DAY, -> INTERVAL 10 DAY + '2010-01-01'; +--------------------------------+--------------------------------+ | '2010-01-01' + INTERVAL 10 DAY | INTERVAL 10 DAY + '2010-01-01' | +--------------------------------+--------------------------------+ | 2010-01-11 | 2010-01-11 | +--------------------------------+--------------------------------+

123

For addition of temporal and interval values, write the operands in either order, as just shown. To subtract an interval from a temporal value, the interval value must be second (it doesn't make sense to subtract a temporal value from an interval):
mysql> SELECT '2010-01-01' - INTERVAL 10 DAY; +--------------------------------+ | '2010-01-01' - INTERVAL 10 DAY | +--------------------------------+ | 2009-12-22 | +--------------------------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-8

Developing Dynamic Web Applications with MySQL and PHP


124

Chapter 8- SQL Expressions

8.3

Functions in SQL Expressions


Functions can be invoked within expressions and return a value that is used in place of the function call when the expression is evaluated. When function is invoked, there must be no space after the function name and before the opening parenthesis. It's possible to change this default behavior by enabling the IGNORE_SPACE SQL mode to cause spaces after the function name to be ignored:
mysql> SELECT PI (); ERROR 1305 (42000): FUNCTION world.PI does not exist mysql> SET sql_mode = 'IGNORE_SPACE'; Query OK, 0 rows affected (#.## sec) mysql> SELECT PI (); +----------+ | PI () | +----------+ | 3.141593 | +----------+

125

8.3.1

Comparison Functions
Comparison functions enable the testing of relative values or membership of one value within a set of values. LEAST() and GREATEST() take a set of values as arguments and return the one that is smallest or largest, respectively:
mysql> SELECT LEAST(4,3,8,-1,5), LEAST('cdef','ab','ghi'); +-------------------+--------------------------+ | LEAST(4,3,8,-1,5) | LEAST('cdef','ab','ghi') | +-------------------+--------------------------+ | -1 | ab | +-------------------+--------------------------+ mysql> SELECT GREATEST(4,3,8,-1,5), GREATEST('cdef','ab','ghi'); +----------------------+-----------------------------+ | GREATEST(4,3,8,-1,5) | GREATEST('cdef','ab','ghi') | +----------------------+-----------------------------+ | 8 | ghi | +----------------------+-----------------------------+

126

INTERVAL() takes a comparison value as its first argument. The remaining arguments should be a set of values in sorted order. INTERVAL() compares the first argument to the others and returns a value to indicate how many of them are less than or equal to it. It's sometimes necessary to determine whether a value is equal to any of several specific values. One way to accomplish this is to combine several equality tests into a single expression with the OR logical operator:
... WHERE id = 13 OR id = 45 OR id = 97 OR id = 142 ... WHERE name = 'Tom' OR name = 'Dick' OR name = 'Harry'

However, MySQL provides an IN() operator that performs the same kind of comparison and that is more concise and easier to read. To use it, provide the comparison values as a comma-separated list of arguments to IN():
... WHERE id IN(13,45,97,142) ... WHERE name IN('Tom','Dick','Harry')

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-9

Developing Dynamic Web Applications with MySQL and PHP


127

Chapter 8- SQL Expressions

8.3.2

Control Flow Functions Control flow functions enable choices between different values based on the result of an expression. If Construct IF() tests the expression in its first argument and returns its second or third argument depending on whether the expression is true or false:
mysql> SELECT IF(1 > 0, 'yes','no'); +-----------------------+ | IF(1 > 0, 'yes','no') | +-----------------------+ | yes | +-----------------------+

128

This example uses the IF() construct to specify the order of the list of countries from the Country table (world database) using the code value to place the USA in the first row of the results:
mysql> SELECT name FROM country -> ORDER BY IF(code='USA',1,2), name -> LIMIT 10; +---------------------+ | name | +---------------------+ | United States | | Afghanistan | | Albania | | Algeria | | American Samoa | | Andorra | | Angola | | Anguilla | ... | Zimbabwe | +---------------------+ 239 rows in set (#.## sec)

129

CASE Construct The CASE construct is not a function, but it too provides flow control. It has two forms of syntax. The first looks like this: CASE case_expr WHEN when_expr THEN result [WHEN when_expr THEN result] ... [ELSE result] END The expression case_expr is evaluated and used to determine which of the following clauses in the rest of the CASE to execute. The when_expr in the initial WHEN clause is evaluated and compared to case_expr. If the two are equal, the expression following THEN is the result of the CASE. If when_expr is not equal to case_expr, and there are any following WHEN clauses, they are handled similarly in turn. If no WHEN clause has a when_expr equal to case_expr, and there is an ELSE clause, the expression in the ELSE clause becomes the CASE result. If there is no ELSE clause, the result is NULL.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-10

Developing Dynamic Web Applications with MySQL and PHP


130

Chapter 8- SQL Expressions

In this example, the CASE expression is used to specify the order of the first three rows in the list of countries from the Country table (world database) using the code values:
mysql> SELECT name FROM country -> ORDER BY -> CASE code -> WHEN 'USA' THEN 1 -> WHEN 'CAN' THEN 2 -> WHEN 'MEX' THEN 3 -> ELSE 4 END, name; +----------------+ | name | +----------------+ | United States | | Canada | | Mexico | ... | Zimbabwe | +----------------+ 239 rows in set (#.## sec)

The second CASE syntax looks like this: CASE WHEN when_expr THEN result [WHEN when_expr THEN result] ... [ELSE result] END For this syntax, the conditional expression in each WHEN clause is executed until one is found to be true, and then its corresponding THEN expression becomes the result of the CASE. If none of them are true and there is an ELSE clause, its expression becomes the CASE result. If there is no ELSE clause, the result is NULL.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-11

Developing Dynamic Web Applications with MySQL and PHP


131

Chapter 8- SQL Expressions

In the following example, we group the countries into three groups, USA, Europe and the rest of the world. Note that the criteria is based on different columns in the two rows:
mysql> SELECT CASE -> WHEN Code = 'USA' THEN 'United States' -> WHEN Continent = 'Europe' THEN 'Europe' -> ELSE 'Rest of the world' -> END AS Area, -> SUM(GNP), SUM(Population) FROM Country GROUP BY Area; +-------------------+-------------+-----------------+ | Area | SUM(GNP) | SUM(Population) | +-------------------+-------------+-----------------+ | Europe | 9498865.00 | 730074600 | | Rest of the world | 11345342.90 | 5070317850 | | United States | 8510700.00 | 278357000 | +-------------------+-------------+-----------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-12

Developing Dynamic Web Applications with MySQL and PHP


132

Chapter 8- SQL Expressions

8.3.3

Numeric Functions
Numeric functions perform several types of mathematical operations, such as rounding, truncation, trigonometric calculations, or generating random numbers. ROUND The ROUND() function performs rounding of its argument. The rounding method applied to the fractional part of a number depends on whether the number is an exact or approximate value: For positive exact values, ROUND() rounds up to the next integer if the fractional part is .5 or greater, and down to the next integer otherwise. For negative exact values, ROUND() rounds down to the next integer if the fractional part is .5 or greater, and up to the next integer otherwise. Another way to state this is that a fraction of .5 or greater rounds away from zero and a fraction less than .5 rounds toward zero:
mysql> SELECT ROUND(28.5), ROUND(-28.5); +-------------+--------------+ | ROUND(28.5) | ROUND(-28.5) | +-------------+--------------+ | 29 | -29 | +-------------+--------------+

For approximate values, ROUND() uses the rounding method provided in the C library used by the MySQL server. This can vary from system to system, but typically rounds to the nearest even integer:
mysql> SELECT ROUND(2.85E1), ROUND(-2.85E1); +---------------+----------------+ | ROUND(2.85E1) | ROUND(-2.85E1) | +---------------+----------------+ | 28 | -28 | +---------------+----------------+

FLOOR and CEILING FLOOR() returns the largest integer not greater than its argument, and CEILING() returns the smallest integer not less than its argument:
mysql> SELECT FLOOR(-14.7), FLOOR(14.7); +--------------+-------------+ | FLOOR(-14.7) | FLOOR(14.7) | +--------------+-------------+ | -15 | 14 | +--------------+-------------+ mysql> SELECT CEILING(-14.7), CEILING(14.7); +----------------+---------------+ | CEILING(-14.7) | CEILING(14.7) | +----------------+---------------+ | -14 | 15 | +----------------+---------------+

Note: TRUNCATE(<number>,<decimals>) is similar to FLOOR(). decimals to truncate number, and does not return negative values.

However, it specifies

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-13

Developing Dynamic Web Applications with MySQL and PHP ABS and SIGN ABS() and SIGN() extract the absolute value and sign of numeric values:
mysql> SELECT ABS(-14.7), ABS(14.7); +------------+-----------+ | ABS(-14.7) | ABS(14.7) | +------------+-----------+ | 14.7 | 14.7 | +------------+-----------+ mysql> SELECT SIGN(-14.7), SIGN(14.7), SIGN(0); +-------------+------------+---------+ | SIGN(-14.7) | SIGN(14.7) | SIGN(0) | +-------------+------------+---------+ | -1 | 1 | 0 | +-------------+------------+---------+

Chapter 8- SQL Expressions

Trigometric Functions A family of functions performs trigonometric calculations, including conversions between degrees and radians:
mysql> SELECT SIN(0), COS(0), TAN(0); +--------+--------+--------+ | SIN(0) | COS(0) | TAN(0) | +--------+--------+--------+ | 0 | 1 | 0 | +--------+--------+--------+ mysql> SELECT PI(), DEGREES(PI()), RADIANS(180); +----------+---------------+-----------------+ | PI() | DEGREES(PI()) | RADIANS(180) | +----------+---------------+-----------------+ | 3.141593 | 180 | 3.1415926535898 | +----------+---------------+-----------------+

Random Numbers To generate random numbers, invoke the RAND() function:


mysql> SELECT RAND(), RAND(), RAND(); +------------------+------------------+------------------+ | RAND() | RAND() | RAND() | +------------------+------------------+------------------+ | 0.55239934711941 | 0.16831658330589 | 0.18438490590489 | +------------------+------------------+------------------+

Instructor Note: Other Functions of interest: mysql> SELECT RIGHT('MySQL', mysql> SELECT mysql> SELECT LOWER('MySQL'); REVERSE('MySQL'); +-------3); +----------------+ ----------+ +-------------------+ | LOWER('MySQL') | | REVERSE('MySQL') | | RIGHT('MySQL', 3) | +----------------+ +------------------+ +-------------------+ | mysql | | LQSyM | | SQL | ______________________________________________________________________________________________ +----------------+ +------------------+ +-------------------+ 1 row in set (#.## sec) 1 row in set (#.## sec) 1 row in set (#.## sec) ______________________________________________________________________________________________

______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-14

Developing Dynamic Web Applications with MySQL and PHP


133

Chapter 8- SQL Expressions

8.3.4

String Functions String functions calculate string lengths, extract pieces of strings, search for substrings or replace them, perform lettercase conversion, and more. String Lengths The LENGTH() and CHAR_LENGTH() functions determine string lengths in byte and character units, respectively. The values returned by the two functions will differ for strings that contain multi-byte characters. The following example shows this, using the latin1 single-byte character set and the ucs2 double-byte character set:
mysql> SELECT LENGTH('MySQL'), CHAR_LENGTH('MySQL'); +-----------------+----------------------+ | LENGTH('MySQL') | CHAR_LENGTH('MySQL') | +-----------------+----------------------+ | 5 | 5 | +-----------------+----------------------+ mysql> SELECT LENGTH(CONVERT('MySQL' USING ucs2)) AS length, -> CHAR_LENGTH(CONVERT('MySQL' USING ucs2)) AS c_length; +------------+------------+ | length | c_length | +------------+------------+ | 10 | 5 | +------------+------------+

Combining Text CONCAT() and CONCAT_WS() concatenate strings. CONCAT() concatenates all of its arguments, whereas CONCAT_WS() interprets its first argument as a separator to place between the following arguments:
mysql> SELECT CONCAT('aa','bb','cc','dd'); +-----------------------------+ | CONCAT('aa','bb','cc','dd') | +-----------------------------+ | aabbccdd | +-----------------------------+ mysql> SELECT CONCAT_WS('aa','bb','cc','dd'); +--------------------------------+ | CONCAT_WS('aa','bb','cc','dd') | +--------------------------------+ | bbaaccaadd | +--------------------------------+

Compare Text The STRCMP() function compares two strings and returns 1, 0, or 1 if the first string is less than, equal to, or greater than the second string, respectively:
mysql> SELECT STRCMP('abc','def'), STRCMP('def','def'), -> STRCMP('def','abc'); +--------------------+--------------------+---------------------+ |STRCMP('abc','def') |STRCMP('def','def') | STRCMP('def','abc') | +--------------------+--------------------+---------------------+ | -1 | 0 | 1 | +--------------------+--------------------+---------------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-15

Developing Dynamic Web Applications with MySQL and PHP


134

Chapter 8- SQL Expressions

8.3.5

Temporal Functions Temporal functions perform operations such as extracting parts of dates and times, reformatting values, or converting values to seconds or days. In many cases, a temporal function that takes a date or time argument also can be given a datetype argument and will ignore the irrelevant part of the datetime value. Functions for retrieving temporal data are: Function NOW() CURDATE() CURTIME() YEAR() MONTH() DAYOFMONTH() or DAY() DAYNAME() (English) HOUR() MINUTE() SECOND() Definition Current date and time as set on the client host ( in DATETIME format) Current date as set on the client host ( in DATE format) Current time as set on the client host ( in TIME format) Year in YEAR format, per value indicated (can use NOW() function within parenthesis to get current year per client) Month of the year in integer format, per value indicated (can use NOW() as above) Day of the month in integer format, per value indicated (can use NOW() as above) Day of the week in string format, per value indicated (can use NOW() as above) Hour of the Day in integer format, per value indicated (can use NOW() as above) Minute of the Day in integer format, per value indicated (can use NOW() as above) Second of the Minute in integer format, per value indicated (can use NOW() as above)

135

Customize a Date To customize the format of output of temporal data, use DATE_FORMAT(); DATE_FORMAT(<date>, <format_string>) % can be used as a wildcard
mysql> SELECT NOW(), DATE_FORMAT(NOW(), '%W the %D of %M'); +---------------------+---------------------------------------+ | NOW() | DATE_FORMAT(NOW(), '%W the %D of %M') | +---------------------+---------------------------------------+ | 2004-04-30 11:59:15 | Friday the 30th of April | +---------------------+---------------------------------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-16

Developing Dynamic Web Applications with MySQL and PHP


136

Chapter 8- SQL Expressions

Extract a Date There are functions for extracting parts of date or time values:
mysql> SELECT YEAR('2010-04-15'), MONTH('2010-04-15), DAYOFMONTH('2010-04-15'); +----------+-----------+----------------+ | YEAR() | MONTH() | DAYOFMONTH() | +----------+-----------+----------------+ | 2010 | 4 | 15 | +----------+-----------+----------------+ mysql> SELECT DAYOFYEAR('2010-04-15'); +---------------+ | DAYOFYEAR() | +---------------+ | 105 | +---------------+ mysql> SELECT HOUR('09:23:57'), MINUTE('09:23:57'), SECOND('09:23:57'); +----------+------------+------------+ | HOUR() | MINUTE() | SECOND() | +----------+------------+------------+ | 9 | 23 | 57 | +----------+------------+------------+

137

Compose a Date MAKEDATE() and MAKETIME() compose dates and times from component values. MAKEDATE() produces a date from year and day of year arguments:
mysql> SELECT MAKEDATE(2010,105); +--------------------+ | MAKEDATE(2010,105) | +--------------------+ | 2010-04-15 | +--------------------+

MAKETIME() produces a time from hour, minute, and second arguments.


mysql> SELECT MAKETIME(9,23,57); +-------------------+ | MAKETIME(9,23,57) | +-------------------+ | 09:23:57 | +-------------------+ 138

Obtain a Current Date If current date or time needs to be determined, use CURRENT_DATE (CURDATE) or CURRENT_TIME (CURTIME). To get the current date and time as a single value, use CURRENT_TIMESTAMP or NOW():
mysql> SELECT CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP; +--------------+--------------+---------------------+ | CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP | +--------------+--------------+---------------------+ | 2005-05-31 | 21:40:18 | 2005-05-31 21:40:18 | +--------------+--------------+---------------------+

The three functions in the preceding statement are unlike most functions in that they can be invoked with or without parentheses following the function name.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-17

Developing Dynamic Web Applications with MySQL and PHP


139

Chapter 8- SQL Expressions

8.3.6

NULL-Related Functions Functions intended specifically for use with NULL values include ISNULL() and IFNULL(). ISNULL() is true if its argument is NULL and false otherwise: mysql> SELECT ISNULL(NULL), ISNULL(0), ISNULL(1); +--------------+-----------+-----------+ | ISNULL(NULL) | ISNULL(0) | ISNULL(1) | +--------------+-----------+-----------+ | 1 | 0 | 0 | +--------------+-----------+-----------+ IFNULL() takes two arguments. If the first argument is not NULL, that argument is returned; otherwise, the function returns its second argument: mysql> SELECT IFNULL(NULL,'a'), IFNULL(0,'b'); +------------------+---------------+ | IFNULL(NULL,'a') | IFNULL(0,'b') | +------------------+---------------+ | a | 0 | +------------------+---------------+ Other functions handle NULL values in various ways, so knowing how a given function behaves is important. In many cases, passing a NULL value to a function results in a NULL return value. For example, any NULL argument passed to CONCAT() causes it to return NULL: mysql> SELECT CONCAT('a','b'), CONCAT('a',NULL,'b'); +-----------------+----------------------+ | CONCAT('a','b') | CONCAT('a',NULL,'b') | +-----------------+----------------------+ | ab | NULL | +-----------------+----------------------+ But not all functions behave that way. CONCAT_WS() (concatenate with separator) simply ignores NULL arguments entirely: mysql> SELECT CONCAT_WS('/','a','b'), -> CONCAT_WS('/','a',NULL,'b'); +------------------------+-----------------------------+ | CONCAT_WS('/','a','b') | CONCAT_WS('/','a',NULL,'b') | +------------------------+-----------------------------+ | a/b | a/b | +------------------------+-----------------------------+

140

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-18

Developing Dynamic Web Applications with MySQL and PHP

Chapter 8- SQL Expressions

Lab 8-A
In this exercise you will use SQL comparisons and Functions. This will require a MySQL command line client and access to the mysql server. If the world database is not available (or not present), please refer to Lab 6-A to create and load the database with the components that will be needed to complete the remainder of this lab. ACTION (You Do) 1. Use a SELECT statement to add the following together; 2, 3, NULL by typing the following in the mysql client (at this point a database does not need to be selected): SELECT 2+3+NULL; 2. Do the exact same expression as in Step 1, with one exception; put single quotes around the word NULL by typing the following in the mysql client: SELECT 2+3+'NULL'; 3. Display the warning that was captured during the last query by typing the following in the mysql client: SHOW WARNINGS; 4. Issue a SELECT statement that will find the populations of the three least populated countries by typing the following in the mysql client: SELECT Population FROM Country WHERE Population > 0 ORDER BY Population ASC LIMIT 3; 5. Using the three numbers returned from the select statement above, issue a select statement using standard numeric expressions to find the average of these three populations. This is accomplished by typing the following in the mysql client: SELECT (50+600+1000)/3; 6. Use a SELECT statement to concatenate the Name and corresponding District from the City table with the words ' is in ' between the name and the district, limiting the output to the first five rows found by typing the following in the mysql client: SELECT CONCAT(name, ' is in ', district) FROM city LIMIT 5; ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ The resulting list from the SELECT statement is limited to the first 5 cities in the City table. Returns the average numeric value for the least populated countries in the Country table. The warning indicates that the NULL is an incorrect value. Returns a value (5) for the part of the expression that does not include the value NULL. A warning is captured. COMPUTER RESPONSE / Comment The result shows a value of NULL.

The number returned is the average of the three populations from those received in step 4.

Page 8-19

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 7. Issue a query for all cities that include the word 'City' in their name by typing the following in the mysql client: SELECT name FROM city WHERE name LIKE '%city%'; 8. Issue a query for all cities that include 'City' in the name, and have four characters and a space before the word 'City' by typing the following in the mysql client: SELECT name FROM city WHERE name LIKE '____ city' 9. Show the current date (default format) with the column title 'TODAY' by typing the following in the mysql client: SELECT CURRENT_DATE AS TODAY; 10. Show the current date (default format) as it will be ten years from now by typing the following in the mysql client: SELECT CURRENT_DATE + INTERVAL 10 YEAR; 11. Use the IF() function within a SUM() function to list the total population of the world (as AllPop) AND the total population of the African countries (as AfricaPop) by typing the following in the mysql client: SELECT sum(IF(Continent='Africa', Population, 0)) AS AfricaPop, sum(population) AS AllPop FROM Country; 12. Use the IF() function to specify the order of the list of country codes and languages from the CountryLanguage table, using the code value to place languages of Norway in the first rows of the results. Limit the results to the first 10. This is accomplished by typing the following in the mysql client: SELECT CountryCode, Language FROM CountryLanguage ORDER BY IF(CountryCode='NOR',1,2), Language LIMIT 10;

Chapter 8- SQL Expressions

COMPUTER RESPONSE / Comment Returns a list of 12 city names with the word city in their name.

The list produced in step 7 is reduced considerably with this new search limitation.

Returns a single column with the current date as you specified.

Returns a single column with the current date, plus10 years. Where will you be?

Returns the sum of all country populations in Africa (titled AfricaPop) and the total population of all continents (as AllPop); +-----------+------------+ | AfricaPop | AllPop | +-----------+------------+ | 784475000 | 6078749450 | +-----------+------------+ 1 row in set (#.## sec) Returns a list of 10 country codes and corresponding languages, with the Norwegian languages listed first.

13. Round the number 3.75 to the nearest integer The result shows a value of 4. by typing the following in the mysql client: SELECT round(3.75); ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-20

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do)

Chapter 8- SQL Expressions

COMPUTER RESPONSE / Comment

14. Show the sign of the following numbers; -80, Returns a value of -1, 1, 0 respectively to indicate (-15.4), 0 by typing the following in the mysql whether the numbers are negative or positive. client: SELECT SIGN(-80), SIGN(-(-15.4)), SIGN(0); 15. Use a SELECT statement to show the string length of the City of 'Dallas' by typing the following in the mysql client: SELECT CHAR_LENGTH(Name) FROM City WHERE Name = 'Dallas'; 16. Concatenate the following individual words; 'This ', 'is ', 'a ', 'great ', 'class!' by typing the following in the mysql client: SELECT CONCAT_WS(' ', 'This', 'is', 'a', 'great', 'class!'); Returns a length value of 6.

Returns a continuous string connecting the specified words; +-----------------------------------+ | CONCAT_WS(' ','This','is','a','great','class!') | +-----------------------------------+ | This is a great class! | +-----------------------------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-21

Developing Dynamic Web Applications with MySQL and PHP


141

Chapter 8- SQL Expressions

Lab 8-B
In this exercise, you will use some of the expressions covered in this chapter to search for data in the photo_album database.

1. 2. 3. 4. 5. 6. 7.

Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). View the existing databases that the MySQL Server is maintaining. Utilize the photo_album database. Calculate how many days ago each person logged into the photo_album system. Note: Difference in dates are returned in microseconds when directly subtracted from each other. List the actual day name (Monday, Tuesday, etc.) for the last logins to determine if there is a trend in the day of the week for the last time a person logged into the photo_album system. Modify the statement above by having the output show 'Weekend' for Saturday and Sunday, and 'Weekday' for every other day. Show the expiration dates (term_date) for the customers with the first name Granny and Yogi, without using two where statements.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-22

Developing Dynamic Web Applications with MySQL and PHP


142

Chapter 8- SQL Expressions

8.4

Chapter Summary
In this chapter, you have learned to: Use Numeric, String and Temporal values in Expressions Expressions are a common element of SQL statements, and they occur in many contexts. For example, expressions often occur in the WHERE clause of SELECT, DELETE, or UPDATE statements to identify which records to retrieve, delete, or update. Terms of expressions consist of constants (literal numbers, strings, dates, and times), NULL values, references to table columns, and function calls. Terms may be combined using operators into more complex expressions. Many types of operators are available, such as those for arithmetic, comparison, logical, and patternmatching operations. Functions can be invoked within expressions and return a value that is used in place of the function call when the expression is evaluated. When function is invoked, there must be no space after the function name and before the opening parenthesis.

List the types of Functions that can be used in Expressions

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 8-23

Developing Dynamic Web Applications with MySQL and PHP

143

CHAPTER 9 SQL DML COMMANDS


144

Developing Dynamic Web Applications with MySQL and PHP


145

Chapter 9- SQL DML Commands

9
9.1

SQL DML COMMANDS


Learning Objectives
This chapter provides the methods and tools needed to manipulate table data using the SQL Data Manipulation Language (DML) commands. At the completion of this chapter, you will be able to: Utilize the INSERT statement Utilize the UPDATE statement Utilize the REPLACE statement Utilize the DELETE statement

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-1

Developing Dynamic Web Applications with MySQL and PHP


146

Chapter 9- SQL DML Commands

9.2

The INSERT Statement


Now that tables have been created, the next step is to populate them with data. Although there are a variety of ways to get data into MySQL tables, the INSERT statement is the most common method for getting data into a table. The INSERT statement uses the following general syntax; INSERT INTO table_name (column_list) VALUES(value_list); An insert can include a only the value(s) without a column list (if the exact column order, quantity and types are known), as follows; INSERT INTO numbers VALUES(250); Row contents will be as follows; +------+ | n | +------+ | 250 | +------+ To add multiple column data into a table (containing an inventory of used books) on a First Edition copy of the book A Tale of Two Cities by Charles Dickens, the following would be used; INSERT INTO used_books (author, title, edition) VALUES ('Charles Dickens', 'A Tale of Two Cities', 'First Edition'); Row contents will be as follows; +-----------------+----------------------+----------------+ | author | title | edition | +-----------------+----------------------+----------------+ | Charles Dickens | A Tale of Two Cities | First Edition | +-----------------+----------------------+----------------+ The first syntax for INSERT uses separate column and value lists following the name of the table into which the record needs to be added. The number of columns and values must be the same. The following statement uses a slightly different syntax in order to create 3 new rows in the people table simultaneously (with id set to 31, name set to 'Bruce, and age set to 49 for the first record, etc.);

147

INSERT INTO people (id,name,age) VALUES(31,'Bruce',49), (04,'Avery',21), (11,'Mackenzie',17); Note: All column values must be enclosed in single quotes (for string and temporal data types) in the INSERT statement. Row contents will be as follows; +----------------+-----+ | id | name | age | +----------------+-----+ | 31 | Bruce | 49 | | 04 | Avery | 21 | | 11 | Mackenzie | 17 | +----------------+-----+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-2

Developing Dynamic Web Applications with MySQL and PHP


148

Chapter 9- SQL DML Commands

9.2.1

149

9.2.2

INSERT with SELECT The SELECT command can also be used with insert in order to populate an existing table with matching column data from another table. In this case, we have created a table like City and called it City2, then added all the column/row data from the original City table in to this new table; INSERT INTO City2 SELECT * FROM City; The resulting rows will be the same as those of the original City table. INSERT with LAST_INSERT_ID The MySQL-specific option LAST_INSERT_ID(expr) can be used after an INSERT to retrieve the last AUTO_INCREMENT value after the insert takes place; mysql> INSERT INTO City (name, countrycode) -> VALUES ('Sarah City', 'USA'); Query OK, 1 row affected (#.## sec) mysql> SELECT LAST_INSERT_ID(); +------------------+ | LAST_INSERT_ID() | +------------------+ | 4080 | +------------------+ If a table contains an AUTO_INCREMENT column and INSERT ... UPDATE inserts a row, the LAST_INSERT_ID() function returns the AUTO_INCREMENT value. If the statement updates a row instead, LAST_INSERT_ID() is not meaningful. However, LAST_INSERT_ID(expr) can be used to worked around this. INSERT with NULL Values In general, if a column has no default value, the effect of omitting it from the INSERT depends on whether it can take NULL values and SQL mode being used: If the column can take NULL values, it is set to NULL. If the column cannot take NULL values, it is set to the implicit default for the column data type if strict SQL mode is not enabled. If the strict mode is enabled, an error occurs. To get the next available number in an AUTO_INCREMENT column, leave the column out of the column list, or give it the value of NULL in the value list. The same applies to TIMESTAMP type columns.

9.2.3
150

Instructor Notes: Mention that the INSERT/SET example is non-standard. A column list can also be provided with INSERT/SELECT: CREATE TABLE districts (id int unsigned auto_increment primary key, district ______________________________________________________________________________________________ varchar(20)); INSERT INTO districts (district) SELECT DISTINCT district FROM city; ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-3

Developing Dynamic Web Applications with MySQL and PHP


151

Chapter 9- SQL DML Commands

9.3

The UPDATE Statement


The UPDATE statement modifies the contents of the existing records. To use it, name the table needing to be updated, provide a SET clause that lists one or more column value assignments, and optionally specify a WHERE clause that identifies which records to update. The Update statement uses the following general syntax; UPDATE table_name SET column=expression(s) WHERE condition [options]; For example, to update the Country table by doubling the Population column for every country, the following statement would be used; mysql> UPDATE Country -> SET Population = Population * 2; Query OK, 232 rows affected, 1 warning (#.## sec) Rows matched: 239 Changed: 232 Warnings: 1 Note: The above statement returns a warning and completes the update for only most of the rows, but not all. This is because some of the updated numbers exceed the number of characters allowed for that column. The effects of column assignments made by an UPDATE are subject to column type constraints, just as they are for an INSERT or REPLACE. By default, if an attempt to update a column to a value that doesn't match the column definition is made, MySQL converts or truncates the value. If strict SQL mode is enabled, the server will be more restrictive about allowing invalid values. It's possible for an update to have no effect. This can occur under the following conditions: When it matches no records for updating; due to an empty table or if no records match the WHERE clause. When it does not actually change any column values (i.e. the value given is the same as the existing value). With respect to handling of records with unique key values, UPDATE is similar to REPLACE in some ways, but the two aren't equivalent: UPDATE does nothing if there is no existing record in the table that contains the specified key values. REPLACE does not require an existing record with the key values and adds one if none exists. UPDATE can be used to change some columns in an existing record while leaving others unchanged. REPLACE entirely discards the existing record. To achieve the effect of leaving some columns unchanged with REPLACE, the new record must specify the same values in those columns that the existing record has.

152

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-4

Developing Dynamic Web Applications with MySQL and PHP


153

Chapter 9- SQL DML Commands

154

9.3.1

9.3.2

9.3.3

UPDATE by default makes no guarantee about the order in which rows are updated. This can sometimes result in problems. Suppose that the people table contains two rows, where id is a primary key: mysql> SELECT * FROM people; +-------------------+ | id | name | age | +-------------------+ | 2 | Victor | 21 | | 3 | Susan | 15 | +-------------------+ UPDATE with SET To renumber the id values to being at 1, the following UPDATE statement: UPDATE people SET id=id-1; Row contents will be as follows; +-------------------+ | id | name | age | +-------------------+ | 2 | Susan | 15 | | 1 | Victor | 21 | +-------------------+ UPDATE with ORDER BY The statement succeeds if it updates id values first by setting 2 to 1 and then 3 to 2. However, it fails if it first tries to set 3 to 2. That would result in two records having an id value of 2, so a duplicate-key violation occurs. To solve this problem, add an ORDER BY clause to cause the row updates to occur in a particular order: UPDATE people SET id=id-1 ORDER BY id; Row contents will be as follows; +-------------------+ | id | name | age | +-------------------+ | 1 | Victor | 21 | | 2 | Susan | 15 | +-------------------+ UPDATE with LIMIT UPDATE also allows a LIMIT clause, which places a limit on the number of records updated. For example, if there are two identical people records with the name value of 'Victor' and there is need to change just one of them to 'Vic', use this statement: UPDATE people SET name='Vic' WHERE name='Victor' LIMIT 1; Note: ORDER BY and LIMIT may be used together in the same UPDATE statement. Row contents will be as follows; +-------------------+ | id | name | age | +-------------------+ | 1 | Vic | 21 | +-------------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-5

Developing Dynamic Web Applications with MySQL and PHP


155

Chapter 9- SQL DML Commands

9.4

The REPLACE Statement


The MySQL-specific statement REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. REPLACE is a MySQL extension to the SQL standard. It either inserts, or deletes and inserts. Uses the following general syntax; REPLACE INTO table_name (column_list) VALUES(value_list); In this example, we are replacing a current row of data (containing three columns) in the people database; REPLACE INTO people (id,name,age) VALUES(12,'Bruce',25); Note that unless the table has a PRIMARY KEY or a UNIQUE index, using a REPLACE statement makes no sense. It becomes equivalent to INSERT, because there is no index to be used to determine whether a new row duplicates another. Values for all columns are taken from the values specified in the REPLACE statement. Any missing columns are set to their default values, just as happens for INSERT. It is not possible to refer to values from the current row and use them in the new row.

156

The REPLACE statement returns a count to indicate the number of rows affected. This is the sum of the rows deleted and inserted. If the count is 1 for a single-row REPLACE, a row was inserted and no rows were deleted. If the count is greater than 1, one or more old rows were deleted before the new row was inserted. It is possible for a single row to replace more than one old row if the table contains multiple unique indexes and the new row duplicates values for different old rows in different unique indexes. The affected-rows count makes it easy to determine whether REPLACE only added a row or whether it also replaced any rows: Check whether the count is 1 (added) or greater (replaced). Currently, it is not possible to perform a replace into a table and select from the same table in a subquery. MySQL uses the following algorithm for REPLACE: 1. 2. Try to insert the new row into the table While the insertion fails because a duplicate-key error occurs for a primary key or unique index: a. b. Delete from the table the conflicting row that has the duplicate key value Try again to insert the new row into the table

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-6

Developing Dynamic Web Applications with MySQL and PHP


157

Chapter 9- SQL DML Commands

9.4.1

INSERT with ON DUPLICATE KEY UPDATE Instead of REPLACE If the MySQL-specific option ON DUPLICATE KEY UPDATE is specified, and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, an UPDATE of the old row is performed. ON DUPLICATE KEY is like REPLACE but nicer in some situations because it doesn't throw out the original row. For example, if a column is declared as UNIQUE and contains the value 1, the following two statements have identical effect: INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; UPDATE table SET c=c+1 WHERE a=1; The rows-affected value is 1 if the row is inserted as a new record and 2 if an existing record is updated. If column b is also unique, the INSERT is equivalent to this UPDATE statement instead: UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1; If a=1 OR b=2 matches several rows, only one row is updated. DUPLICATE KEY clause on tables with multiple unique indexes. In general, avoid using an ON

From the previous example in the INSERT section, suppose that id is the AUTO_INCREMENT column. To make LAST_INSERT_ID() meaningful for updates, insert rows as follows: INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-7

Developing Dynamic Web Applications with MySQL and PHP


158

Chapter 9- SQL DML Commands

9.5

The DELETE Statement


To remove records(data) from tables, use the DELETE command. The DELETE statement allows a WHERE clause that identifies which records to remove. To empty a table entirely by deleting all its records, use the following syntax: DELETE FROM table_name; To remove only specific records in a table, a DELETE statement needs to be issued with a WHERE clause that identifies which records to remove: DELETE FROM table_name WHERE ; Note: There is no need to mention any columns since it will delete whole rows at a time. Using DELETE with ORDER BY and LIMIT DELETE supports ORDER BY and LIMIT clauses, which provide finer control over the way records are deleted. For example, LIMIT can be useful to remove only some instances of a given set of records. Suppose that the people table contains five records where the name column equals 'Emily'. To keep only one such record, use the following statement to remove four of the duplicated records. DELETE FROM people WHERE name='Emily' LIMIT 4; Normally, MySQL makes no guarantees about which four of the five records selected by the WHERE clause it will delete. An ORDER BY clause in conjunction with LIMIT provides better control. For example, to delete four of the records containing 'Emily' but leave the one with the lowest id value, use ORDER BY and LIMIT together as follows; DELETE FROM people WHERE name='Emily' ORDER BY id DESC LIMIT 4; Note: The DELETE result will indicate number of rows affected, which can be zero (0) if the statement did not cause a change to be made.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-8

Developing Dynamic Web Applications with MySQL and PHP

Chapter 9- SQL DML Commands

Lab 9-A
In this exercise you will use some of the DML statements presented in this chapter to manipulate the data contained in the tables. This will require a MySQL command line client and access to the mysql server. ACTION (You Do) 1. After logging into the mysql client, use the test database by typing the following: USE test; 2. In the mysql client, enter the following statement to create a new table: CREATE TABLE numbers (n smallint unsigned); 3. Issue the following statement in the mysql client to add a record to the table just created: INSERT INTO numbers VALUES (5); 4. Issue the following statement in the mysql client to review the contents of the numbers table: SELECT * FROM numbers; 5. In the mysql client, enter the following statement to create a new table: CREATE TABLE birthdates (name varchar(30), bdate date); 6. Issue the following statement in the mysql client to add two records to the table just created: INSERT INTO birthdates VALUES ('Joe','1950-0215'),('Jane','1980-07-30'); 7. Review the data just entered by typing the following statement in the mysql client: SELECT * FROM birthdates; 8. Enter the following statement in the mysql client to create a new table which contains a column that records the current time when data is inserted: CREATE TABLE students (name varchar(30), modtime timestamp); If "Query OK. 0 rows affected." is the response from the server, then the statement was accepted and the table was created. If "Query OK. 0 rows affected." is the response from the server, then the statement was accepted and the table was created. The following response would show that the statement was accepted: Query OK, 2 rows affected (#.## sec) Records: 2 Duplicates: 0 Warnings: 0 The two records in the birthdates table, that were added in step 6, are displayed. If "Query OK. 0 rows affected." is the response from the server, then the statement was accepted and the table was created. If "Query OK. 1 row affected." is the response from the server, then the statement was accepted and the row was added to the table. The INSERT statement issued in step 3 was completed and the numbers table now contains a row of data. COMPUTER RESPONSE / Comment This will ensure that any statements issued will be performed against the test table.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-9

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 9. Issue the following statement in the mysql client to add two records to the table just created: INSERT INTO students (name) VALUES ('Peter'),('Tariq');

Chapter 9- SQL DML Commands

COMPUTER RESPONSE / Comment The column name is used in this statement due to the fact that we are only going to be entering data in one of the two columns. The following response would show that the statement was accepted: Query OK, 2 rows affected (#.## sec) Records: 2 Duplicates: 0 Warnings: 0 The two records in the students table, that were added in step 9, are displayed with the modtime field being set to the date/time when the record was stored. The following response would show that the statement was accepted: Query OK, 8 rows affected (#.## sec) Records: 8 Duplicates: 0 Warnings: 0 The record is accepted and added without any problems.

10. Review the data just entered by typing the following statement in the mysql client: SELECT * FROM students; 11. In the numbers table, add additional records by typing the following statement into the mysql client: INSERT INTO numbers VALUES (7),(9),(11),(13),(15),(17), (19),(21); 12. Attempt to insert a record with the same numeric value as one already entered by typing the following in the mysql client: INSERT INTO numbers VALUES (21); 13. Alter the table structure of the numbers table to reject duplicates in the n field by typing the following in the mysql client: ALTER TABLE numbers CHANGE n n SMALLINT UNSIGNED PRIMARY KEY;

The statement issued attempts to change the n column in the numbers table to include a PRIMARY KEY attribute forcing the column to accept only unique entries. However, the statement is not accepted because the data in the table would violate the unique rule assigned. The following statement is returned: ERROR 1582 (23000): Duplicate entry '21' for key 'PRIMARY'

14. Enter the following command to delete the records in the numbers table that were preventing the PRIMARY KEY from being assigned to the n column: DELETE FROM numbers WHERE n = 21; 15. Reenter the statement that was entered in step 13 in the mysql client: ALTER TABLE numbers CHANGE n n SMALLINT UNSIGNED PRIMARY KEY;

The following response shows that two records were deleted: Query OK, 2 rows affected

The statement issued attempts to change the n column in the numbers table to a PRIMARY KEY again. The following response would show that the statement was accepted: Query OK, 8 rows affected (#.## sec) Records: 8 Duplicates: 0 Warnings: 0

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-10

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 16. Now with a PRIMARY KEY attribute assigned to the n column in the numbers table, attempt to insert a record with the same numeric value as one already in the table by typing the following in the mysql client: INSERT INTO numbers VALUES (19); 17. Delete all records from the numbers table where the value in the n column is greater than 15 by typing the following in the mysql client: DELETE FROM numbers WHERE n > 15;

Chapter 9- SQL DML Commands

COMPUTER RESPONSE / Comment The statement issued attempts to add a record to the numbers table, but would violate the PRIMARY KEY attribute of the n column. The statement is not accepted and the following statement is returned: ERROR 1582 (23000): Duplicate entry '19' for key 'PRIMARY' The statement issued deletes all records that contain a n column value that is greater than 15. The record with a value of 15 in the n column will not be deleted because it is not greater than 15. The following response would show that the statement was accepted: Query OK, 2 rows affected (#.## sec) The following response would show that the statement was accepted: Query OK, 3 rows affected (#.## sec) Rows matched: 3 Changed: 3 Warnings: 0 The changes that were made to the numbers table are now reflected in the contents of that table. This option limits the potential for making a drastic mistake in the manipulation of the data. In most cases, this would delete all the records in the numbers table; however, because safe updates is turned on, the statement is rejected and the following response is given: ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

18. Using the numbers table again, add a value of 100 to all records that have a n column value greater than 10 by typing the following in the mysql client: UPDATE numbers SET n = n+100 WHERE n > 10; 19. Review the numbers table by typing the following statement in the mysql client: SELECT * FROM numbers; 20. Set the safe updates option by typing the following in the mysql client: SET SQL_SAFE_UPDATES = 1; 21. Attempt to delete all the records from the numbers table by typing in the following command in the mysql client: DELETE FROM numbers;

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-11

Developing Dynamic Web Applications with MySQL and PHP


159

Chapter 9- SQL DML Commands

Lab 9-B
In this exercise, you will use some of the DML commands covered in this chapter to manipulate the data in the photo_album database.

1. 2. 3. 4. 5. 6. 7. 8.

Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). View the existing databases that the MySQL Server is maintaining. Utilize the photo_album database. Search the customers records for the customer with the following e-mail address: hollywood@truedog.com Search the logins records for logins associated with the customer identified in step 4. In the customers table, update the customers e-mail address, identified in step 4, to howleewood@truedog.com. Review the customers records to see if the change (from step 6) took place. If the update did not take place, reissue the statement in step 6 to ensure the change takes place? Review the logins table to see if the e-mails associated with the customer in step 6 were also changed. If the e-mail associated with that customer were also changed in the logins table, why?

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-12

Developing Dynamic Web Applications with MySQL and PHP


160

Chapter 9- SQL DML Commands

9.6

Chapter Summary
In this chapter, you have learned to: Utilize the INSERT statement Although there are a variety of ways to get data into MySQL tables, the INSERT statement is the most common method for getting data into a table. The UPDATE statement modifies the contents of the existing records. To use it, name the table needing to be updated, provide a SET clause that lists one or more column value assignments, and optionally specify a WHERE clause that identifies which records to update. The MySQL-specific statement REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. REPLACE is a MySQL extension to the SQL standard. It either inserts, or deletes and inserts. To remove records (data) from tables, use the DELETE command. The DELETE statement allows a WHERE clause that identifies which records to remove.

Utilize the UPDATE statement

Utilize the REPLACE statement

Utilize the DELETE statement

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 9-13

Developing Dynamic Web Applications with MySQL and PHP

161

CHAPTER 10 SQL JOINS


162

Developing Dynamic Web Applications with MySQL and PHP


163

Chapter 10- SQL Joins

10 SQL JOINS
10.1 Learning Objectives
This chapter provides the methods and tools needed to retrieve data from multiple MySQL tables using Joins. At the completion of this chapter, you will be able to: Describe the concept of a Join Connect Data from Multiple Tables using various Join Statements Resolve Name Clashes when Joining Tables Join a Table to Itself Join Tables with UPDATE and DELETE statements

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-1

Developing Dynamic Web Applications with MySQL and PHP


164

Chapter 10- SQL Joins

10.2 What is a Join?


The SELECT queries shown thus far in this training guide retrieve information from a single table at a time. However, not all questions can be answered using just one table. When it's necessary to draw on information that is stored in multiple tables, use a join conditionan operation that produces a result by combining (joining) information in one table with information in another. The contents of two original tables are shown below. These tables can be joined together using a SELECT query which retrieves data from more than one table at a time.

165

table1 +----+----+ | i1 | c1 | +----+----+ | 1 | a | | 2 | b | | 3 | c | +----+----+ 3 rows in set (#.## sec)

table2 +----+----+ | i2 | c2 | +----+----+ | 2 | c | | 3 | b | | 4 | a | +----+----+ 3 rows in set (#.## sec)

mysql> SELECT * FROM table1 JOIN table2; +----+----+----+----+ | i1 | c1 | i2 | c2 | +----+----+----+----+ | 1 | a | 2 | c | | 2 | b | 2 | c | | 3 | c | 2 | c | | 1 | a | 3 | b | | 2 | b | 3 | b | | 3 | c | 3 | b | | 1 | a | 4 | a | | 2 | b | 4 | a | | 3 | c | 4 | a | +----+----+----+----+ 9 rows in set (#.## sec)

The above example returns a list of all data in both tables combined. This is known as a cross join. This example employs the use of the JOIN keyword. However, there are multiple methods available for joining tables which will be discussed within this chapter. A 'Cross Join' is so called because each row of each table is crossed with each row in every other table to produce all possible combinations. The result is known as a 'Cartesian Product'. A Cartesian product is a mathematical (set theory) concept which basically means combining all elements from the first entity with all elements of the second entity. Joining tables this way has the potential to produce a very large number of rows because the possible row count is the product of the number of rows in each table. A cross join between three tables contain 100, 200 and 300 rows, respectively, could return 100X200X300 = 6 million rows. That's a lot of rows, even though the individual tables are small. In cases like this, normally a WHERE clause is useful for reducing the result to a more manageable size. A join condition is critical to produce meaningful table joins.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-2

Developing Dynamic Web Applications with MySQL and PHP


166

Chapter 10- SQL Joins

10.3 Inner Joins


A join that identifies combinations of matching rows from two tables is called an inner join. The joining is done by connecting one table, using the primary key, another table that references it with a foreign key. Inner joins may be written using two different syntaxes. One syntax lists the tables to be joined separated by a comma. The other uses the INNER JOIN keywords.

167

10.3.1 Comma Separated Inner Join


To combine data from two or more tables to find the detail of records referenced in a foreign key , a table join must be performed. The most common way to do this is by specifying a list (comma separated) of tables in the FROM clause of the SELECT and using the WHERE clause to indicate the relationship between the tables. A simple question that might be asked about the information in the world database is, What are the country and corresponding capital cities (along with ID)? To answer that question, the following two individual queries could be executed
mysql> SELECT Name, Capital -> FROM Country; +---------------+---------+ | Name | Capital | +---------------+---------+ | Afghanistan | 1 | ... | Sweden | 3048 | ... | Germany | 3068 | ... | United States | 3813 | ... +---------------+---------+ 239 rows in set (#.## sec) mysql> SELECT Id, Name FROM -> City; +------+------------+ | Id | Name | +------+------------+ | 1 | Kabul | ... | 3048 | Stockholm | ... | 3068 | Berlin | ... | 3813 | Washington | ... +------+------------+ 4079 rows in set (#.## sec)

or they can be joined into a multi-table query. This is accomplished by using a join condition. A join condition is supplied in the WHERE clause (for comma joins) or by specifying the ON or USING keyword.
168

Notice that the column Capital (from the Country table) contains the same data as the Id column (from City). Therefore, these two queries can be joined where the Capital and Id are the same;
mysql> SELECT Country.Name, City.Name, City.Id FROM Country, City -> WHERE Country.Capital = City.Id; +----------------------+------------------+------+ | Name | Name | Id | +----------------------+------------------+------+ | Afghanistan | Kabul | 1 | ... | Sweden | Stockholm | 3048 | ... | Germany | Berlin | 3068 | ... | United States | Washington | 3813 | ... +----------------------+------------------+------+ 232 rows in set (#.## sec)

Instructor Note: The SELECT syntax <table_name>.<column_name> is required in the above example because the column "Name" would be ambiguous otherwise. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-3

Developing Dynamic Web Applications with MySQL and PHP


169

Chapter 10- SQL Joins

10.3.2

The INNER JOIN Keywords The form of inner join syntax just discussed uses the comma operator in the FROM clause to name the joined tables. Another inner join syntax uses the INNER JOIN keywords. With this syntax, those keywords replace the comma operator between table names in the FROM clause. Also, with INNER JOIN, the conditions that indicate how to perform record matching for the tables move from the WHERE clause to become part of the FROM clause. There are two syntaxes for specifying matching conditions with INNER JOIN queries: Add ON and an expression that states the required relationship between tables. Suppose that a join performs a country code match between the CountryLanguage and Country tables. The join would be written as follows: SELECT Country.Name, CountryLanguage.Language FROM CountryLanguage INNER JOIN Country ON CountryLanguage.CountryCode = Country.Code; If the name of the joined column is the same in both tables, add USING() rather than ON after the table names, and list the name within the parentheses. For example, if the country code column happened to be named CountryCode in both tables, the query could be written like this: SELECT Country.Name FROM City INNER JOIN CountryLanguage USING (CountryLanguage.CountryCode) WHERE CountryLanguage.Language='Turkish'; If tables using more than one pair of like-named columns are being joined, list the column names within the parentheses of the USING() clause separated by commas. The ON Clause Similar to WHERE, the ON clause in a join specifies how to match records in the joined tables, and eliminates non-corresponding combinations of rows from the output. The ON clause also can include additional conditions to further restrict the output and answer more specific questions. Here are some examples:

170

In which countries is the Swedish language spoken? To answer this, include a condition that identifies the language desired:

mysql> SELECT Country.Name, CountryLanguage.Language -> FROM CountryLanguage INNER JOIN Country -> ON CountryLanguage.CountryCode = Country.Code -> AND Language = 'Swedish'; +---------+----------+ | Name | Language | +---------+----------+ | Norway | Swedish | | Sweden | Swedish | | Finland | Swedish | | Denmark | Swedish | +---------+----------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-4

Developing Dynamic Web Applications with MySQL and PHP


171

Chapter 10- SQL Joins

SELECT Constructs Joins can use any of the constructs allowed for single-table SELECT statements. The following join uses the COUNT() function and a GROUP BY clause to summarize the number of languages spoken per country, and a HAVING clause to restrict the output to include only those countries where more than 10 languages are spoken: mysql> -> -> -> -> SELECT COUNT(*), Country.Name FROM CountryLanguage INNER JOIN Country ON CountryLanguage.CountryCode = Country.Code GROUP BY Country.Name HAVING COUNT(*) > 10;

+----------+--------------------+ | COUNT(*) | Name | +----------+--------------------+ | 12 | Canada | | 12 | China | | 12 | India | | 12 | Russian Federation | | 11 | South Africa | | 11 | Tanzania | | 12 | United States | +----------+--------------------+ Note: The INNER JOIN keywords are equivalent to the JOIN keyword interchangeably. They can be used

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-5

Developing Dynamic Web Applications with MySQL and PHP


172

Chapter 10- SQL Joins

10.4 Outer Joins


Whereas an INNER JOIN will find combinations of matching rows from joined tables, the OUTER JOIN also finds the instances where a row in one table has no match in another table. An OUTER JOIN find matches (just like an INNER JOIN), but also identifies mismatches. Two forms of outer joins are LEFT JOIN and RIGHT JOIN. These do not use the comma separator or the INNER JOIN keywords. They each answer the same kinds of questions, but differ slightly in their syntax. That is a LEFT JOIN can always be re-written into a equivalent RIGHT JOIN. (In the following sections, the terms left table and right table refer to the tables named first and second in the FROM clause, respectively.)

173

10.4.1

Left Outer Join A left join is a type of outer join, written using the LEFT JOIN keywords. A left join treats the left table (the first one named) as a reference table and produces output for each row selected from it, whether or not the row is matched by rows in the right table. Like a join written with the INNER JOIN keywords, a LEFT JOIN is written using either ON or USING() after the table names in the FROM clause. For example an inner join can associate country names listed in the Country table with the languages spoken in those countries through a join based on country codes with the CountryLanguage table. But it cannot provide information about which countries aren't associated with any language in the CountryLanguage table. Answering the latter question is a matter of identifying which country codes present in the Country table are not present in the CountryLanguage table. As illustrated below, the LEFT JOIN will result in a list that shows where there were empty (NULL) values for the Language;
mysql> SELECT Country.Name, CountryLanguage.Language -> FROM Country -> LEFT JOIN CountryLanguage -> ON Country.Code = CountryLanguage.CountryCode; +-----------------------------+------------------+ | Name | Language | +-----------------------------+------------------+ | Aruba | Dutch | | Aruba | English | | Aruba | Papiamento | | Aruba | Spanish | | Afghanistan | Balochi | ... | | | | | | | | Antarctica French Southern territories Antigua and Barbuda Antigua and Barbuda Australia Australia Australia Australia ... | | | | | | | | NULL NULL Creole English English Arabic Canton Chinese English German | | | | | | | |

990 rows in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-6

Developing Dynamic Web Applications with MySQL and PHP


174

Chapter 10- SQL Joins

Filter Out Matches Furthermore, with an appropriate WHERE clause, an OUTER JOIN can filter out matches to display only the mismatches. The following query can be used, with a LEFT JOIN which requires row combinations to have NULL in the right table; mysql> SELECT Country.Name, Country.Language -> FROM Country LEFT JOIN CountryLanguage -> ON Country.Code = CountryLanguage.CountryCode -> WHERE CountryLanguage.CountryCode IS NULL; +----------------------------------------------+----------+ | Name | Language | +----------------------------------------------+----------+ | Antarctica | NULL | | Bouvet Island | NULL | | British Indian Ocean Territory | NULL | | South Georgia and the South Sandwich Islands | NULL | | Heard Island and McDonald Islands | NULL | | French Southern territories | NULL | +----------------------------------------------+----------+ 6 rows in set (#.## sec)

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-7

Developing Dynamic Web Applications with MySQL and PHP


175

Chapter 10- SQL Joins

10.4.2

Right Outer Join A right join is another type of outer join, written using the RIGHT JOIN keywords. Every RIGHT JOIN corresponds to an equivalent LEFT JOIN. The only difference is that the roles of the tables are reversed relative to the roles in a RIGHT JOIN. That is, the right table is the reference table, so a RIGHT JOIN produces a result for each row in the right table, whether or not it has any match in the left table. The previous example showed the result of a LEFT JOIN . The example below is the same statement, but with a RIGHT JOIN: mysql> SELECT Name, Language -> FROM Country -> RIGHT JOIN CountryLanguage -> ON Code = CountryCode -> WHERE CountryCode IS NULL; Empty set (#.## sec) Note that the join is now being referenced to the right table CountryLanguage, which yields no results (empty set). Syntactically, converting a left join to a right join requires only that the order be reversed in which the tables are named. It isn't necessary to also reverse the order in which the columns are named in the ON clause, but it can help make the query clearer to name the columns in the same order as the tables in which they appear.

Instructor Note: A best practice is to only use LEFT JOINs. Also mention that USING() can be used a LEFT JOIN b USING (c1,c2,c3); And also IS NULL SELECT table1.* FROM table1 ______________________________________________________________________________________________ LEFT JOIN table2 ______________________________________________________________________________________________ ON table1.id=table2.id WHERE table2.id IS NULL; ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-8

Developing Dynamic Web Applications with MySQL and PHP


176

Chapter 10- SQL Joins

10.5 Using Qualifiers and Aliases


When tables are joined, it's often the case that the tables contain columns with the same names. If such a column is referred to in the query, it's ambiguous which table the column reference applies to. This ambiguity usually can be addressed by qualifying column names with table names. However, if a join is on a table to itself, even the table name is ambiguous and it's necessary to use aliases to disambiguate table references. This section describes how to address naming issues in queries by qualifying column and table names and by using aliases. 10.5.1 Qualifying Column Names If a column name used in the query appears in more than one table, the name is ambiguous and it's necessary to provide information that identifies which table the column is connected to. This has been accommplished by qualifying the column name with the appropriate table name throughout the examples in this chapter. If name qualification has not been used, then problems can arise such as the following simple query that associates Country names and City names based on the Country codes that are common to the two tables. This results in a small complication: mysql> SELECT Name, Name FROM Country JOIN City -> ON Code = CountryCode; ERROR 1052 (23000): Column: 'Name' in field list is ambiguous The problem here is that the name column in the Country table and the name column in the City table both are called Name. MySQL has no way to know which instance of Name in the query goes with which table. To resolve this ambiguity, qualify the references to Name with the appropriate table name so that MySQL can tell which table to use for each reference:

177

mysql> SELECT Country.Name, City.Name -> FROM Country JOIN City -> ON Code = CountryCode; +-------------+----------------+ | Name | Name | +-------------+----------------+ | Afghanistan | Kabul | | Afghanistan | Qandahar | | Afghanistan | Herat | | Afghanistan | Mazar-e-Sharif | | Netherlands | Amsterdam | | Netherlands | Rotterdam | | Netherlands | Haag | ...

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-9

Developing Dynamic Web Applications with MySQL and PHP


178

Chapter 10- SQL Joins

Qualifiers is Good Practice Although it might not always be necessary to provide table qualifiers in a join, it's always allowable to do so. Thus, Code and CountryCode in the preceding example are unambiguous because each appears in only one table, but they can be qualified explicitly if desired: mysql> SELECT Country.Name, City.Name -> FROM Country JOIN City -> ON Country.Code = City.CountryCode; +-------------+----------------+ | Name | Name | +-------------+----------------+ | Afghanistan | Kabul | | Afghanistan | Qandahar | | Afghanistan | Herat | | Afghanistan | Mazar-e-Sharif | | Netherlands | Amsterdam | | Netherlands | Rotterdam | | Netherlands | Haag | ... Adding qualifiers even when they aren't necessary to enable MySQL to understand a query often can make the query easier for people to understand, particularly those who are unfamiliar with the tables. Without the qualifiers, it might not be evident which table each column comes from. It also prevents problems when case tables are extended.

179

Multiple Name Qualifiers More complex queries might involve multiple ambiguous columns. For example, the Country and City tables each have a Population column, and they can be compared to identify cities that contain more than 75% of their country's population: mysql> -> -> -> SELECT Country.Name, Country.Population, City.Name, City.Population FROM City JOIN Country ON City.CountryCode = Country.Code AND (Country.Population * .75) < City.Population;

+---------------------------+------------+--------------+------------+ | Name | Population | Name | Population | +---------------------------+------------+--------------+------------+ | Falkland Islands | 2000 | Stanley | 1636 | | Gibraltar | 25000 | Gibraltar | 27025 | | Cocos (Keeling) Islands | 600 | Bantam | 503 | | Macao | 473000 | Macao | 437500 | | Pitcairn | 50 | Adamstown | 42 | | Saint Pierre and Miquelon | 7000 | Saint-Pierre | 5808 | | Singapore | 3567000 | Singapore | 4017733 | +---------------------------+------------+--------------+------------+ Both Name and Population require table qualifiers in this query because each is ambiguous.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-10

Developing Dynamic Web Applications with MySQL and PHP


180

Chapter 10- SQL Joins

10.5.2

Qualifying and Aliasing Table Names Qualifying column names with table names resolves many column name ambiguities, but sometimes even the table name is ambiguous. This happens in two ways; Same column name, different tables Different or same column names, same tables

First, a join might be performed between tables that have the same name but come from different databases. In this case, it is necessary to place qualifiers to address the table names along with database names as well. Suppose that two databases world1 and world2 both have a table named Country and it is necessary to determine which names are present in both tables. The query can be written like this: SELECT world1.Country.Name FROM world1.Country JOIN world2.Country ON world1.Country.Name = world2.Country.Name;

______________________________________________________________________________________________ Instructor Note: Mention that you can also alias column names. Some applications may require column ______________________________________________________________________________________________ aliasing. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-11

Developing Dynamic Web Applications with MySQL and PHP


181

Chapter 10- SQL Joins

10.5.3

Self Joins A table name is always ambiguous when table is joined to itself using a self-join. For example, the Country table in the world database contains an IndepYear column indicating the year in which each country achieved independence. To find all countries that have the same year of independence as some given country, a self-join can be used. However, the query cannot be written like this: mysql> SELECT IndepYear, Name, Name -> FROM Country JOIN Country -> ON IndepYear = IndepYear AND Name = 'Qatar'; ERROR 1066 (42000): Not unique table/alias: 'Country' Furthermore, the ambiguity cannot be removed from column references by preceding them with table name qualifiers because the names remain identical: mysql> SELECT Country.IndepYear, Country.Name, Country.Name -> FROM Country JOIN Country -> ON Country.IndepYear = Country.IndepYear -> AND Country.Name = 'Qatar'; ERROR 1066 (42000): Not unique table/alias: 'Country' It doesn't even help to add a database name qualifier because the database is the same for both tables. To address this naming issue, create an alias for one or both table references and refer to the aliases elsewhere in the query. The aliases give an alternative unambiguous name by which to refer to each instance of the table in the query. Here is one solution that aliases both tables:

182

mysql> SELECT t1.IndepYear, t1.Name, t2.Name -> FROM Country AS t1 JOIN Country AS t2 -> ON t1.IndepYear = t2.IndepYear AND t1.Name = 'Qatar'; +-----------+-------+----------------------+ | IndepYear | Name | Name | +-----------+-------+----------------------+ | 1971 | Qatar | United Arab Emirates | | 1971 | Qatar | Bahrain | | 1971 | Qatar | Bangladesh | | 1971 | Qatar | Qatar | +-----------+-------+----------------------+

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-12

Developing Dynamic Web Applications with MySQL and PHP


183

Chapter 10- SQL Joins

10.6 Multi-Table UPDATE and DELETE Statements


MySQL allows the use of join syntax in UPDATE and DELETE statements to enable updates or deletes that involve multiple tables. They can be useful for storage engines where transactions and foreign keys are not supported, and to make sure that the tables are consistent. These statements can be used to perform the following operations: Update rows in one table by transferring information from another table Update rows in one table, determining which rows to update by referring to another table Update rows in multiple tables with a single statement Delete rows from one table, determining which rows to delete by referring to another table

Delete rows from multiple tables with a single statement Some of the principles involved in writing joins in SELECT statements also apply to multiple-table UPDATE and DELETE statements. This section provides a brief overview of their syntax. A multiple-table UPDATE is an extension of a single-table statement: Following the UPDATE keyword, name the tables involved in the operation, separated by commas. (all the tables used in the query must be named, even if all of them are not being updated.) In the WHERE clause, describe the conditions that determine how to match records in the tables.

In the SET clause, assign values to the columns to be updated. These assignments can refer to columns from any of the joined tables. For example, this statement identifies matching records in two tables based on id values, and then copies the name column from t2 to t1:
UPDATE t1, t2 SET t1.name = t2.name WHERE t1.id = t2.id;

Multiple-table DELETE statements can be written in two formats. The following example demonstrates one syntax, for a query that deletes rows from a table t1 where the id values match those in a table t2:
DELETE t1 FROM t1, t2 WHERE t1.id = t2.id;

The second syntax is slightly different:


DELETE FROM t1 USING t1, t2 WHERE t1.id = t2.id;

To delete the matching records from both tables, the statements are:
DELETE t1, t2 FROM t1, t2 WHERE t1.id = t2.id; DELETE FROM t1, t2 USING t1, t2 WHERE t1.id = t2.id;

Multiple-Table Operations The ORDER BY and LIMIT clauses normally supported by UPDATE and DELETE aren't allowed when these statements are used for multiple-table operations.
184

Specifically, INNER JOIN syntax is also allowed and can be preferable to the comma separated join syntax shown above. In the following example, the employee named 'Sean' is being deleted from both the employees and the access_rights tables, according the their matching id numbers;
DELETE FROM employees INNER JOIN access_rights USING (user_id) WHERE employees.name_first='Sean';

Or to delete only the rights but not the user;


DELETE access_rights.* FROM employees INNER JOIN access_rights USING (user_id) WHERE employees.name_first='Sean';

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-13

Developing Dynamic Web Applications with MySQL and PHP

Chapter 10- SQL Joins

Lab 10-A
In this exercise you will use the methods covered in this chapter to expand upon your knowledge of using joins in MySQL. This will require a MySQL command line client and the world database. ACTION (You Do) 1. Using the world database, create a comma separated join, find all the cities in the world where the 'Turkish' language is spoken. List the language and the City names. This is accomplished by typing the following in the mysql client: SELECT City.Name, Language FROM CountryLanguage, City WHERE CountryLanguage. CountryCode = City.CountryCode AND Language = 'Turkish'; 2. Using the world database, create an inner join, find all the cities in the world where the 'Turkish' language is spoken. List the language and the City names. This is accomplished by typing the following in the mysql client: SELECT City.Name, Language FROM CountryLanguage INNER JOIN City ON CountryLanguage. CountryCode = City.CountryCode AND Language = 'Turkish'; 3. Using the world database, perform a SELECT/INNER JOIN which combines Country and City tables to retrieve the country name and city district on the equality of Code to CountryCode, where there is a City named 'San Antonio'. This is accomplished by typing the following in the mysql client: SELECT Country.Name, City.District FROM Country INNER JOIN City ON CountryCode = Code WHERE City.Name = 'San Antonio'; The Country Name and the State in which San Antonio is located is displayed on the screen use a combination of data from the Country and City tables. Using an inner join, a listing of all the cities where 'Turkish' is spoken is listed. COMPUTER RESPONSE / Comment Using a comma separated join, a listing of all the cities where 'Turkish' is spoken is listed.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-14

Developing Dynamic Web Applications with MySQL and PHP ACTION (You Do) 4. Execute the following to prepare for an update; SELECT * FROM City WHERE Name='Casablanca'; and SELECT * FROM Country WHERE Code='mar'\G 5. Now make an update so that the name of the country associated with the city of 'Casablanca', will also be named 'Casablanca' by entering the following in the mysql client: UPDATE Country, City SET Country.Name = City.Name WHERE Country.Code = City.CountryCode AND City.Name = 'Casablanca'; 6. Enter the following statements in the mysql client to ensure that the update made in step 5 was made to the data: SELECT * FROM Country WHERE Code='mar'\G 7. Delete the newly renamed country of 'Casablanca' and all the cities associated with this Country by typing the following into the mysql client: DELETE Country, City FROM Country, City WHERE Country.Code = City.CountryCode AND Country.Name = 'Casablanca';

Chapter 10- SQL Joins

COMPUTER RESPONSE / Comment Note the code and country code information as well as the country name and city name, as they are now.

The following response would show that the statement was accepted: Query OK, 1 row affected (#.## sec) Rows matched: 1 Changed: 1 Warnings: 0

The name of the Country associated with the Country code 'mar' is now identified as 'Casablanca'.

The row for Casablanca is deleted in the Country table and all records associated with this Country in the City table.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-15

Developing Dynamic Web Applications with MySQL and PHP


185

Chapter 10- SQL Joins

Lab 10-B
In this exercise, you will use some of the join commands covered in this chapter to display data in the photo_album database.

1. 2. 3. 4. 5. 6.

Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). View the existing databases that the MySQL Server is maintaining. Utilize the photo_album database. Query the database to display the active primary customer (email, first and last name) and all the associated active login names associated with that customer. Modify the query just issued to also show the image name of all the active files associated with each one of the login names. The customer with the login name of Frankie has requested that his login name be changed to just 'Frank' to make it easier for him to remember it. The only problem is that the change must also take place in the images table. This is not automatic due to the fact that this table is a MyISAM table (rightfully so) and there is no Foreign Key constraints that would make the change automatic. However, this is not a problem with the right update statement against the two tables at once. Can you make one query that will update both the tables at once?

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-16

Developing Dynamic Web Applications with MySQL and PHP


186

Chapter 10- SQL Joins

10.7 Chapter Summary


In this chapter, you have learned to: Describe the concept of a Join When it's necessary to draw on information that is stored in multiple tables, use a join conditionan operation that produces a result by combining (joining) information in one table with information in another. A join that identifies combinations of matching rows from two tables is called an inner join. The joining is done by connecting one table, using the primary key, another table that references it with a foreign key. Inner joins may be written using two different syntaxes. One syntax lists the tables to be joined separated by a comma. The other uses the INNER JOIN keywords. Whereas an INNER JOIN will find combinations of matching rows from joined tables, the OUTER JOIN also finds the instances where a row in one table has no match in another table. An OUTER JOIN find matches (just like an INNER JOIN), but also identifies mismatches. Two forms of outer joins are LEFT JOIN and RIGHT JOIN. These do not use the comma separator or the INNER JOIN keywords. They each answer the same kinds of questions, but differ slightly in their syntax. That is a LEFT JOIN can always be rewritten into a equivalent RIGHT JOIN. A table name is always ambiguous when table is joined to itself using a self-join. To address this naming issue, create an alias for one or both table references and refer to the aliases elsewhere in the query. The aliases give an alternative unambiguous name by which to refer to each instance of the table in the query. MySQL allows the use of join syntax in UPDATE and DELETE statements to enable updates or deletes that involve multiple tables. They can be useful for storage engines where transactions and foreign keys are not supported, and to make sure that the tables are consistent.

Connect Data from Multiple Tables using various Join Statements

Resolve Name Clashes when Joining Tables

Join a Table to Itself

Join Tables with UPDATE and DELETE statements

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 10-17

Developing Dynamic Web Applications with MySQL and PHP

188

CHAPTER 11 MYSQL DATA DRIVEN WEB BASED FORMS


187

Developing Dynamic Web Applications with MySQL and PHP


189

Chapter 11- MySQL Data Driven Web Forms

11 MYSQL DATA DRIVEN WEB BASED FORMS


11.1 Learning Objectives
This chapter provides the knowledge necessary to create web based forms that interact with the end user and the data within MySQL. At the completion of this chapter, you will be able to: Establish and Close a Connection to the MySQL Server from PHP Retrieve Data from the MySQL Server Insert and Update Data in a MySQL Database Using a PHP Web Form Delete MySQL database data with PHP Retrieve MySQL Metadata Retrieve Error Information from MySQL using PHP

Instructor Notes: This chapter does not have any inline labs; however, there are numerous examples that the students can perform throughout the chapter. Allow the students to actually enter and test the examples as you see fit in lieu of inline labs. A Chapter11.php file is available that contains all the scripts and there output. In addition, there are multiple files that are also associated with this chapter: City_Update.php, City_Insert.php, City_Delete.php and connect_info.php. Each of these files will be required to support the Chapter11.php file. The further practice also contains numerous PHP files that can be viewed and compared for the solutions to the labs. The names of these files are view_images.php, view_images2.php, view_images3.php, view_images4.php and view_images5.php. Additional information about these files can be found in the further practice solution. Extremely Important: For the inline labs to work, each student must also have a directory under their web server ______________________________________________________________________________________________ document root called uploaded_files. In this file is where the images should be stored because the scripts in the further practice will look in this folder for displaying the images. The idea of uploading images will be discussed in ______________________________________________________________________________________________ later chapters, but for now the images should be placed in this directory for access by the scripts. It will also be ______________________________________________________________________________________________ important for the rights of this folder be open enough for viewing and upload for later events. ______________________________________________________________________________________________

Page 11-1

Developing Dynamic Web Applications with MySQL and PHP


190

Chapter 11- MySQL Data Driven Web Forms

11.2 Connecting to MySQL


PHP and MySQL are two different technologies that have found favor in the community of web developers based on their combined strength. This of course has given rise to both technologies finding great success in the marketplace that they may not have enjoyed otherwise. Those responsible for the two technologies have worked hard to provide the end users easy to use interfaces and technologies to ensure that the integration of the two are smooth and support the creation of next generation websites. User Privileges MySQL has a very strong authentication system that allows multiple security levels for each user that can access the server. MySQL's highly effective security system can cause headaches for those trying to break into the data, but likewise can cause headaches for those that are authorized to access the data. MySQL sees any requests from PHP in the same way that it sees requests from any other API (such as the mysql client or MySQL Query Browser) and will require a login name and password to determine what can and can not be accomplished with the data in the MySQL Server. For the purposes of the training at this point, the user that will be used (root) has complete access to everything within the database ensuring that there are no limitations on what can and can not be done. However, this practice is acceptable in a training environment, but should never be utilized in a system that will be truly accessible by others (like a website). PHP MySQL API PHP and MySQL both offer an Application Programming Interface (API), each creating the ability to interface between the two technologies. The basics of both API's offer multiple PHP functions which are capable of performing a wide array of tasks against the data in the MySQL Server. These functions will be the topic of discussion for this chapter and will provide the tools necessary to complete the majority of tasks against the data in the MySQL server. Connecting to MySQL The most basic request necessary when working with PHP and MySQL is the ability to connect to the MySQL server itself. mysql_connect() - This function (which is a PHP resource type) is used to establish an initial connection to the MySQL server. Believe it or not, each parameter in the function make-up below is optional (a connection can be made to MySQL that would have no rights whatsoever): $link_id = mysql_connect([hostname [:port] [:/path/to/socket] [, username] [, password]]) In the case of this training, the hostname will be referred to as 'localhost' due to the fact that the webserver is local and use 'root' as our username. As far as the password, the password 'training' will be used; however, check with the instructor to ensure that this is the password that should be used. The $link_id is not necessary to establish a connection to the MySQL server in either method; however, when it comes to ensuring that a specific connection is closed, the $link_id can be useful.

Instructor Notes: User Authentication is a discussion that takes up an entire chapter in the MySQL & PHP course and any deep discussions at this point should be held off until that time if teaching the MySQL & PHP course. ______________________________________________________________________________________________ In addition, there will be a complete hands on lab at the end of this chapter that will cover the majority of the content ______________________________________________________________________________________________ in this chapter, please feel free to supplement this hands on lab with having your students perform some of the examples shown as you are going through the instruction. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-2

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

Disconnecting from MySQL Even though it is important to understand the process of connecting to the MySQL server itself, it is also important to terminate the MySQL connection properly to ensure that there is no possibility of a connection remaining open beyond the need (which of course could become a security concern). If there is no specific termination function to the MySQL server, PHP's garbage collection feature will close the connection when the script terminates. There are two ways to close a connection to the MySQL server. mysql_close($link_id) - This use of the mysql_close() function, which would include the $link_id of the connection resource that connected PHP to the mysql server would be closed. By identifying the $link_id, PHP looks for that connection to the MySQL server to close. mysql_close($link_id) mysql_close() - This use of the mysql_close() function, which does not include the $link_id, the most recently open link is assumed. mysql_close() Putting it all together The following example demonstrates an example of PHP connecting to the MySQL server, completing a query against the data contained in the MySQL server and then closing out the connection to the MySQL server (the other details of this script will be discussed throughout the remainder of this chapter): <?php /* Connect to MySQL server */ $linkID1 = mysql_connect('localhost','root','training') or die("Could not connect to MySQL server"); /* Query the MySQL Server for Information */ $query = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'world'"; $result = mysql_query($query, $linkID1); while ($row = mysql_fetch_array($result)) { print $row[0]."<br>"; } /* Close the connection to the MySQL server */ mysql_close($linkID1); ?> Even though it is not necessary to provide the link identifier in the mysql_close() function seeing there is only one open connect; however, it is best practice to include the link identifier to limit potential problems when it should be included.

191

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-3

Developing Dynamic Web Applications with MySQL and PHP


192

Chapter 11- MySQL Data Driven Web Forms

11.2.1

Independent Connection Information For many programmers, the idea of storing connection information (such as username and password) directly in the script itself is a little unnerving and rightfully so. Even though, with the correct privileges assigned to the actual file housing the php script, there would be little concern for the scripts themselves from being seen. As a best practice, it is wise to create a separate PHP script file that would contain variables that would contain the connection information and could be used in the PHP script that is actually connecting to the MySQL server. A typical file containing this connection information would look something like the example below: <?php // MySQL Server Connection Information $dbhost = 'localhost'; $dbuser = 'root'; $dbpass = 'training'; ?> In this example, the file would be saved as "connect_info.php" and stored in the same folder as our php script (most likely the htdocs folder of the apache server). Using this file as our source for the connection information, we would rewrite the script presented earlier as:

193

<?php /* Load variable that will be used in mysql_connect */ include "connect_info.php"; /* Connect to MySQL server */ $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); /* Query the MySQL Server for Information */ $query = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'world'"; $result = mysql_query($query, $linkID1); while ($row = mysql_fetch_array($result)) { print $row[0]."<br>"; } /* Close the connection to the MySQL server */ mysql_close($linkID1); ?>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-4

Developing Dynamic Web Applications with MySQL and PHP


194

Chapter 11- MySQL Data Driven Web Forms

Securing Connection Information Having connection information stored in a plain readable fashion can be disconcerting to many new web developers; however, with the right security steps, this can be less of a concern. The following are some steps that should be addressed to make sure that the information is kept secure: Operating System Rights - Almost every operating system provides a means to limit access to files by end users in one fashion or another. In the case of Unix like systems (ex. Linux), this is handled by changing the file ownership privileges to the user that is executing the web process and setting the connection file permissions to -r-------- (or 400). Remote Connections - In the examples up to this point, the connections have been made to localhost; however, there are setups in which a connection is made to an external server that requires sending information through an interconnect of some sort. When in transit over this interconnect, the information in the file submitted can be intercepted and viewed for content by anyone having access to the interconnect. The information transmitted can be encrypted by using such encryption as Secure Socket layer (SSL). Script Encoding - There are multiple products on the market that provide encryption of the source files used by PHP and associated decryption tools without affecting the processing of the scripts. This can be beneficial for both files that will be transmitted over an interconnect and those files that will not be transmitted over an interconnect. However, the overhead that provides an additional level of maintenance must be considered before implementing such a solution.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-5

Developing Dynamic Web Applications with MySQL and PHP


195

Chapter 11- MySQL Data Driven Web Forms

11.3 Retrieving Data


The process of retrieving data once a connection has been made to the MySQL server is similar to the process of interacting with the data through the mysql client. The first thing that needs to be addressed is the database that holds the table (which in turn holds the data). Selecting a Database In the mysql client, a database is identified (or selected) by the USE <database> command. In PHP, this is accomplished with a PHP MySQL API function called mysql_select_db(). This function identifies the database that should be used for any subsequent requests to the data, which eliminates the need to qualify every table (or other MySQL resource) called with the database name. There are two ways to use this function: mysql_select_db($db_name, $link_id) Using the mysql_select_db function in this fashion ensures that the resource that initiated the connection to the MySQL server would be selected with the $link_id. The variable, that is identified here as $db_name, would be the table that would be selected for use in any subsequent queries. mysql_select_db($db_name, $link_id) or die("Could not select the $db_name database!"); mysql_select_db($db_name) Using the mysql_select_db function in this fashion forces PHP to use the last connection made to the MySQL server to submit the request. Without a $link_id to choose from, the MySQL server chosen could be the wrong one to use (not containing the database identified by $db_name). Best practice is to include the $link_id, but it is not necessary. mysql_select_db($db_name) or die("Could not select the $db_name database!"); As stated, this function is not necessary to query the data in the MySQL server; however, without this step, any reference to resources in the MySQL server would need to be preceded with the database name (ex. SELECT * FROM world.City vs. just typing SELECT * FROM City) Querying MySQL In the mysql client, any interaction is accomplished through a query command. These query commands include data definition language (DDL) and data manipulation language (DML) commands that pretty much include every command that can be issued into MySQL. Of course, MySQL has non-standard SQL commands such as SHOW ... which can also be queried and can be called from PHP. To query the MySQL server in PHP, the mysql_query() function is used. Similar to the other functions mentioned up to this point, there are two ways to use this function: mysql_query($query, $link_id) Using the mysql_query function in this fashion ensures that the resource that initiated the connection to the MySQL server would be selected with the $link_id. The variable, that is identified here as $query, would be the query that would be executed against the MySQL server. $query_results = mysql_query($query, $link_id); mysql_query($query) Using the mysql_query function in this fashion forces PHP to use the last connection made to the MySQL server to submit the request. Without a $link_id to choose from, the MySQL server chosen could be the wrong one to use (not being able to return the results of $query because the server does not contain the data). Best practice is to include the $link_id, but it is not necessary. $query_results = mysql_query($query); Instructor Notes: Just in case it comes up; DDL statements are used to build and modify the structure of your tables and other objects in the database. When you execute a DDL statement, it takes effect immediately. DML statements are used to work with the data in tables (SELECT, UPDATE, INSERT, DELETE, etc.). ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-6

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

Combining mysql_select_db() and mysql_query() The PHP MySQL API includes a function that is able to group the selection of a database and a query against that database. This function is called mysql_db_query() and can be used in place of mysql_select_db() and mysql_query(). The syntax for the proper way to use this command is: $query_result = mysql_db_query($db_name, $query, $link_id); ... or without the $link_id variable ... $query_result = mysql_db_query($db_name, $query);
196

Displaying Query Results The majority of query commands that are sent to MySQL are of the SELECT nature in which a set of data will be returned from the query. Understanding how to deal with the query results from SELECT statements is probably one of the most important tasks associated with PHP and MySQL interactions. There are four main ways to accomplish this: mysql_result($query_result, $row_id, $column_name) Using the mysql_result() function will return a single row, single column of data from the query output. The $row_id is an offset numeric identifier (0 being the first row, 1 being the second row and so on). The $column_name is the actual column identifier that is returned by MySQL. In the event that the query used an alias to identify the column, the alias name must be used to identify the column. In a majority of cases, a single row of data is not that useful; however, using a looping construct with the mysql_result() function can prove quite useful: $query = "SELECT * FROM world.Country LIMIT 5"; $query_results = mysql_query($query, $linkID1); for ($count=0; $count <= mysql_numrows($query_results); $count++) { $country_code = mysql_result($query_results, $count, 'Code'); $country_name = mysql_result($query_results, $count, 'Name'); print "$country_name($country_code)<br>\n"; } This portion of a PHP script would return the Country Name and the associated Country Code, in parenthesis, for every record in the Country table located in the world database. The mysql_numrows($query_results) is a function that returns and integer of the number of rows that is returned from the query executed. Thus in this case, the for loop construct is terminated when it reaches the end of the rows returned.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-7

Developing Dynamic Web Applications with MySQL and PHP


197

Chapter 11- MySQL Data Driven Web Forms

mysql_fetch_row($query_result) The mysql_fetch_row() function is a step up from the mysql_result() function by retrieving and storing the entire row of data into an indexed array. The array can then be parsed, by their numeric index location, for the specific results that are desired. By itself, the advantage may not be much over the mysql_result() function; however, combining this function with the list() function can provide a much more versatile tool. $query = "SELECT Code, Name FROM world.Country LIMIT 5,5"; $query_results = mysql_query($query, $linkID1); while (list($country_name, $country_code) = mysql_fetch_row($query_results)) { print "$country_name($country_code)<br>\n"; } This portion of a PHP script is identical to the previous example used with the mysql_result() function. The differences between the two scripts include a more defined SQL query statement (which is a best practice anyways), the use of a while loop construct (instead of a for loop construct) and the use of the list() function to store the mysql_fetch_row() associated array into two variables used to create the output contained therein. mysql_fetch_array($query_result) The mysql_fetch_array() function is a step up from the mysql_fetch_row() function by retrieving and storing the entire row of data into an index and associative array. The array can then be parsed, either by the numeric index location or by the column name value, for the specific results that are desired. $query = "SELECT Code, Name FROM world.Country LIMIT 10,5"; $query_results = mysql_query($query, $linkID1); while ($row = mysql_fetch_array($query_results, MYSQL_BOTH)) { $country_code = $row['Code']; $country_name = $row['Name']; print "$country_name($country_code)<br>\n"; } In the above example, the returned result is stored both as an index and an associative array called $row. The contents of the $row array are then parsed by their associated column names and displayed duplicating the previous examples. They could of easily have been parsed by their index location in the array ($row[0] and $row[1]). However, if there is no need for only one array method, the result type can be modified to provide only one array type: o MYSQL_ASSOC - Replacing MYSQL_BOTH, in the above example, and replacing it with MYSQL_ASSOC will result in the $row array containing only an associative array. The process of calling the values from the array, is by using the column name as the key representing the data (as shown in the example above). The mysql_fetch_assoc() function is identical to this function combination. MYSQL_NUM - Replacing MYSQL_BOTH, in the above example, and replacing it with MYSQL_NUM will result in the $row array containing only an indexed array. The process of calling the values from the array, is by using the numeric indicator as the key representing the data. In this example above, $country_code = $row[0] and $country_name = $row[1] is how the array would be parsed to give the same output.

198

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-8

Developing Dynamic Web Applications with MySQL and PHP


199

Chapter 11- MySQL Data Driven Web Forms

mysql_fetch_object($query_result) The mysql_fetch_object() function is identical to the mysql_fetch_array() function with the exception that an object is returned rather than an array. The array can then be parsed, using object oriented programming, for the specific results that are desired. $query = "SELECT Code, Name FROM world.Country"; $query_results = mysql_query($query, $linkID1); while ($row = mysql_fetch_object($query_results)) { $country_code = $row->Code; $country_name = $row->Name; print "$country_name($country_code)<br>\n"; } In the above example, it is clear that there is not a large advantage from objects to arrays; however, the use of Objected Oriented programming techniques enhances PHP in many other areas and this capability can be incorporated in those areas.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-9

Developing Dynamic Web Applications with MySQL and PHP


200

Chapter 11- MySQL Data Driven Web Forms

11.4 The Web Interface


Due to the fact that PHP is a programming language that is primarily designed to enhance the delivery of content in web based applications, it would make sense that if there was a need to manipulate or retrieve data in MySQL from PHP, a HTML form would have to come into play to collect or retrieve the data. The following example is a breakdown of an HTML form that manges the interface to a MySQL database called world. Each section of the breakdown will be explained below the script:
(1) HTML Head Element <html><head><title>World Database</title></head> <body>

(2) Connecting to the MySQL Server


<?php // Load variables ($dbhost,$dbuser,$dbpass) that will be used in mysql_connect //// This script contains the three variables mentioned and are located in the //// same directory as the PHP scripts utilizing the variables (this is not //// the recommended practice - they should be in a directory not accessible //// through the web browser; however, for training purposes this is //// acceptable) include "connect_info.php"; // Connect to MySQL server //// Prepare the link to the MySQL Server with the information //// gathered from the connect_info.php file. If the connection //// can not be completed, a message will be displayed through the //// web browser that the script "Could not connect to the MySQL //// server" (the or die portion) $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to the MySQL server"); // Identify which MySQL database to use //// Prepare the actual database to utilize in the MySQL server. //// If the connection to the database can not be completed (access issues, //// database not existing, etc.), a message will be displayed through the //// web browser that the script "Could not connect to the world //// database" (the or die portion) mysql_select_db("world",$linkID1) or die ("Could not connect to the world database"); ?>

(3) Looking up the City


<H1>World Database Web Interface</H1>
<form name="world_interface" method="post" action="<?php print $_SERVER['PHP_SELF'] ?>">

<p><strong>Enter a city name to lookup:</strong> <input type="text" name="CityLookup"> <input type="submit" name="Submit" value="Lookup City"> </p> </form>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-10

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

(4) Collecting City Information


<?php //Receive City Name to Lookup and Display Content //// Check to see if the "Lookup City" button was pressed if ($_POST['Submit'] == "Lookup City") { // Collect the additional fields sent across //// To prevent query failures, use the mysql_real_escape_string() //// function anytime user provided data is going to be passed into //// MySQL. This function will escape special characters in the //// unescaped_string, taking into account the current character //// set of the connection so that it is safe to place it in a //// mysql_query(). $CityName = mysql_real_escape_string($_POST['CityLookup']); //// This is the actual SQL that is used to collect the data for the //// lookup city. This SQL utilizes a Join to collect the Country Name $lookup_sql = "SELECT City.Name, Country.Code, Country.Name, District, City.Population FROM City, Country WHERE City.CountryCode = Country.Code AND City.Name = '$CityName'"; //// The SQL is executed $lookup_results = mysql_query($lookup_sql, $linkID1); //// If the SQL is executed successfully, then the $lookup_results //// variable will be loaded with values from the database, these //// values are separated out (City Name, Country Code Country Name, //// District and City Population) list($city_name, $country_code, $country_name, $district, $population) = mysql_fetch_row($lookup_results); //// If the city_name variable is filled, then display that and the other //// city information, otherwise, let the end user know the city entered //// to lookup was not valid

(5) Displaying the City Results


if ($city_name) { //// A table is created to display the results cleanly // Form for managing world data (END; needs to have no whitespace in front of it) //// The END commands used to allow large chunks of HTML to be printed print <<<END <form name="world_update" method="post" action="world_update.php"> <table width="700" border="0" cellpadding="3" cellspacing="3"> <tr> <th width="100" scope="col"><div align="left"> <strong>City Name</strong></div></th> <th width="579" scope="col"><div align="left"> <input type="text" name="CityName" value="$city_name"> </div></th> </tr> <tr> <td><div align="left"><strong>Country</strong></div></td> <td><div align="left"> <select name="CountryCode" id="CountryCode"> END; // This will fill the list with countries from Country table //// This is the SQL code that will be used to obtain //// the list items to populate the HTML list form object $query = "SELECT DISTINCT Code, Name FROM Country ORDER BY Name"; //// The prepare SQL is executed against the server $results = mysql_query($query, $linkID1);

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-11

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

//// Each row that is returned is handled and the values stored //// for use in creating the list while ($row = mysql_fetch_array($results, MYSQL_ASSOC)) { $results_code = $row['Code']; $results_name = $row['Name']; // The actual creation of the HTML code to create the list components //// If the country code is the one associated with the country, then //// place the key word selected to have the country be the selected //// country in the list if ($country_code == $results_code) {
print "<option value=\"$results_code\" selected>$results_name</option>\n";

} else { print "<option value=\"$results_code\">$results_name</option>\n"; } } print <<<END2 </select> </p> </tr> <tr> <td><div align="left"><strong>District</strong></div></td> <td><div align="left"> <input name="CityDistrict" type="text" id="CityDistrict" value="$district"> </div></td> </tr> <tr> <td><div align="left"><strong>Population</strong></div></td> <td><div align="left"> <input name="CityPop" type="text" id="CityPop" value="$population"> </div></td> </tr> </table> <p> <input name="Submit" type="submit" id="Submit" value="Update City"> <input name="Submit" type="submit" id="Submit" value="Delete City"> <input name="Submit" type="submit" id="Submit" value="Add City"> </p> </form> END2; } else { //// A response is sent to the user letting them know that the //// information provided was either not accurate or the city does //// not exist print "<p>The city entered does not exist in the database</p>"; } } ?>

(6) Close out the HTML Code


</form></body></html>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-12

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

Disclaimer It is important to understand that the scripts presented in this chapter by no means contain all the options that should be in a user data entry form, in actuality they are quite limited and not very useful in the real world as is (ex. no checks on the data entered). However, the ability to see how the scripts were developed and broken down will add value to future scripts that will be created not only in this class but in the real world beyond the classroom.
201

Explanation of the Web Page Interface (1) HTML Head Element - This section can be considered the meta-information for the actual HTML document as a whole. o <html> - The first element shown tells the web browser reading the text that the main scripting language that will be used in the document will be the Hyper Text Markup Language (HTML). In some cases, a document type header element <!DOCTYPE> will be the first tag in the document. It is good practice to have at least the <html> header; however, neither is completely necessary for the web browser to be able to interpret the page correctly. o <head> - This header opening element tells the server that anything from here until the associated closing tag </head>, should be considered meta-information associated with the HTML document. Even though some browsers will actually display HTML tags that should only be in the body of the HTML, it is not good practice to put anything in here that is part of the actual body of the page. o <title> - This element is responsible for identifying the title of the web page. The text that is contained between the opening title tag, <title>, and the closing title tag, </title>, will be displayed in the application title bar and any tab titles (if using tabs in the browser). o <body> - This element is not exactly part of the head element group; however, for the purposes of this training it will be grouped under this section of the script. The <body> element defines the documents' body. It contains all the contents of the document (like text, images, colors, graphics, etc.). (2) Connecting to the MySQL Server - This section is the PHP script that prepares the connection to the MySQL server for any future PHP sections that will require the use of the database. o include "connect_info.php" - This function will load the PHP elements from the connect_info.php file which includes the $dbhost (hostname), $dbuser (username) and $dbpass (password) for connecting to the MySQL server. o mysql_connect - This function is used to establish an initial connection to the MySQL server. o mysql_select_db - This function identifies the database that should be used for any subsequent requests to the data, which eliminates the need to qualify every table (or other MySQL resource) called with the database name. (3) Looking up the City - The first thing to notice in this portion of the script is the form elements which are the means by which HTML can pass data entered by a user to a specified URL. A form can contain multiple entry elements to include textfields, checkboxes, radio-buttons, etc. o <form> header - The first section of a form defines how the form will handle the data that is entered. The name attribute defines the name that this form can referred by. In many cases, the name will never need to be referred to either in the receiving file or within the form itself; however, it is good practice to name the form to distinguish it from other forms.

202

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-13

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

203

The method attribute determines how the data will be sent to the receiving file. Using the method="get" option will send the form contents in the URL: URL?name=value&name=value. If the form values contains non-ASCII characters or exceeds 100 characters, the method="post" must be used. The method="post" sends the form contents in the body of the request. The majority of browsers are unable to bookmark post requests. The action attribute defines where to send the data when the submit button is pushed. In this case, $_SERVER['PHP_SELF'], tells the form to send the contents back to itself. By placing the <?php ... ?> in the actual text of the HTML we were able to utilize PHP functions to handle the placement of the actual name of the current web page (world.php) in the action field. o <input> - This HTML tag identifies the start of an input field where the user can enter data. The tag attributes identify how the collected data will be handled and the limitations that the entry will be constrained to. The name attribute defines the name in which the data entered will be connected to. In the retrieval of the data, this name will be used to draw the user entered data out of. This attribute is required with type="button", type="checkbox", type="file", type="hidden", type="image", type="password", type="text", and type="radio" The type attribute defines what type of data should be collected. There are multiple types (or ways) of collecting data in HTML forms but the text type is the most common and will be used if there is no type identified (it is the default type). The text type creates a single-line text input control. o <input type="submit" ... > - This form element is the button that actually tells the web page to send the contents of the collected data to the file identified in the action attribute of the form header. The type="submit" attribute tells the web browser to display a button that can be clicked for submission of the form data. The name is the key that will be used to store the value that is assigned. Yes, the value is collected just like any other user input text and stored to the name attribute for submission to the receiving form. (4) Collecting City Information o if ($_POST['Submit'] == "Lookup City") { - This line of code reads in a form value that was passed from the original submission ('Submit') and ensures that the correct button was selected to perform the action. In this case the "Lookup City" button. o mysql_real_escape_string() - This PHP function escapes special characters in the unescaped_string, taking into account the current character set of the connection so that it is safe to place it in a mysql_query() execution. o $lookup_sql - This is the actual SQL that is used to collect the data for the lookup city. In addition, the this SQL utilizes a Join to collect the Country Code and Country Name from the Country table. o $lookup_results - mysql_query() is used actually execute the prepared SQL ($lookup_sql) o list($city_name ...) = mysql_fetch_row($lookup_results) - This combination of the PHP functions will separate out the data collected in the execution of the SQL script and place them into separate variables (City Name, Country Code, Country Name, District and City Population) (5) Displaying the City Results o if ($city_Name) - This conditional statement verifies that a city name was collected from the execution of the SQL. If the $city_name variable was filled with a value, then the city name was good and the city information can be displayed. However, the if the $city_name variable is empty, then the city name entered was not valid and the else code is executed instead. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-14

Developing Dynamic Web Applications with MySQL and PHP o

Chapter 11- MySQL Data Driven Web Forms

print <<<END ... END; - The print <<< command, as used here, allows for large chunks of HTML code to be entered in the PHP code without having to preface each line with an individual print command. The big thing to remember is that these statements can not have any spaces in front of them so it can look strange with the other code indentation. In addition, the word END is not anything special, it just can not be repeated if another print <<< command is needed (as seen later in the script with print <<<END2 ... END2;) o <form name="world_update" method="post" action="world_update.php"> - Another form element is added to the web page with the action pointing to another web page to handle any actions performed against the form elements. o <table ... > - This HTML code and the subsequent components make up the HTML code to display a table on the web page. Tables are defined with the <table> tag and are divided into rows (with the <tr> tag) with each row being divided into data cells (with the <td> tag). In this case the table is being used to display the contents in a neater fashion and the table itself is not visible due to the border tag being set to zero (0). o <input type="text" name="CityName" value="$city_name"> - This HTML form element (input) is a straight forward text box for collecting form data; however, it can also be used to display data that can be changed by using the value field. In this case the city name is placed into this field which can be changed for update operations (or insert operations for adding a new record to the database). o while ($row = mysql_fetch_array($results, MYSQL_ASSOC)) { - The mysql_fetch_array() function is a step up from the mysql_fetch_row() function by retrieving and storing the entire row of data into an index and associative array. The array can then be parsed, either by the numeric index location or by the column name value, for the specific results that are desired. MYSQL_ASSOC will result in the $row array containing only an associative array. o <select ...> - This HTML code is designed to create a drop-down list. The actual code includes lessons learned in the earlier part of the chapter to populate the drop-down list with all the country names (and there associated codes). The use of the DISTINCT SQL attribute ensures that a country name would only appear once, no matter how many times it actually may appear in the data. The Country Code is the actual data that will be collected by the form, not the Name of the country. o <option ... selected> - In the drop-down lists of HTML form elements, the keyword selected identifies the item in the list that should be selected by default. If this keyword does not appear in the list components the first element in the option lists is selected as the default option. By using the conditional test, we can connect the correct country to the city results. o <input type="submit" ... > - This HTML form element has been seen in each of the sections associated with the world database data. Notice that the input type is the same, but the values are different. The values will be passed on giving us the ability to test what button has been passed and act accordingly with the data. Here there are three actions that can be performed against the data displayed: Update City - The data displayed in the form can be changed to update the record displayed with new information. Delete City - The city that is being displayed can be deleted from the database (basically the record removed) by selecting this button. Insert City - The form elements can be changed (or not if the city needs to duplicated for some reason) to create a brand new city listing in the database (a new record being added based on the values in the form). (6) Close out the HTML Code - The </body> and </html> tags are used to identify the end of the HTML body and the end of the HTML script itself. In addition, the </form> HTML tag is used to ensure the form is closed out properly. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-15

Developing Dynamic Web Applications with MySQL and PHP


204

Chapter 11- MySQL Data Driven Web Forms

11.5 Update Existing Data


Once the data is retrieved and displayed, giving the end user the ability to update the existing data is valuable in many web interfaces. With the original data being loaded into text fields that can be updated, making modifications to the dat is very easy. The Web Page Script The world_update.php script will be built in stages going forward. The first stage is the updating of the existing data utilizing the Update Data button. The following web page script is the complete script to handle the update process. New components in this web page will be explained following the script.
<html><head><title>Modify the World Database</title></head> <body> <?php // Load variables ($dbhost,$dbuser,$dbpass) that will be used in mysql_connect //// This script contains the three variables mentioned and are located in the //// same directory as the PHP scripts utilizing the variables (this is not //// the recommended practice - they should be in a directory not accessible //// through the web browser; however, for training purposes this is //// acceptable) include "connect_info.php"; // Connect to MySQL server //// Prepare the link to the MySQL Server with the information //// gathered from the connect_info.php file. If the connection //// can not be completed, a message will be displayed through the //// web browser that the script "Could not connect to the MySQL //// server" (the or die portion) $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to the MySQL server"); // Identify which MySQL database to use //// Prepare the actual database to utilize in the MySQL server. //// If the connection to the database can not be completed (access issues, //// database not existing, etc.), a message will be displayed through the //// web browser that the script "Could not connect to the world //// database" (the or die portion) mysql_select_db("world",$linkID1) or die ("Could not connect to the world database"); // Update City //// If the Update City button was submitted, perform the following actions if ($_POST['Submit'] == "Update City") { // Collect the additional fields sent across //// To prevent query failures, use the mysql_real_escape_string() //// function anytime user provided data is going to be passed into //// MySQL. This function will escape special characters in the //// unescaped_string, taking into account the current character //// set of the connection so that it is safe to place it in a //// mysql_query(). $CityCode = $_POST['CityCode']; $CityName = mysql_real_escape_string($_POST['CityName']); $CountryCode = $_POST['CountryCode']; $District = mysql_real_escape_string($_POST['CityDistrict']); //// The use of the (int) type casts the input to only allow //// integer values thus if a string is sent across it will //// update the population

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-16

Developing Dynamic Web Applications with MySQL and PHP


$Population = (int) $_POST['CityPop'];

Chapter 11- MySQL Data Driven Web Forms

// Update the data changed in the City table $update_query = "UPDATE City SET Name='$CityName', CountryCode = '$CountryCode', District='$District', Population='$Population' WHERE ID=$CityCode"; $update_result = mysql_query($update_query,$linkID1); // Display results //// If the update was executed without problems, then a response //// stating that the city was updated successfully is displayed; //// otherwise, the end user is notified there was a problem if ($update_result) { print "<p>City successfully updated!</p>"; } else { print "<p>$update_query</p>"; print "<p>There was a problem updating the City!</p>"; } } // Return to Main World Page //// The following link allows the end user to return to the main page //// after the update (or failure to update) takes place print "<p><a href=\"world.php\">Return to Main Page</a></p>"; ?> </body></html>

Explanation of the New Components in the Web Page Script (world_update.php) For the most part the components of this script are similar to the components described in the previous script (world.php); however, there are a few new components that should be explained: $_POST['CityCode'], $_POST['CountryCode']... - Just like the $_POST['Submit'] explained previously, these variables hold the other data that was passed on from the form into this web page. Each variable is stored into another variable making it easier to refer to in the script. (int) - By placing the attribute (int) in front of the $_POST['CityPop'] variable, the variable is type casted to only allow integer values. This is very useful in ensuring that the input collected is the proper data type for the column to hold the data. print "<p><a href=\"world.php\">Return to Main Page</a></p>" - This line provides the means to return to the main web page (world.php) once the world_update.php script has been executed (either successfully or unsuccessfully). The slashes (\) prior to the quotes (") around the world.php name is used because the print is also using quotes.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-17

Developing Dynamic Web Applications with MySQL and PHP


205

Chapter 11- MySQL Data Driven Web Forms

11.6 Delete Data


In this section, the idea of deleting data (or more clearly, rows of data) from MySQL tables, will be presented and demonstrated with an addition to the world_update.php script. The Web Page Script To support the deleting of the city displayed, an additional component has been added to the world_update.php script (highlighted in the script below) to handle the deleting of the city displayed. Now of course in a real world application additional steps should be added to ensure that the end user wishes to delete the record (or better yet, the record should not be deleted at all but just "turned off" or hidden from the main data). The explanation of the additional script is available after the complete script is displayed.
<html><head><title>Modify the World Database</title></head> <body> <?php // Load variables ($dbhost,$dbuser,$dbpass) that will be used in mysql_connect //// This script contains the three variables mentioned and are located in the //// same directory as the PHP scripts utilizing the variables (this is not //// the recommended practice - they should be in a directory not accessible //// through the web browser; however, for training purposes this is //// acceptable) include "connect_info.php"; // Connect to MySQL server //// Prepare the link to the MySQL Server with the information //// gathered from the connect_info.php file. If the connection //// can not be completed, a message will be displayed through the //// web browser that the script "Could not connect to the MySQL //// server" (the or die portion) $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to the MySQL server"); // Identify which MySQL database to use //// Prepare the actual database to utilize in the MySQL server. //// If the connection to the database can not be completed (access issues, //// database not existing, etc.), a message will be displayed through the //// web browser that the script "Could not connect to the world //// database" (the or die portion) mysql_select_db("world",$linkID1) or die ("Could not connect to the world database"); // Update City //// If the Update City button was submitted, perform the following actions if ($_POST['Submit'] == "Update City") { // Collect the additional fields sent across //// To prevent query failures, use the mysql_real_escape_string() //// function anytime user provided data is going to be passed into //// MySQL. This function will escape special characters in the //// unescaped_string, taking into account the current character //// set of the connection so that it is safe to place it in a //// mysql_query(). $CityCode = $_POST['CityCode']; $CityName = mysql_real_escape_string($_POST['CityName']); $CountryCode = $_POST['CountryCode']; $District = mysql_real_escape_string($_POST['CityDistrict']); //// The use of the (int) type casts the input to only allow //// integer values thus if a string is sent across it will ______________________________________________________________________________________________

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-18

Developing Dynamic Web Applications with MySQL and PHP


//// update the population $Population = (int) $_POST['CityPop'];

Chapter 11- MySQL Data Driven Web Forms

// Update the data changed in the City table $update_query = "UPDATE City SET Name='$CityName', CountryCode = '$CountryCode', District='$District', Population='$Population' WHERE ID=$CityCode"; $update_result = mysql_query($update_query,$linkID1); // Display results //// If the update was executed without problems, then a response //// stating that the city was updated successfully is displayed; //// otherwise, the end user is notified there was a problem if ($update_result) { print "<p>City successfully updated!</p>"; } else { print "<p>There was a problem updating the City!</p>"; } } // Delete City //// If the Delete City button was submitted, perform the following actions if ($_POST['Submit'] == "Delete City") { // Collect the City Code //// Due to the fact that deletes take place against the entire row //// we only need to collect the City Code to identify the row to delete $CityCode = $_POST['CityCode']; // Prepare the SQL for deleting the record $delete_query = "DELETE FROM City WHERE ID=$CityCode"; $delete_result = mysql_query($delete_query,$linkID1); // Display results //// If the delete was executed without problems, then a response //// stating that the city was deleted successfully is displayed; //// otherwise, the end user is notified there was a problem if ($delete_result) { print "<p>City successfully deleted!</p>"; } else { print "<p>There was a problem deleting the city requested!</p>"; } } // Return to Main World Page //// The following link allows the end user to return to the main page //// after the update (or failure to update) takes place print "<p><a href=\"world.php\">Return to Main Page</a></p>"; ?> </body></html>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-19

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

Explanation of the Additions in the Web Page Script For the most part the script for deleting the city displayed is very similar to code already presented up to this point; however, there are some components of the script that should be explained further: $CityCode = $_POST['CityCode'] - The only value that needs to read in from the previous form is the city code (even though all the values are available if there was a need to read the other values). This is because the city code is the primary key for the City table and uniquely identifies the record that will be deleted. Once this code is captured it can be used in the SQL to delete the individual record the city name is associated with. Due to the fact that there could be more than one record with the same city name, the city code is imperative to ensure the proper city is being deleted. $delete_query = "DELETE FROM City WHERE ID=$CityCode"; - The SQL used to delete the record is different than updates (or inserts) against the table due to the fact that only the table name is needed (along with a WHERE clause to identify the city to be deleted).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-20

Developing Dynamic Web Applications with MySQL and PHP


206

Chapter 11- MySQL Data Driven Web Forms

11.7 Inserting Data


Last but not least, the ability to add new records to existing tables is an important part of data entry that must be taken into account in most web applications. In the case of our world database interface, the insert is accomplished by changing the fields of an existing record. This supports the idea that multiple cities may have the same country and/or district and the fields can be reused. In many applications this is not the case; however, for training purposes this is an effective way of demonstrating inserts. The Web Page Script To support the insert of a new city, an additional component has been added to the world_update.php script (highlighted in the script below) to handle the insertion of the new city. With the exception of the SQL using the INSERT INTO (instead of an UPDATE command) the code is identical to the Update City code and no additional discussion on the actual code is warranted.
<html><head><title>Modify the World Database</title></head> <body> <?php // Load variables ($dbhost,$dbuser,$dbpass) that will be used in mysql_connect //// This script contains the three variables mentioned and are located in the //// same directory as the PHP scripts utilizing the variables (this is not //// the recommended practice - they should be in a directory not accessible //// through the web browser; however, for training purposes this is //// acceptable) include "connect_info.php"; // Connect to MySQL server //// Prepare the link to the MySQL Server with the information //// gathered from the connect_info.php file. If the connection //// can not be completed, a message will be displayed through the //// web browser that the script "Could not connect to the MySQL //// server" (the or die portion) $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to the MySQL server"); // Identify which MySQL database to use //// Prepare the actual database to utilize in the MySQL server. //// If the connection to the database can not be completed (access issues, //// database not existing, etc.), a message will be displayed through the //// web browser that the script "Could not connect to the world //// database" (the or die portion) mysql_select_db("world",$linkID1) or die ("Could not connect to the world database"); // Update City //// If the Update City button was submitted, perform the following actions if ($_POST['Submit'] == "Update City") { // Collect the additional fields sent across //// To prevent query failures, use the mysql_real_escape_string() //// function anytime user provided data is going to be passed into //// MySQL. This function will escape special characters in the //// unescaped_string, taking into account the current character //// set of the connection so that it is safe to place it in a //// mysql_query(). $CityCode = $_POST['CityCode']; $CityName = mysql_real_escape_string($_POST['CityName']); $CountryCode = $_POST['CountryCode']; $District = mysql_real_escape_string($_POST['CityDistrict']); //// The use of the (int) type casts the input to only allow //// integer values thus if a string is sent across it will //// update the population $Population = (int) $_POST['CityPop'];

______________________________________________________________________________________________ // Update the data changed in the City table ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-21

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

$update_query = "UPDATE City SET Name='$CityName', CountryCode = '$CountryCode', District='$District', Population='$Population' WHERE ID=$CityCode"; $update_result = mysql_query($update_query,$linkID1); // Display results //// If the update was executed without problems, then a response //// stating that the city was updated successfully is displayed; //// otherwise, the end user is notified there was a problem if ($update_result) { print "<p>City successfully updated!</p>"; } else { print "<p>There was a problem updating the City!</p>"; } } // Delete City //// If the Delete City button was submitted, perform the following actions if ($_POST['Submit'] == "Delete City") { // Collect the City Code //// Due to the fact that deletes take place against the entire row //// we only need to collect the City Code to identify the row to delete $CityCode = $_POST['CityCode']; // Prepare the SQL for deleting the record $delete_query = "DELETE FROM City WHERE ID=$CityCode"; $delete_result = mysql_query($delete_query,$linkID1); // Display results //// If the delete was executed without problems, then a response //// stating that the city was deleted successfully is displayed; //// otherwise, the end user is notified there was a problem if ($delete_result) { print "<p>City successfully deleted!</p>"; } else { print "<p>There was a problem deleting the city requested!</p>"; } }

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-22

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

// Insert City //// If the Insert City button was submitted, perform the following actions if ($_POST['Submit'] == "Insert City") { // Collect the additional fields sent across //// To prevent query failures, use the mysql_real_escape_string() //// function anytime user provided data is going to be passed into //// MySQL. This function will escape special characters in the //// unescaped_string, taking into account the current character //// set of the connection so that it is safe to place it in a //// mysql_query(). $CityCode = $_POST['CityCode']; $CityName = mysql_real_escape_string($_POST['CityName']); $CountryCode = $_POST['CountryCode']; $District = mysql_real_escape_string($_POST['CityDistrict']); //// The use of the (int) type casts the input to only allow //// integer values thus if a string is sent across it will //// update the population $Population = (int) $_POST['CityPop']; // Insert the data into the City table $insert_query = "INSERT INTO City SET Name='$CityName', CountryCode = '$CountryCode', District='$District', Population='$Population'"; $insert_result = mysql_query($insert_query,$linkID1); // Display results //// If the insert was executed without problems, then a response //// stating that the city was inserted successfully is displayed; //// otherwise, the end user is notified there was a problem if ($update_result) { print "<p>City successfully inserted!</p>"; } else { print "<p>There was a problem inserting the City!</p>"; } } // Return to Main World Page //// The following link allows the end user to return to the main page //// after the update (or failure to update) takes place print "<p><a href=\"world.php\">Return to Main Page</a></p>"; ?> </body></html>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-23

Developing Dynamic Web Applications with MySQL and PHP


207

Chapter 11- MySQL Data Driven Web Forms

11.8 MySQL Metadata


Databases contain data, but information about the way databases are structured is metadata. The primary way of obtaining metadata is by using the INFORMATION_SCHEMA database to access metadata. MySQL produces metadata for several aspects of database structure. To name a few, metadata can be obtained from such database information as names of databases and tables, information about columns and indexes in tables, or stored routine definitions. Database Information In the world of web based applications. getting information about databases is important to be able to create generic and scalable applications. This section will demonstrate how to obtain information concerning the databases, the tables and the columns located in the MySQL server. Due to the fact that the root user is being used to log into the MySQL server, the resulting queries against the INFORMATION_SCHEMA database will result in a display of all information contained on the server. However, the majority of users will have limited information that they will be able to view from the INFORMATION_SCHEMA database. Only that which a user has access to can be seen. If a user has access to a database, then they will have access to view the information pertaining to that database. The Top Three Even though the INFORMATION_SCHEMA database has multiple tables of data relating to just about every component of a database, the tables that are the most useful for a PHP programmer are the SCHEMATA (Information about the databases), TABLES (Information about the tables in the databases) and COLUMNS (Information about the columns in tables). Understanding and being able to draw information out of these three tables will answer the majority of questions that could be asked about the information in the MySQL server. SCHEMATA Table - The standard SQL INFORMATION_SCHEMA.SCHEMATA table shows the schemas that may be accessed by the current user. The following are the most useful columns to view from this table (the table contains 4 columns in total): SCHEMA_NAME - shows the name of a schema (i.e., a database) which the current user may use. DEFAULT_CHARACTER_SET_NAME - shows the name of the database's default character set. TABLES Table - The standard SQL INFORMATION_SCHEMA.TABLES table shows the base tables and views that are available to the current user. The majority of the columns in this table are MySQL specific columns and are not part of the standard SQL implementation of this table. The following are the most useful columns to view from this table (there are 21 columns in total): TABLE_SCHEMA - shows the name of the schema (i.e., the database) in which an available table resides. TABLE_NAME - shows the name of a table which the current user may access (i.e., on which the current user has been granted a privilege). TABLE_TYPE - shows whether this table is a 'BASE TABLE', a 'TEMPORARY' table, or a 'VIEW'. ENGINE - shows the storage engine used for this table and is not part of the standard SQL definition. ROW_FORMAT - shows this table's row storage format; either 'FIXED', 'DYNAMIC', or 'COMPRESSED' and is not part of the standard SQL definition. TABLE_ROWS - shows the number of rows in this table and is not part of the standard SQL definition. INDEX_LENGTH - shows the length of the index file associated with this table and is not part of the standard SQL definition. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-24

Developing Dynamic Web Applications with MySQL and PHP

Chapter 11- MySQL Data Driven Web Forms

208

AUTO_INCREMENT - shows the next AUTO_INCREMENT value where applicable; otherwise NULL. This column is not part of the standard SQL definition. CREATE_TIME - shows the timestamp of the time this table was created and is not part of the standard SQL definition. UPDATE_TIME - shows the timestamp of the time this table's data file was last updated and is not part of the standard SQL definition. CHECK_TIME - shows the timestamp of the time this table was last checked; NULL if the table has never been checked. This column is not part of the standard SQL definition. TABLE_COLLATION - shows this table's default character set and collation combination and is not part of the standard SQL definition. CREATE_OPTIONS - shows any additional options used in the table's definition; otherwise left blank. This column is not part of the standard SQL definition. TABLE_COMMENT - shows the comment, if any, stored for this table; otherwise left blank. This column is not part of the standard SQL definition. COLUMNS Table - The standard SQL INFORMATION_SCHEMA.COLUMNS table shows the columns that are available to the current user. Similar to the TABLES table, there are number of columns in this table that are MySQL specific columns and are not part of the standard SQL implementation. The following are the most useful columns to view from this table (there are 19 columns in total): TABLE_SCHEMA - shows the name of the schema (i.e., the database) in which the table that contains an available column resides. TABLE_NAME - shows the name of the table to which an available column belongs. COLUMN_NAME - shows the name of a column that may be accessed by the current user (i.e., for which the current user has been granted a privilege). ORDINAL_POSITION - shows the ordinal position of the column in the table to which it belongs. COLUMN_DEFAULT - shows the column's default value. If this column is blank, the column has no defined default value. IS_NULLABLE - shows whether the column may accept NULL values; either 'YES' or 'NO'. DATA_TYPE - shows the column's defined data type (keyword only, not the entire definition). CHARACTER_SET_NAME - shows, for a column with a character string data type, the column's default character set; otherwise NULL. COLLATION_NAME - shows, for a column with a character string data type, the column's default collation; otherwise NULL. COLUMN_TYPE - shows the column's defined data type in full and is not part of the standard SQL definition. COLUMN_KEY - shows whether the column is indexed; either 'PRI' if the column is part of a PRIMARY KEY, 'UNI' if the column is part of a UNIQUE key, 'MUL' if the column is part of an index key that allows duplicates, or blank if the column is not indexed. EXTRA - shows any additional column definition information, e.g., whether the column was defined with the AUTO_INCREMENT attribute; otherwise left blank. This is not part of the standard SQL definition. PRIVILEGES - shows the privileges available to the current user on the column and is not part of the standard SQL definition. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-25

Developing Dynamic Web Applications with MySQL and PHP


209

Chapter 11- MySQL Data Driven Web Forms

Viewing MySQL Metadata The INFORMATION_SCHEMA is a virtual database that is automatically created and populated by MySQL, there is no need to create an INFORMATION_SCHEMA database. There also is no associated file structure due to the fact that the contents of the data are actual views, rather than logical data being stored in any one location. Only SELECT statements are allowed against the tables in the INFORMATION_SCHEMA database. The following SELECT example demonstrates some of the metadata that can be viewed:
<?php // Load variables used in mysql_connect and connect to server include "connect_info.php"; $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); // Execute Query to Collect Metadata $query = "SELECT TABLE_NAME, ENGINE, TABLE_ROWS, UPDATE_TIME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='world'"; $results = mysql_query($query, $linkID1); // Build HTML Table of Results print "<table width='700' border='1'>\n"; print "<tr>\n<th>TABLE_NAME</th>\n<th>ENGINE</th>\n"; print "<th>TABLE_ROWS</th>\n<th>UPDATE_TIME</th>\n</tr>\n"; while ($row = mysql_fetch_array($results, MYSQL_BOTH)) { print "<tr>\n<th>".$row[0]."</th>\n<th>".$row[1]."</th>\n"; print "<th>".$row[2]."</th>\n<th>".$row[3]."</th>\n</tr>\n "; } print "</table>"; // Close the connection to the MySQL server mysql_close($linkID1); ?>

An output similar to the one will be displayed: TABLE_NAME City Country CountryLanguage ENGINE MyISAM MyISAM MyISAM TABLE_ROWS 4043 238 984 UPDATE_TIME 2007-04-18 12:25:50 2007-04-16 23:42:21 2007-04-17 01:29:01

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-26

Developing Dynamic Web Applications with MySQL and PHP


210

Chapter 11- MySQL Data Driven Web Forms

11.8.1

PHP Functions for Retrieving Metadata The most complete way to retrieve metadata is by using a SELECT statement against the INFORMATION_SCHEMA database in the MySQL server. However, there are times that is overkill for the data needing to be collected for a PHP application. With that said, PHP offers multiple functions that provide methods for retrieving a small amount of metadata about the data in the MySQL server. Database Metadata The mysql_list_dbs() function retrieves the name of all the databases found on the server that are accessible by the user requesting the information:
<?php // Load variables used in mysql_connect and connect to server include "connect_info.php"; $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); // Retrieve the names of the databases accessible by the user $schema_results = mysql_list_dbs($linkID1); print "The databases available to the root user are:<br>\n"; while (list($schema) = mysql_fetch_row($schema_results)) { print "$schema <br>\n"; } // mysql_db_name() also displays the databases print "The databases available to the root user are:<br>\n"; for ($count=0; $count < mysql_num_rows($schema_results); $count++) { print mysql_db_name($schema_results,$count)."<br>\n"; } ?>

211

Table Metadata The mysql_list_tables()function retrieves the name of all the tables found in the database identified that are accessible by the user requesting the information:
<?php // Load variables used in mysql_connect and connect to server include "connect_info.php"; $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); // List world database tables accessible by the user $table_results = mysql_list_tables('world',$linkID1); print "The world database tables available to the root user are:<br>\n"; while (list($table) = mysql_fetch_row($table_results)) { print "$table <br>\n"; } // mysql_tablename() also displays the world database tables retrieved print "The world database tables available to the root user are:<br>\n"; for ($count=0; $count < mysql_num_rows($table_results); $count++) { print mysql_tablename($table_results,$count)."<br>\n"; } ?>

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-27

Developing Dynamic Web Applications with MySQL and PHP


212

Chapter 11- MySQL Data Driven Web Forms

Column Metadata In comparison to the metadata that can be collected about databases and tables, the column metadata is much more robust and extensive due to the multiple attributes that can be assigned to columns. The following functions are used to retrieve column metadata: mysql_fetch_field() - This function retrieves an object that contains 12 different pieces of information concerning each column. This information collected ranges from the name of the field to the data type of the field. The following example show how this could be implemented:
<?php // Load variables used in mysql_connect and connect to server include "connect_info.php"; $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); mysql_select_db("world", $linkID1) or die("Could not select the world database!"); // Display metadata about columns $query = "SELECT * FROM City LIMIT 1"; $query_result = mysql_query($query,$linkID1); for ($count=0; $count < mysql_num_fields($query_result); $count++) { $column = mysql_fetch_field($query_result,$count); print "<p>$column->name ($column->type)</p>"; } ?>

mysql_fetch_field() Object Properties The mysql_fetch_field() function returns twelve object properties: name, table, max_length, not_null*, primary_key*, unique_key*, multiple_key*, numeric*, blob*, type, unsigned* and zerofill*. The options identified with an asterisk display either a 1, for 'True' or 0, for 'False'.
213

mysql_field_flags() - This function is used to obtain all the options assigned to a column in a string format. The following example show how this could be implemented:
<?php // Load variables used in mysql_connect and connect to server include "connect_info.php"; $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); mysql_select_db("world", $linkID1) or die("Could not select the world database!"); // Displays options about the world City ID columns $query = "SELECT ID FROM City LIMIT 1"; $query_result = mysql_query($query,$linkID1); print "The options assigned to the world.City.ID column are: "; print mysql_field_flags($query_result,0)."<br>\n"; ?>

mysql_num_fields() The mysql_num_fields(), which is used in the script above, returns an integer which is equivalent to the number of columns that are located in the query result set. For example, SELECT * FROM City, would return an integer of 5 to account for the 5 columns that are present in the City table. Instructor Notes: mysql_list_fields() is another way of obtaining the name of the columns; however, using SELECT against the INFORMATION_SCHEMA.COLUMNS tables is preferable. There are other specific functions for obtaining specific portions of the column metadata; mysql_field_len(), mysql_field_name(), mysql_field_type() and mysql_field_table(). However, using the mysql_fetch_field() is ______________________________________________________________________________________________ the preferred method for obtaining column metadata. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-28

Developing Dynamic Web Applications with MySQL and PHP


214

Chapter 11- MySQL Data Driven Web Forms

11.9 MySQL Error Information


Even though developers (most at least) strive for an application free of bugs, no application (except minor projects) can be expected to be completely bug-free. For that purpose, a good practice for programmers is to build in code that will trap and display errors in a way that is both meaningful and useful to assist in the correction of the error. PHP offers two functions that can display error messages from MySQL: mysql_error() - This function displays the error message (if there was one) from the last MySQL function. The language that the message will be displayed in is based on the target language that is setup in the MySQL server. However, even if a fluent speaker of the message language were to read the majority of error messages returned, they would most likely still have a difficult time understanding what was said. Needless to say, error messages from MySQL are not very verbose or informative.
<?php // Load variables used in mysql_connect and connect to server include "connect_info.php"; $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); // Insert a record in the INFORMATION_SCHEMA database $query = "INSERT INTO INFORMATION_SCHEMA.TABLE SET TABLE_NAME = 'dog'"; $query_result = mysql_query($query,$linkID1); if ($query_result) { print "<p>INSERT successful</p>"; } else { print "<p>".mysql_error($linkID1)."</p>"; } ?>

The response which is displayed is not exactly accurate; "Access denied for user 'root'@'localhost' to database 'INFORMATION_SCHEMA'". The real error is that the INFORMATION_SCHEMA database is a made up of system view tables that can only accept SELECT statements against the data contained. The rights a user has does not control if an INSERT can be made against the INFORMATION_SCHEMA database. This is one of many examples of error messages that are not as accurate (or descriptive) to really be helpful. Other solutions should be considered in providing more accurate feedback when errors occur, such as: Labeling code snippets and then using that naming convention in the error message to pinpoint exactly where the error took place in the code. o Label the error message with the line of code on which it occurred (or at least where the error message was captured). o Set up a function that will e-mail the results of errors to the administrator of the code or store them in a file. o Producing a generic error message that tells the end user there was a problem and providing contact information for them to contact the administrator of the system. mysql_errno() - This function is identical to the mysql_error() function with the exception that only the associated error number is displayed without any explanatory text. The resulting number produced is MySQL-specific and is not portable to other database systems. Developers can use these numbers to create customer error messages. The complete list of MySQL numeric error values can be found at http://dev.mysql.com/doc/refman/5.1/en/error-messages-server.html. o

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-29

Developing Dynamic Web Applications with MySQL and PHP


215

Chapter 11- MySQL Data Driven Web Forms

Lab 11-A
In this further practice, you will create a web page that displays the images in the photo_album database and provide a form for update picture information and adding comments. 1. 2. Using the script view_images.php, view the image associated with id_image 8 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=8 Using the view_images.php script again, add to the PHP script the ability to capture the image entered (id=#) and verify if it is a valid and active image id. Once completed attempt to enter an image identifier that is not in the database to see how the script will handle it. In addition, attempt to enter in an image_id that is not numeric. Add to the view_images.php script the ability to move forward or backwards through the pictures without having to type in the next or previous imageID. Add to the view_images.php script the ability to see the image name and the data associated with the picture. The data associated with the image must be able to be updated by the end user (image name and date of the image). Build the form to make this happen and the script to update the images table with the updated data. Test your script by making changes to multiple dates and image names. Add to the view_images.php the ability to delete the images (make them inactive). It is best not to truly delete the images, by making the active_image='False', the end user will no longer be able to view the image through the web interface; however, the image will remain for undoing purposes. In your own applications you would have to consider the implications of such a solution (security vs. undoing capabilities).

3. 4.

5.

Bonus: Add to the view_images.php script the ability to review and add comments to the picture displayed. At this point, hard code a login_name (such as 'Hank') into the comments table to track who entered the comment.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-30

Developing Dynamic Web Applications with MySQL and PHP


216

Chapter 11- MySQL Data Driven Web Forms

11.10

Chapter Summary
In this chapter, you have learned to: Establish and Close a Connection to the MySQL Server from PHP Retrieve Data from the MySQL Server Insert and Update Data in a MySQL Database Using a PHP Web Form The most basic request necessary when working with PHP and MySQL is the ability to connect to the MySQL server itself. The process of retrieving data once a connection has been made to the MySQL server is similar to the process of interacting with the data through the mysql client. When data is put into a MySQL table it is referred to as inserting data. Inserting data is a pretty straightforward activity in MySQL; however, it is important to remember what kind of data is specified in the columns of the table. Deleting data, in this sense, involved removing rows of data from the associated tables. Databases contain data, but information about the way databases are structured is metadata. The primary way of obtaining metadata is by using the INFORMATION_SCHEMA database to access metadata. MySQL produces metadata for several aspects of database structure. To name a few, metadata can be obtained from such database information as names of databases and tables, information about columns and indexes in tables, or stored routine definitions. PHP also offers multiple functions that provide methods for retrieving a small metadata about the data in the MySQL server. Even though developers (most at least) strive for an application free of bus, no application (except minor projects) can be expected to be completely bug-free. For that purpose, a good practice for programmers is to build in code that will trap and display errors in a way that is both meaningful and useful to assist in the correction of the error. PHP offers two functions that can display error messages from MySQL: mysql_error and mysql_errno.

Delete MySQL database data with PHP Retrieve MySQL Metadata

Retrieve Error Information from MySQL using PHP

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 11-31

Developing Dynamic Web Applications with MySQL and PHP

217

CHAPTER 12 SESSION HANDLING


218

Developing Dynamic Web Applications with MySQL and PHP


219

Chapter 12- Session Handling

12 SESSION HANDLING
12.1 Learning Objectives
This chapter provides the knowledge necessary to utilize session handling within PHP to track user-specific behavior and preferences. At the completion of this chapter, you will be able to: Describe Session Handling Utilize Session Handling Tasks

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-1

Developing Dynamic Web Applications with MySQL and PHP


220

Chapter 12- Session Handling

12.2 What is Session Handling


Hyper Text Transfer Protocol (HTTP) is the method on which information is transferred from a server to a client on the world wide web. This protocol is static in nature, that is every request is a new request and no persistence (or memory of a previous transfer) remains within the protocol itself. This has its advantages in the form of safety, the requests by either the client or the server has no long term affects on the other. This provides a level of security that could be related to a friendly acquaintance with each other and no long term affects are felt by the interaction. However, for the application developer (and dare it be said, also for the end user), there are times when a more intimate relationship is needed to add value to the experience. This is where session handling comes in. Basically, when a user interacts with a web page, the application attempts to get to know the person and retain a memory of their visit. Maintaining State In PHP, this method of retaining a memory of a specific user is known as maintaining a state. This is accomplished through a series of session management activities that are used to help web applications maintain their state across several HTTP requests when needed. These session management activities within PHP sessions are simplistic, yet powerful enough to meet the needs of developers worldwide. PHP hides all the complexities inherent to where and how to store session data by providing developers with transparent tools for the managing of information that must persist or remain over a period of time and/or interactions. Telling PHP to Remember a Visitor Before a user (or more importantly the activities of a user) can be remembered, PHP must be told to remember the person. It is similar to walking on a busy street in a major metropolitan city; a person may walk past thousands of individuals in the course of getting to and fro; however, the chances of that person remembering every face they have passed is nearly impossible to consider. It is like that in session handling. It is not necessary to remember every visitor (or more importantly their activities) that encounters an application (even though it is theoretically possible, but not feasible). It may be easy to count that they visited the site, but to get up close and personal with every visitor is not truly the goal of session handling. Being picky and choosy on who is remembered and who is not, is not only important for the application, but also could be a sanity check for developers who feel that every little piece of knowledge about every visitor needs to be stored. The Process of Remembering a Visitor There are many tricks for the mind to help in remembering a person; these tricks may or may not work. However, for PHP this process, when implemented correctly, is a sure winner in remembering the visitor when necessary. Here is the overview of how this rememberance is possible: Session ID - A cryptographic session identifier is created that is saved on the clients machine in a cookie. There is another process that is completed through the propagation by the URL as part of the query string (also known as URL propagation) that is limited in scope and will not be expanded upon in this training. Data Stored - Session data is stored on the server in text files (the default directory for storing session data is /tmp), but this behavior can be easily changed to save session data in shared memory or even database tables (MySQL of course). Two Become One - The corresponding session ID is associated with saved session data, in this way providing a method for tying a particular user to this data. Breaking Completely Free It is important to note, that at anytime the end user or the developer (via the application) can break off the relationship with each other and complete a total purge of their rememberance of each other.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-2

Developing Dynamic Web Applications with MySQL and PHP


221

Chapter 12- Session Handling

12.3 Session Handling Tasks


As stated earlier, the process of PHP maintaining information from one session to the next for a visitor is pretty straight forward without lacking in capability. This maintaining of information (getting to know the end user) is accomplished through session handling tasks. Starting a Session It is necessary to tell PHP when to open up its eyes and prepare for the possibility of having to get to know an end user. This process is accomplished through the function session_start(). This function initializes the session data or continues the current session that is being passed by a request, such as a GET, POST or a cookie.
<?php session_start(); ?>

Setting up the Session "Key" After starting the session process, it is important to identify the "key" by which the user will be remembered. This key is stored on the end users machine and is called when interacting with the end user machine with the same function; session_id().
<?php session_start(); // Calling the session ID of the current visitor echo 'Old session ID :'.session_id(); // Giving the visitor a new session ID session_id(md5(rand(1,5000))); echo 'New session ID: '.session_id(); ?> 222

Replacing the Session "Key" In the example above, the old session ID is removed and a new session ID is made using the rand function. This works fine; however, there is a simpler approach to the idea of replacing (or regenerating) a new session ID. This is accomplished with the session_regenerate_id() function that will replace the current session id with a new one, while keeping the current session information.
<?php session_start(); // Calling the session ID of the current visitor echo 'Old session ID :'.session_id(); // Giving the visitor a new session ID session_regenerate_id(); echo 'New session ID: '.session_id(); ?>

Remembering the Session When working with sessions, it is important to understand that keeping track of the session is utmost for this recall to take place. If a session ID is lost, then the information that is associated with it is useless because the key is lost. Without the key, the session information is wasted space. The way PHP prevents this important "key" from getting lost, is by giving the developers a tool that is easy to pass on. This tool is the global constant SID and one way it can be applied is in the following manner:
<?php session_start(); ?> <a href="nextscript.php?<?php echo SID?>">Click here</a>

Storing the Session Data Once the session has been initialized, the data that must remain persistently can be stored in the superglobal $_SESSION array. The following are examples of storing persistence data to this superglobal array:
<?php $_SESSION['fname'] = 'George'; ______________________________________________________________________________________________

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-3

Developing Dynamic Web Applications with MySQL and PHP


$_SESSION['lname'] = 'Burnes'; ?> 223

Chapter 12- Session Handling

Retrieving the Session Data Once the session data has been stored, retrieving (or recalling) this information is also very easy to setup. The following demonstrates how this is accomplished:
<?php print "Dear ".$_SESSION['fname']." ".$_SESSION['lname'].","; ?>

Terminating a Session There are times when it is necessary (and good practice) to terminate a session and destroy all data associated with the current session. The function session_destroy is responsible for handling the described actions; however, this function is limited in its ability by not unsetting (or clearing) the global variables tied to the session or the respective cookies. This requires a more detailed approach:
<?php session_start(); // Unset all session variables $_SESSION = array(); // Unset all cookie variables if(isset($_COOKIE[session_name()])){ setcookie(session_name(),'', time()-48000,'/'); } ?>

session_unset() Another way to remove all the session variables stored in the current session, is by issuing the session_unset() function. This effectively erases all session variables and returns the session to the state in which it was initially found. However, and the reason it is not a large discussion in this chapter, is its limitation in actually removing the session from the storage medium. The example with the session_destroy() function is the only true way of accomplishing the complete purging of the session data.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-4

Developing Dynamic Web Applications with MySQL and PHP


224

Chapter 12- Session Handling

12.3.1

Encoding/Decoding Session Data PHP stores all the session data associated with a session ID in a single string and handles the decoding of this string automatically. However, there are times when it may be necessary or beneficial to handle this process manually. The first thing to understand is how the string is put together. In the following example, three session variables are stored (last name, first name and phone number):
lname|s:6:"Gordon";fname|s:6:"Jethro";phone|s:10:"7197235674";

The session variables are separated by a semicolon (;) and then can be broken down into their individual components: name of the variable, length of the string that is contained and the value itself. For the session variable lname, the length of the string is 6 characters long and the value that is stored in the string is "Gordon". Encoding the Session Variables The function session_encode allows for all the session variables available to the user to be encoded into a single string (as shown above). This can be helpful in the event that a developer may wish to store this string into a database and later retrieve it.
<?php session_start(); // Load the session variables with values $_SESSION['lname'] = 'Gordon'; $_SESSION['fname'] = 'Jethro'; $_SESSION['phone'] = '7197235674'; // Combine all the session variables together // into a single string $session_variables = session_encode(); ?> 225

Decoding the Session Variables The manual decoding process is as simple as the encoding process when using the session_decode() function. This function takes one input parameter; the variable that is storing the encoded session variable string. When decoded, each value will be placed into its corresponding session variable.
<?php session_start(); // Obtain the Session ID from the local system $SID = session_id(); // Read in the encoded session string from MySQL $linkID1 = mysql_connect("localhost", "root", "training"); $session_query = "SELECT sessionVars FROM world.user WHERE sid = $SID"; $session_result = mysql_query($session_query, $linkID1); list($session_variables) = mysql_fetch_row($session_result); session_decode($session_variables); print "Name: ".$_SESSION['lname'].", ".$_SESSION['fname']; print " Phone: ".$_SESSION['phone']."<br>\n"; mysql_close($linkID1); ?>

______________________________________________________________________________________________ Instructor Notes: This is one way to "process" session handlers using a database; however, there are better methods ______________________________________________________________________________________________ that are more standard in practice. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-5

Developing Dynamic Web Applications with MySQL and PHP

Chapter 12- Session Handling

12.4 PHP Session Handling with MySQL


There are many ways that session handling can be used to provide a dynamic and non-static experience for the end user. Sessions can be used for providing a more personal experience for the end users by keeping track of them as they roam through a site providing content that is more tailored to their likes and dislikes (by monitoring the choices they make in what they choose to view). Sessions can also be used to make sure that only those who have a valid username and password can gain access to a specific part of a site, or in the case of any online store; keep track of what is in the shopping chart at any given time. These are just some examples of how session handling have added value to the web experience. MySQL is a perfect companion to session handling by being able to help with the process of storing and retrieving the data that gives extra life to the session handling capabilities. With the ability to connect multiple types of information (data stored in the database selected and used in such a way to add value) to the user at the database level can provide a much more dynamic and personal experience for the end user.
226

12.4.1

MySQL Handling Logins Example It is quite common to use a database to handle the login storage and retrieval of the associated data needed for ensuring a secure login and personal experience. However, it is also handy to provide a means to allow returning users to skip the login when they move from page to page in a site or return to the site within a specified time period. Storing MySQL Session Data Before using MySQL to store session data, there must be a place to put the data. This involves creating a table that contains the information necessary to manage the login of a user into a site. The following table will be used to manage the storage of the login information that will be used by PHP to manage logins: CREATE TABLE `customers` ( `customerEmail` VARCHAR(40) NOT NULL, `lname` VARCHAR(25) NOT NULL, `fname` VARCHAR(25) NOT NULL, `title` ENUM('Mr.', 'Mrs.', 'Miss', 'Ms.', 'Dr.'); `passwd` VARCHAR(30), PRIMARY KEY (`customerEmail`) ); The idea of using the customerEmail as the login in identifier has become standard practice in many web applications these days. As far as an email being a primary identifier for the customer, it is perfect; It is unique (no two people could have the exact same e-mail account), it is specific to the user and it is an alternate means to contact the user. In this table, there could be additional columns used to support other areas of the application; however, for the purpose of this training, this table will suffice.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-6

Developing Dynamic Web Applications with MySQL and PHP


227

Chapter 12- Session Handling

Creating a Login Form The login form is a pretty straightforward component of most applications today and this application will be no different. The login form will be a standard HTML file that is called login.html.
<p><form name="login" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>"> E-mail assigned to the account: <input type="input" name="email" size="40"><br>\n Password: <input type="password" name="pswd"><br>\n <input type="submit" value="Login"> </form></p>

228

Managing the Login Process Now that the table that contains the data is created (which would also need to be propagated with data) and the login form is available, it is time to create the actual script that will manage the login process. The following script is an example of how this could be accomplished:

(1) HTML Head Element


<html><head><title>Our Secure Web Page</title></head> <body>

(2) Standard Opening Sequence for PHP Scripts using Session Handling and MySQL
<?php session_start(); // Load variables that will be used in mysql_connect include "connect_info.php"; // Connect to the MySQL Server and use the // world database (which houses the customers table) $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to $dbhost database"); mysql_select_db("world",$linkID1) or die ("Could not connect to world database");

(3) Session Information has already been loaded, which shows a prior successful login
// Is there a session initiated if (isset($_SESSION['email'])) { $sessionEmail = $_SESSION['email']; $welcome_SQL = "SELECT title, lname FROM customers WHERE customerEmail = $sessionEmail"; $welcome_results = mysql_query($welcome_SQL, $linkID1); list($title,$lname) = mysql_fetch_row($welcome_results); print "<p>Welcome back, $title $lname</p>";

(4) Session Information has not been loaded, check to see if login form has been submitted
} else { // Has the login form been filled in and submitted if (isset($_POST['email'])) { $postEmail = $_POST['email']; $postPass = $_POST['pswd']; $login_query = "SELECT title, lname FROM customers WHERE customerEmail = '$postEmail' AND passwd = SHA('$postPass'); $login_results = mysql_query($login_query, $linkID1);

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-7

Developing Dynamic Web Applications with MySQL and PHP

Chapter 12- Session Handling

(5) Test to See if the Login Name and Password Match the Data Stored in MySQL
If (mysql_numrows($login_results)==1) { //SELECT returned successfully list($title,$lname) = mysql_fetch_row($login_results); $_SESSION['email'] = $postEmail; print "<p>Thank you for logging in, $title $lname</p>"; } else { // SELECT statement not returned successfully print "<p>Email or Password Incorrect, please try again</p>"; include "login.html"; }

(6) If There is No Session Handler for the Email and The Login Form has not been Submitted
} else { // Load the Login Form include "login.html"; } } ?>

(7) HTML Footer Information


</body></html>

Explanation of the Login Script (1) HTML Head Element - This section can be considered the meta-information for the actual HTML document as a whole. (2) Standard Opening Sequence for PHP Scripts using Session Handling and MySQL - This section is the PHP script that prepares the connection to the MySQL server for any future PHP sections that will require the use of the database. In addition, the session handling process is opened with the session_start() function. (3) Session Information has already been loaded, which shows a prior successful login - This section tests to see if the global Session variable is available for the email. The customer email is the PRIMARY KEY for our table and is used to verify that the login is successful. If the customer has previously logged in, this variable would have been set. o $_SESSION['email'] - This references the global session variable that would be available if the customer logged in previously. o $welcome_SQL - This SQL statement will retrieve the customers title and last name so that a personal message can be created welcoming the customer back to the web site. (4) Session Information has not been loaded, check to see if login form has been submitted - If there is no global session variable named email (the one that is being used to determine if a session has been created for this user), then check to see if an email and password has been submitted through the login form. If there has been a submission through the form (by checking to see if there has been a posting with the name of email), check the values submitted against the data in the database. o SHA($postPass) - The passwords have been stored in the MySQL database using the SHA-1 160-bit checksum as described in RFC 3174 (Secure Hash Algorithm). The SHA value is a binary string of 40 hex digits. The value of the password entered in will be converted to the equivalent SHA value to be tested against the values stored in the database. (5) Test to See if the Login Name and Password Match the Data Stored in MySQL - If the login name and password are good, the result will be a single row of data returned. If that is the case, then fill in the global session variable named email with the email of the customer. o mysql_numrows($login_results) == 1 - This works to ensure that one row has been returned letting the script know that the login e-mail and password was accurate and that the script should proceed. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

229

Page 12-8

Developing Dynamic Web Applications with MySQL and PHP o

Chapter 12- Session Handling

$_SESSION['email'] = $postEmail - This is the actual step that assigns the customer email to the global session variable called email. This step ensures the other steps work correctly. o include "login.html" - This function will load the login.html file that was previously created which will load the login form HTML script into the current page. (6) If There is No Session Handler for the Email and The Login Form has not been Submitted In the event that the global session variable for the email has not been set and the login form has not been loaded and submitted, then display just the login form. This is the action that will take place the very first time the page is loaded. (7) HTML Footer Information - The </body> and </html> tags are used to identify the end of the HTML body and the end of the HTML script itself. Disclaimer It is important to understand that the scripts presented in this chapter by no means contain all the options that should be included, in actuality they are quite limited and not very useful in the real world as is (ex. no checks on the data entered). However, the ability to see how the scripts were developed and broken down will add value to future scripts that will be created not only in this class but in the real world beyond the classroom.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-9

Developing Dynamic Web Applications with MySQL and PHP


230

Chapter 12- Session Handling

12.4.2

Session Handling Configuration Options By default, the time that a session handler remains on the client side is set to 0, meaning that the session identifier will be "lost" when the web browser that initiated the original session handler page is shut down. This can be changed in the php.ini file by the configuration setting of session.cookie_lifetime. This is one of many configuration options that must be considered when setting up session handling for the specific instance of PHP: session.save_handler - This configuration options defines the method in which the storage of the session will be handled. There are three options to choose from: o files - This method is the default and the most common. When this setting is set, the session handler uses files on the operating system to track the session information. o mm - This method stores the session information in shared RAM. Of the three, this option is the fastest but also the most volatile. o user - This method refers to using user-defined functions to handle the session information. This would be the option to choose when using MySQL, or any other medium, to handle the storage and management of the session information. session.save_path - The value assigned to this option (which is /tmp by default) determines the location where the files associated with the session ID will be stored. Two things to keep in mind when setting this path. First, can the system write to this directory and second, is this location a safe directory. Using the document root of the web server is not acceptable and in fact even the /tmp directory is unacceptable because of its ability to be viewed by other users on the server. session.use_cookies - If this value is set to 1, PHP will only use cookies when storing the session ID. This means that the session ID will not be removed from the server when the web browser is closed (thus releasing the session ID). The session ID will remain on the system until other settings (or scripting) tell PHP to terminate the session ID. If this value is set to 0, then URL rewriting will be used. URL rewriting is a transparent method on which the session ID will be tracked from web page to web page (on the same site) by adding its value to the URL for the next web page to read. This of course works only for individual site visits and no persistence beyond the visit will remain (Basically the host will be friendly while the user is visiting, but will forget about the user and their preferences when they leave). session.use_only_cookies - If this value is set to 1, only cookies can be used for storing session ID's (No URL Rewriting will be allowed thus preventing any possible attacks of stealing a session ID in the URL). If this value is set to 0, both URL Rewriting and cookies can be utilized. session.name - This configuration option determines the default name of the cookie that will be used. The default name assigned to this configuration option is PHPSESSID; however, this can be named to better associate the session handling name of the application that it will be supporting. In addition, the session name can also be set for the specific application component setting it with the session_name() function. session.cookie_lifetime - The value that is entered here determines how long a cookie is valid in seconds. If it was necessary to have a cookie last 7 days, then the number would need to be set to 604800 (60*60*24*7). session.cookie_path - The value that is entered here determines the path (and all subsequent directories) on which cookies are valid for the operating system running PHP. An entry such as / on www.mysql.com will include the root directory of the web server and all subsequent directories. However, an entry such as /training on www.mysql.com will only allow cookies in the training path (www.mysql.com/training and all subsequent directories) session.cookie_domain - This configuration option sets the domain for which the cookie is valid and ensures that other domains are not able to read the domains cookies. This can be a complete domain; such as www.mysql.com or set up to support subdomains also; such as .mysql.com. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-10

Developing Dynamic Web Applications with MySQL and PHP

Chapter 12- Session Handling

session.gc_probability - When a session is created, a flat-file is created on the server and will accumulate over time. PHP has a built in "load balancing" feature (called garbage collection) that will take care of these files and delete old files from time to time. This "load balancing" feature is managed by three configuration options that ensure old session files are not deleted on each and every session request, but with a certain probability. This configuration option, session.gc_probability, is the numerator component of the probability ratio used to calculate the frequency in which the garbage collection routine is invoked (1/x). session.gc_divisor - This configuration option is the denominator component of the probability ratio used to calculate the frequency in which the garbage collection routine is invoked (x/100). session.gc_maxlifetime - This configuration option sets the maximum age (in seconds) of data before it is considered garbage and is irretrievably destroyed. The default is 1440 seconds (or 24 minutes). Instructor Notes: session.auto_start is another configuration option that eliminates the need to use the session_start() function to start a session. If this setting is set to 1, the session is automatically started and no need to ever issue the session_start() function is necessary. If this setting is set to 0, the developer must use session_start() to explicitly start the session (which should be the preferred method for consistency and being easier for the code to be understood by an outsider of the application). Other configuration options such as those dealing with URL referrer checks (session.referer_check),caching session pages (session.cache_limiter, session.cache_expire) and hashing session ID's (session.hash_function, session.hash_bits_per_character) have not been discussed due to the scope of the training (these require deep discussions and not directly relate to the content of the material). Additional notes on garbage collection: PHP has a session cookie with a lifetime until the browser is closed, but the garbage collector might delete the session file much earlier. In this case, and if there is a session request after the session file has been deleted, a new session is created and the old session information is lost. This can

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-11

Developing Dynamic Web Applications with MySQL and PHP


231

Chapter 12- Session Handling

Lab 12-A
In this further practice, you will use the view_images.php and add the ability for the customer to return to the last picture they were viewing. There is no need at this point to add a login; however, in a live application, a login system should be setup. 1. 2. In the mysql client, recreate (or create) the photo_album database and source in the /tmp/photo_album.sql file to propogate the database with clean data. Create the sessions table in the photo_album database: Column Name session_ID image_ID date_created 3. Data Type CHAR(60) INT TIMESTAMP Extra NOT NULL NOT NULL

Using the script view_images.php, ensure that the correct script is being used by viewing the image associated with id_image 15 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=15. Does the form contain links to move to the previous image and the next image? Does the form contain the ability to delete the image? Does the form have the ability to update the date? Does the form contain comments associated with the image and provide the ability to add comments? If so, then the correct version of the view_images.php file is being used. Add the ability to keep track of the last image that was viewed using session handlers in the view_images.php file. Use the sessions table in the photo_album database to store the session ID and the associated data (image_ID and the date the session ID was created). Create the ability to store and retrieve the last image ID that was viewed using sessions. Open your web browser and open http://localhost/view_images.php. Go to image ID 9. Using the same web browser, open up the MySQL web page, http://www.mysql.com. Using the same web browser again, type in http://localhost/view_images.php. Does the image associated with ID 9 show up? If not, review the view_images.php script and determine where the problem is. Open the mysql client and perform a SELECT against the photo_album.sessions table. Is there session information in this table?

4.

5. 6. 7.

8.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-12

Developing Dynamic Web Applications with MySQL and PHP


232

Chapter 12- Session Handling

12.5 Chapter Summary


In this chapter, you have learned to: Describe Session Handling In PHP, this method of retaining a memory of a specific user is known as maintaining a state. This is accomplished through a series of session management activities that are used to help web applications maintain their state across several HTTP requests when needed. These session management activities within PHP sessions are simplistic, yet powerful enough to meet the needs of developers worldwide. PHP hides all the complexities inherent to where and how to store session data by providing developers with transparent tools for the managing of information that must persist or remain over a period of time and/or interactions. The maintaining of information (getting to know the end user) is accomplished through session handling tasks: Starting a session, setting up the session "key", replacing the session "key", remembering the session, storing session data, retrieving session data and terminating a session.

Utilize Session Handling Tasks

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 12-13

Developing Dynamic Web Applications with MySQL and PHP

233

CHAPTER 13 OBJECT ORIENTED PROGRAMMING


234

Developing Dynamic Web Applications with MySQL and PHP


235

Chapter 13- Object Oriented Programming

13 OBJECT ORIENTED PROGRAMMING


13.1 Learning Objectives
This chapter provides the knowledge necessary to integrate PHP's object oriented programming (OOP) functionality into the design of web applications. At the completion of this chapter, you will be able to: Describe the Benefits of Object Oriented Programming Explain the Class Data Type Explain the purpose of Methods within the Class Data Type Utilize Exception Handling in PHP

Instructor Notes: This chapter does not have any inline labs. The main idea of this section is to introduce object ______________________________________________________________________________________________ oriented programming and then move onto the exception-handling material. The further practice will allow them to ______________________________________________________________________________________________ use the object oriented knowledge to create an exception handling script to handle a problem that could arise. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-1

Developing Dynamic Web Applications with MySQL and PHP


236

Chapter 13- Object Oriented Programming

13.2 Benefits of OOP


Object-oriented programming (OOP) is a programming model that uses "objects" in the design of the applications. Standard programming is seen as a list of instructions read more from top to bottom, while OO programming is better identified as a collection of "objects" working together to create the application. OO programming is modular in nature which is designed to support greater flexibility while also being easier to maintain. Objects, when designed properly, become "black boxes", where the only concern is inputting data and receiving output data. The innards, although important to the programmer when developing the object, become less important as the object is put into production and reused. Benefits Many of the benefits of OO programming have already been presented in the introduction, but for the purposes in being straight-forward, the following list is more complete: Encapsulation - The object is an enclosed and complete program that for the most part can stand on its own. All the code required to take an input and provide an appropriate output based on the design of the object is located in one complete package. Reuse - Once an object is created, it is easy to drop that object into another piece of code (or share with others) that requires a similar procedure. (ex. Login object, database connection, etc.) Quality - When using code that has already been used in another application, the chances of the bugs being worked out is high. This produces code that had a greater quality and less likelihood of being latent with bugs. Maintainability - Using objects creates a central location to change code if need be. If the code is in one place, being called by other programs, it is easier to change that one piece of code rather than having to locate and change numerous pieces of code.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-2

Developing Dynamic Web Applications with MySQL and PHP


237

Chapter 13- Object Oriented Programming

13.3 Working with Objects


Two terms that are often heard when discussing OOP are class and object. A class is essentially a description of an object (the code itself), while an object is an instance of that class. One method to think about it is that an object has a particular class for example, $myDog is an object of class Dog. Generally, a class represents a particular type of object, either a physical object (such as a Dog) or a conceptual one (such as a Poll). The methods in a class represent either things that an object can do itself, or that another object can cause the class to do. Similarly, a property represents some piece of information, either something kept track of inside the class, or something that other objects are allowed to access and modify. Public, Private, Protected, Static Methods and properties can be declared in one of three ways: public, private, or protected. Public - Public methods and properties can be accessed by any code, inside or outside of the object, for example by other objects. Private - Private methods and properties can only be accessed internally, by other code inside of the class. Protected - Protected methods and properties can be accessed internally, as well as by parent or inherited classes.

Static - Methods can also be declared static, which means that it is not required to create an object in order to call that method. Some static methods may be purely informational, while others perform a 'one-off' function such as deletion of a record, as it may not make sense to populate an object with data just to delete it from the database. Static methods may also return an instance of a class, which can be an easier way to fetch an object under a certain condition (for example, if a given ID is not available). Working with classes In order to use a class, it must be instantiated. Instantiation is the act of allocating a new instance of the class. Put simply, to use a class, an object must be created. This is done using the 'new' operator. For example, this statement would create an object $myCanine of class Dog: $myCanine = new Dog(); Once an instance of the class is created, the end user is able to access public methods and properties of that class.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-3

Developing Dynamic Web Applications with MySQL and PHP


238

Chapter 13- Object Oriented Programming

Code Example
<?php class Dog { // Anyone can see the dog's color public $furColor; // The dog's age is not immediately obvious private $age; // Only the dog can decide to run private function Run() { /* Code */ } // Anyone can pet the dog public function Pet() { /* Code */ } // dog not needed to find out about local breeds public static function getLocalBreeds() { /* Code */ } } $myCanine = new Dog(); $myCanine->furColor = 'brown'; /* Dye our dog's fur */ $myCanine->Pet(); $myCanine->Run(); /* Illegal - Private method */ echo $myCanine->age; /* Illegal - Private property */ $breeds = Dog::getLocalBreeds(); ?>

In the code example above, the definition of a basic class, as well as some example uses of the class is displayed. The first block of code is the class definition. Inside of this class definition is where the definitions for the methods and properties. In this example, there are two properties, representing the color of the dog's fur and the age of the dog. The first is a public property, meaning that any code, internal or external, is capable of reading or changing the value of that property. The second is private, meaning it can only be accessed by code running inside of the class. Method Declarations Next, there are two method declarations. The first declaration is the private method 'Run()'. Being private, the method is only available to code running inside of the class. In this example, that might mean that the Dog will only run as a result of something else happening to it (another method being called). The second declaration, 'Pet()', is public, meaning anyone can call the method. Thus, any outside user is able to pet (or try to pet) the dog. Perhaps if the dog is not feeling sociable, it may try to get away, calling the 'Run()' method to escape. Instantiate a Class After the class is defined, an object of class Dog is instantiated, using the example seen earlier. This creates a new variable in PHP and allocates a Dog object that can be accessed using that variable, providing access to the public properties and methods of that class. Accessing Public Properties and Methods Next, the public properties and methods of the object is accessed, by changing the color of the dog's fur (perhaps dying it), and then by petting the dog afterwards.
$myCanine->furColor = 'brown'; $myCanine->Pet();

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-4

Developing Dynamic Web Applications with MySQL and PHP


239

Chapter 13- Object Oriented Programming

Accessing Private Properties and Methods Afterwards, an attempt is made to access private properties and methods to which the end user does not have permissions. In PHP, any attempt to access a private property or method throws an immediate fatal error, and script execution halts; in this case, the code will never reach the second attempt.
$myCanine->Run(); /* Illegal - Private method */ echo $myCanine->age; /* Illegal - Private property */

Get and Set Functions A common convention in object-oriented programming is to use get and set functions. For example, a getAge() method could be defined that would allow access to read the canine's age, but not change it. The canine's fur could also be changed to be a private property, and then provide a getColor() method to read the value, and a dyeFur() method to attempt to change the value. Informational Functions Finally, there is an informational function, getLocalBreeds(), to provide a list of breeds of canines native to our locale (whatever that might be). Since this is a canine-related function, the code is put into the Dog class; however, since there is no need to actually have a canine object in order to find out the local breeds of canines, it is made as a static function. The function can then return an array of local canine breeds, which can then be used in any fashion required, without creating an instance of the class first.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-5

Developing Dynamic Web Applications with MySQL and PHP


240

Chapter 13- Object Oriented Programming

13.4 Exception Handling


Exception handling is a core feature of almost any programming language and is designed to handle the occurrence of some condition that changes the normal flow of execution. The term, exception, comes from the fact that an exceptional condition has taken place that has prevented the continuing flow of the script in which it occurred. PHP provides a powerful exception-handling model that can easily be used by programmers. The Exception Flow In the operation of a normal script, there is always the potential for an unexpected event (exception) to creep into the execution of the script. By placing conditional tests at certain points in the operation of the script, the programmer can test to see if everything is working correctly. If the conditional test returns normal, then the execution of the script continues with no interruption. However, if the conditional test fails, an exception is thrown letting the system know that not everything is working correctly. At this point, the exception is caught and handled by pre-defined methods. Once the methods are completed in handling the exception, the execution of the script either continues or dies gracefully (hopefully).

Normal Script Execution Conditional Test ( try )


Failed

Passed Continue Execution

Throwan Exception ( throw ) Catchthe Exception ( catch )


Continue Execution

241

PHP's Exception-Handling Implementation

Clean Up

Graceful Death

STOP

In PHP 5, the implementation of the exceptionhandling capabilities is accomplished with the improved object-oriented programming (OOP) capabilities. The first part of the exception-handling object is the base exception class. There are two ways to initiate the base exception class: Default Constructor - A constructor is a block of code that automatically executes at the time an object is created (or instantiated). The default constructor for the base exception class contains no parameters to initiate the class. throw new Exception(); The command throw, identifies the function used to initiate an exception being captured. The term, new, refers to the fact that a new object is being created and the class is called Exception. Overload Constructor - This constructor method is similar to the default constructor, with the exception that parameters can be added to personalize the base exception class. The two parameters are message and error code: o message - This is the message that will be stored for use in the output of any exceptions that are captured. o error code - This is a code that is stored (similar to the message) and can be used in the output of any exceptions that are captured. This code can be used in an identifier-to-message table that displays specific messages based on the audiences needs (ex. language).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-6

Developing Dynamic Web Applications with MySQL and PHP Methods

Chapter 13- Object Oriented Programming

After initializing the base exception class, there are six methods that are available for use in any output based on the exception that is caught: getMessage() - This returns the message that was passed into the overload constructor, if any. getCode() - This returns the error code that was passed into the overload constructor, if any. getLine() - This returns the line number where the exception was thrown in the script. getFile() - This returns the name of the file where the exception was thrown. getTrace() - This returns an array consisting of important information that would be useful in tracing where an exception was thrown: file name, line, function and function parameters. getTraceAsString() - This is identical to getTrace(), but returns the values as a string rather than an array. Putting It All Together The example below demonstrates how the base exception-handling class, with the use of the overload base class constructor, can throw and capture exceptions:
<?php try { $linkID1 = mysql_connect("localhost", "root","badpsswd"); if (! $linkID1) { throw new Exception("Could not connect to MySQL!"); } } catch (Exception $e) { echo $e->getMessage()." (File: ".$e->getFile().", line ".$e>getLine().")"; } ?>

242

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-7

Developing Dynamic Web Applications with MySQL and PHP


243

Chapter 13- Object Oriented Programming

Lab 13-A
In this further practice, you will use the view_images.php and replace the die statement with an exception handling script. 1. 2. In the mysql client, recreate (or create) the photo_album database and source in the /tmp/photo_album.sql file to propogate the database with clean data. Using the script view_images.php, ensure that the correct script is being used by viewing the image associated with id_image 15 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=15. Does the form contain links to move to the previous image and the next image? Does the form contain the ability to delete the image? Does the form have the ability to update the date? Does the form contain comments associated with the image and provide the ability to add comments? Can you shut down the browser, restart and return to the exact picture you left by typing in only the PHP file (http://localhost/view_images.php)? If so, then the correct version of the view_images.php file is being used. Replace the ... or die ... script for connecting to the database with an exception handling script that will identify there is an error, display the file the error is associated to and the line of the error in the file. After saving the changes, reload the http://localhost/view_images.php file in your browser. Is the script still working correctly? In the view_images.php script, replace the password ($dbpass) with an empty string (forcing the exception handling to be tested). After saving the changes, reload the http://localhost/view_images.php file in your browser. Is the script still working correctly? If not, is there a message letting you know what the problem is? Correct the view_images.php script, save the changes and refresh in the browser. Is everything working correctly again?

3.

4. 5. 6. 7.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-8

Developing Dynamic Web Applications with MySQL and PHP


244

Chapter 13- Object Oriented Programming

13.5 Chapter Summary


In this chapter, you have learned to: Describe the Benefits of Object Oriented Programming Object-oriented programming (OOP) is a programming model that uses "objects" in the design of the applications. The benefits include encapsulation, reuse, quality and maintainability. Two terms that are often heard when discussing OOP are class and object. A class is essentially a description of an object (the code itself), while an object is an instance of that class. Methods and properties can be declared in one of three ways: public, private, or protected. Public methods and properties can be accessed by any code, inside or outside of the object, for example by other objects. Private methods and properties can only be accessed internally, by other code inside of the class. Protected methods and properties can be accessed internally, as well as by parent or inherited classes. Methods can also be declared static, which means that it is not required to create an object in order to call that method. Exception handling is a core feature of almost any programming language and is designed to handle the occurrence of some condition that changes the normal flow of execution. The term, exception, comes from the fact that an exceptional condition has taken place that has prevented the continuing flow of the script in which it occurred. PHP provides a powerful exception-handling model that can easily be used by programmers.

Explain the Class Data Type

Explain the purpose of Methods within the Class Data Type

Utilize Exception Handling in PHP

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 13-9

Developing Dynamic Web Applications with MySQL and PHP

245

CHAPTER 14 ESTABLISHING USER AUTHENTICATION


246

Developing Dynamic Web Applications with MySQL and PHP


247

Chapter 14- Establishing User Authentication

14 ESTABLISHING USER AUTHENTICATION


14.1 Learning Objectives
This chapter provides the knowledge necessary to authenticate user identities utilizing PHP built-in authentication capabilities and MySQL's user and privilege management capabilities. At the completion of this chapter, you will be able to: Describe HTTP Authentication Utilize PHP Authentication Using Hard-coded Authentication Utilize PHP Authentication Using File-based Authentication Utilize PHP Authentication Using Database Authentication

Instructor Notes: This chapter does not have any inline labs. The scripts that are presented are available for the students to either recreate or pull from the example files associated with this chapter. The further practice will ______________________________________________________________________________________________ give the students the ability to interact with the database component they have learned in this chapter. The files associated with this chapter HardCoded_auth.php, FileBased_auth.php, Database_auth.php, auth_users.txt, ______________________________________________________________________________________________ View_Images7.php and View_Images8.php along with photo_album.sql and world_with_customers.sql. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-1

Developing Dynamic Web Applications with MySQL and PHP


248

Chapter 14- Establishing User Authentication

14.2 HTTP Authentication


The HTTP authentication protocol is a basic authentication scheme to allow a client program (like a web browser) to provide credentials in the form of a username and password when requesting a request (like a web page) that is protected by this level of authentication.

User Requests A Resource Server Responds With a 401

The process of the authentication starts with a user requesting a resource that is protected by the http authentication method. The server responds with a 401 (unauthorized access) response 401 message. The client program (web browser) recognizes the 401 Unauthorized response and produces a pop-up authentication prompt that requests the username and password be entered. If the username and password match a username and password combination stored on the server (and on the appropriate resource), the resource is then made View Resource available to the end user. The server maintains the username and Requested password entered in until the browser is closed or a different http authentication protected resource is requested. If the username and password combination do not match a recognized username and password combination on the server (and the appropriate resource), the client program produces a response identifying a 401 unauthorized access. Types of HTTP Authentication There are currently 2 modes of authentication built into HTTP 1.1 protocol, termed 'Basic' and 'Digest' Access Authentication. Basic Authentication transmits the username:password pair in an unencrypted form from browser to server and in such should not be used for sensitive logins unless operating over an encrypted medium such as Secure Socket Layer (SSL). Digest Authentication sends the server a one way hash of the username:password pair calculated with a time sensitive, server supplied salt value. The use of a salt value means that every authentication attempt with the same username:password pair will result in a unique hash and is not vulnerable to replay attacks. The Digest Authentication Mechanism was developed to provide a general use, simple implementation, access control that could be used over unencrypted channels. Users should note that it is not as secure as client-side private-key authentication mechanisms. It is also important to note that only the username:password is protected by the hashing mechanism and that without the use of an encrypting medium such as SSL all retrieved documents will still be visible to all parties with access to network traffic. These two types of authentication do have their place in applications that require authentication; however, they should not be considered high grade protection for sensitive information or access as they do not address network level attacks. Using User Authentication For the purposes of this course, the HTTP authentication will not be taught in detail (as far as how it is actually implemented). However, if there is a need to use this type of authentication, ApacheWeek has an excellent article on setting up authentication - http://www.apacheweek.com/features/userauth.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-2

Developing Dynamic Web Applications with MySQL and PHP


249

Chapter 14- Establishing User Authentication

14.3 PHP Authentication


When addressing the need to authenticate a web page (and subsequent pages/resources), integrating user authentication directly into the design of the web application logic is both convenient (in the sense that additional layers of communication is unnecessary) and flexible (in the sense that it is easier to integrate into other applications/scripts when contained in one location). PHP allows three types of authentication: Hard-coded, file-based and database authentication. Authentication Variables Within PHP, there are two pre-defined variables that are used in the authentication of users: $_SERVER['PHP_AUTH_USER'] - This variable holds the username that is needed for authentication. $_SERVER['PHP_AUTH_PW'] - This variable holds the password that is needed for authentication. Limitations of Authentication Variables When using the predefined authentication variables, it is important to keep in mind the following limitations: Both variables must be verified at the start of every page. This limitation can be overcome by having each restricted page wrapped in authentication code (in a separate file) using the REQUIRE() function. The functions do not work properly with the CGI version of PHP - When running PHP through a web server, there are two distinct options: running it using PHP's CGI SAPI, or running it as a module for the web server. The CGI version has the advantage of having the php.ini read every time a PHP page is called up; thus allowing changes in the php.ini to take place immediately (not requiring a restart of the web server). However, the fact that every time a PHP file is read, the php.ini has to be read, set its settings and load all of its extensions prior to actually reading the script makes this choice an unreasonable choice for production environments (may be appropriate in development because changes made can be seen immediately). These functions do not work on Microsoft's IIS server - the username and password are assigned to the $_SERVER['HTTP_AUTHENTICATION'] variable and must be parsed to obtain the separate username and password.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-3

Developing Dynamic Web Applications with MySQL and PHP


250

Chapter 14- Establishing User Authentication

14.3.1

Hard-Coded Authentication This is the simplest PHP authentication to implement but has the problem of being limited on flexibility and high on maintenance cost. It literally places the username and password into the script as seen in the following example:
<?php if (($_SERVER['PHP_AUTH_USER'] != 'root') || ($_SERVER['PHP_AUTH_PW'] != 'training')) { header('WWW-authenticate: Basic Realm="Photo Album"'); header('HTTP/1.0 401 Unauthorized'); print "You must provide a valid username and password!"; exit; } // Remainder of script ?>

In this example, the first portion of the script reads in the username and password variables. If the variables do not match the hard-coded user name or password, then the script prints out some HTTP header information and text saying that the username and/or password was not valid. It then exits the script and terminates the rest of the script processing. If, though, the username and password are correct, this portion of the script is ignored and the remainder of the script is executed. Limitations of Hard-Coding Although this method is quick and easy, it has a number of drawback that make it unrealistic for applications in production. Using the same username - As the code stands, every user requiring access to this web page would need to use the same login name and password. This is not the way most applications in production work. The majority of applications in production use the username to provide specific preferences and specific access to resources that could not be done if everyone is using the same username. Of course, additional usernames and passwords could be coded in, but that is just nonsensical and leads to poor coding techniques. Maintenance nightmare - If the username and password are compromised, a new username and password have to be hard-coded in and everyone using that username and password have to be notified of the change. Anytime that code has to be touched leads to the greater likelihood that something else could be inadvertently changed causing the script to malfunction. Avoiding touching code in production is a best practice for reliability of services. header() function The header() function is used to send a raw HTTP header into the web browser. In the case of the scripts being used in this section, the header information being submitted to the browser forces the web browser to produce the HTTP authentication login prompt. This function is crucial to the success of authentication, no matter which PHP authentication method that is being used.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-4

Developing Dynamic Web Applications with MySQL and PHP


251

Chapter 14- Establishing User Authentication

14.3.2

File-Based Authentication Using file-based authentication can eliminate the single username and password problem of the hard-coded solution; however, there can still be limitations that must be considered in implementing this authentication solution. The first things that needs to be created when using this solution to authentication is to create a users text file. This file should be located in a directory that is not in or under the htdocs directory of the web server (to eliminate someone being able to access the file through the website). It also needs to be in a directory that the server can read and write from. For the example below, the /tmp directory will be used; however, in production this directory should not be used because it is cleaned out every time the server restarts and is easily accessible to anyone who can access the server. The Users Text File The following is the contents of the /tmp/auth_users.txt file: Candance:90e0b2ef171cf8edd7f58527f3134f634ccb7091 Celine:44c40e17b33ee3fd125120b7ccddbeed2b2d7db3 Frank:ef1c3c9da92b9f869ea684808312525130c7f530 Granny:eaf7def567e8c7462a7f5530328016203409c474 Hank:70f7ec35e966287aefd78352828f21fc0c8fae33 Howard:38c260888790bbe43e7ec191fd90544d2c8c59d0 Jarel:c968edd668e273763e039a511b76609b195570fd Mildred:a9e4af8f7113527a04defa057a7a65136cdae803 Pierre:72a3925b00f932dbe79e6ee99818b3556b27e88c Roberta:160409a52594eab968f03a46019ea2ab8e9606a7 Rudy:70f08ceac2f2428e3f3b87e2bc5e23d2c3c6f447 Tawanda:b5a03cd9c9eaf136aa704e00008b60855903477f Yogi:3234eec08278d9c9a22d7478f7adbe0d245dae45 The File-Based Authentication script Prior to showing the example script for using file-based authentication, there are a few functions that need to be discussed: file() - The file() function has one parameter, the location of the file to be read in entered as a string. The function will read the contents of the file into an array, with every line being an array element. explode() - The explode() function is similar to the split() function, but does not require the use of PHP's regular expression parsing engine, making it perform quicker. The explode() function has two parameters. The first is the delimiter which will be searched for within the string (which is the second parameter). The string is separated into an array based on the delimiter that is used. sha1() - This function calculates the sha1 hash of the string parameter (the only parameter for this function) using the US Secure Hash Algorithm 1, and returns that hash. The hash is a 40-character hexadecimal number.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-5

Developing Dynamic Web Applications with MySQL and PHP


252

Chapter 14- Establishing User Authentication

The File-Based Authentication Script


<?php // Preset the variable used to verify authentication $authorized_user=FALSE; if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { // Read the authentication file into an array $authArray = file("/tmp/auth_users.txt"); foreach ($authArray as $row) { list($user,$pswd) = explode(":", $row); // Remove the new line character from the password $pswd = trim($pswd); if (($_SERVER['PHP_AUTH_USER'] == $user) && (sha1($_SERVER['PHP_AUTH_PW']) == $pswd)) { $authorized_user=TRUE; break; } } } // Test to see if there is an authorized user if (!$authorized_user) { header('WWW-authenticate: Basic Realm="Photo Album"'); header('HTTP/1.0 401 Unauthorized'); print "You must provide a valid username and password!"; exit; } // Remainder of script ?>

253

In this example, the first portion of the script reads in the username and password variables along with the usernames and passwords from the authorized users file. After looking at each authorized users file entry, if the authentication variables do not match any of the user names or passwords, then the script moves on to the next condition (which remains FALSE) and prints out some HTTP header information and text saying that the username and/or password was not valid. It then exits the script and terminates the rest of the script processing. If, though, the username and password are found in the authorized users file, then the test variable is set to TRUE and the second condition is ignored and the remainder of the script is executed. Limitations of File-Based Authentication Although this method is much more robust over hard-coding authentication, it still has its limitations: Large Number Of Users - As the user base grows, so does the need to maintain and update the authorized users file. This can become a maintenance time drain and/or a coding nightmare to parse and edit with supporting code. Limited Infrastructure - The use of file-based authentication schemes are designed for relatively small data infrastructures. As the data complexity grows, so does the problems associated with connecting a flat-file (or multiple flat-files) with other data storage techniques (such as databases).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-6

Developing Dynamic Web Applications with MySQL and PHP


254

Chapter 14- Establishing User Authentication

14.3.3

Database Authentication The final, and most complete of the three PHP authentication methods, is the utilization of a database to maintain and manage the usernames and passwords used to access PHP files. This solution provides advanced capabilities in administering authentication systems but also provides incredible flexibility and scalability to incorporate the authentication system into the database system as a whole. The first step of the process involves creating the user tables that will be used to house the authentication data. Storing Authentication Data The following table will be used to manage the storage of the login information that will be used by PHP to manage logins:
CREATE TABLE `customers` ( `customerEmail` VARCHAR(40) NOT NULL, `lname` VARCHAR(25) NOT NULL, `fname` VARCHAR(25) NOT NULL, `title` ENUM('Mr.', 'Mrs.', 'Miss', 'Ms.','Dr.'), `passwd` VARCHAR(30), PRIMARY KEY (`customerEmail`) );

255

The idea of using the customerEmail as the login in identifier has become standard practice in many web applications these days. As far as an email being a primary identifier for the customer, it is perfect; It is unique (no two people could have the exact same e-mail account), it is specific to the user and it is an alternate means to contact the user. In this table, there could be additional columns used to support other areas of the application; however, for the purpose of this training, this table will suffice. The Database Authentication Script
<?php // Create a function due to the script components having to be called 2x function userAuth() { header('WWW-authenticate: Basic Realm="World Database"'); header('HTTP/1.0 401 Unauthorized'); print "You must provide a valid e-mail and password!"; exit; } // Check to see if the login prompt has been submitted // If not, call up the login prompt, if so, check against // the database if (! isset($_SERVER['PHP_AUTH_USER'])) { userAuth(); } else { // Connect to the MySQL Server and use the // world database (which houses the customers table) $linkID1 = mysql_connect('localhost','root','training') or die("Could not connect to $dbhost database"); mysql_select_db("world",$linkID1) or die ("Could not connect to world database"); // Create variables for login data $serverEmail = $_SERVER['PHP_AUTH_USER']; $serverPass = $_SERVER['PHP_AUTH_PW']; // Create and execute the verification $login_query = "SELECT title, lname FROM customers WHERE customerEmail = '$serverEmail' AND passwd = SHA('$serverPass')"; $login_results = mysql_query($login_query, $linkID1);

256

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-7

Developing Dynamic Web Applications with MySQL and PHP


257

Chapter 14- Establishing User Authentication

// Verify user, otherwise prompt again if (mysql_numrows($login_results)==0) { userAuth(); } else { list($title,$lname) = mysql_fetch_row($login_results); } print "You are authorized to view the data $title $lname<br>\n"; } ?>

For the most part, this script is a standard interaction with MySQL. The only real difference in this script is that the email and password information is being collected through the HTTP standard login prompt.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-8

Developing Dynamic Web Applications with MySQL and PHP


258

Chapter 14- Establishing User Authentication

Lab 14-A
In this further practice, you will use the view_images.php and replace the die statement with an exception handling script. 1. 2. In the mysql client, recreate (or create) the photo_album database and source in the /tmp/photo_album.sql file to propogate the database with clean data. Using the script view_images.php, ensure that the correct script is being used by viewing the image associated with id_image 15 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=15. Does the form contain links to move to the previous image and the next image? Does the form contain the ability to delete the image? Does the form have the ability to update the date? Does the form contain comments associated with the image and provide the ability to add comments? Can you shut down the browser, restart and return to the exact picture you left by typing in only the PHP file (http://localhost/view_images.php)? If so, then the correct version of the view_images.php file is being used. Add a database authentication to the view_images.php that check the users login name and password against the logins table in the photo_album database. Once access is granted, use the users login name to track the comments that they add to the database. After saving the changes, reload the http://localhost/view_images.php file in your browser and attempt incorrect logins along with hitting the cancel button on the login prompt window. What happens? Was that expected? Reload the http://localhost/view_images.php file in your browser and login with the e-mail Granny@Grannies4Life.com and the password Iam30andCounting. Was the login accepted? Add comments to any of the pictures. Do your comments get associated with Granny?

3.

4.

5. 6.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-9

Developing Dynamic Web Applications with MySQL and PHP


259

Chapter 14- Establishing User Authentication

14.4 Chapter Summary


In this chapter, you have learned to: Describe HTTP Authentication The HTTP authentication protocol is a basic authentication scheme to allow a client program (like a web browser) to provide credentials in the form of a username and password when requesting a request (like a web page) that is protected by this level of authentication. This is the simplest PHP authentication to implement but has the problem of being limited on flexibility and high on maintenance cost. It literally places the username and password into the script. Using file-based authentication can eliminate the single username and password problem of the hard-coded solution; however, there can still be limitations that must be considered in implementing this authentication solution. The final, and most complete of the three PHP authentication methods, is the utilization of a database to maintain and manage the usernames and passwords used to access PHP files. This solution provides advanced capabilities in administering authentication systems but also provides incredible flexibility and scalability to incorporate the authentication system into the database system as a whole.

Utilize PHP Authentication Using Hard-coded Authentication

Utilize PHP Authentication Using File-based Authentication

Utilize PHP Authentication Using Database Authentication

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 14-10

Developing Dynamic Web Applications with MySQL and PHP

260

CHAPTER 15 SECURING MYSQL AND PHP


261

Developing Dynamic Web Applications with MySQL and PHP


262

Chapter 15- Securing PHP and MySQL

15 SECURING PHP AND MYSQL


15.1 Learning Objectives
This chapter provides the knowledge necessary to secure PHP and MySQL to improve the integrity of the application and subsequent data. At the completion of this chapter, you will be able to: Explain PHP's Configuration Parameters that Support Securing an Application Utilize PHP's Encryption Functions Secure the mysqld daemon Describe the MySQL Access Privilege System

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-1

Developing Dynamic Web Applications with MySQL and PHP


263

Chapter 15- Securing PHP and MySQL

15.2 Building a Wall of Security


The reality of attacks on the web can be seen in the number of viruses being created everyday and the number of warnings being sent out by some of the top names in the industry. However, it is more than just being defensive when it comes to security, there needs to be an offensive with security issues. This offensive task is not to take vigilante action against any user who attempts to break into the applications, but rather to take a pro-active approach to removing the wholes in the application that can be used by a would-be attacker. In the realm of web based applications, there are numerous areas where a would be attacker could exploit an opening and turn in into a nightmare for the administrator: Data Entered by Users - Trusting users to enter the correct data into a form field, is liking trusting a lion to babysit an infant. There has to be checks and boundaries placed into any input prior to allowing that input into a file, a database or any other means that is being used to stored the collected data. Technology Holes - With the number of technologies that are used in the make-up of a web application, the interaction between these technologies can be a source of attack for a would-be attacker. In addition, updates are being constantly made to close up vulnerabilities in software and administrators have to continually monitor and update the updates that affect their systems. The Web - The internet is filled with not-so-nice, or down right ugly elements that make it their living to wreak havoc on unsuspecting web applications. Worms, viruses, robots, port scanners, script kiddies along with the number of internet users that are determined to cause problems all have to be taken into account when it comes to securing an application. Loose Lips Sink Ships - And last but not least, the authorized end users of the system can cause havoc either intentionally but more often unintentionally. Deletions, sharing logins/passwords, using passwords that are easily cracked, having access to too much data, etc. all play into considerations that need to be addressed with an application. Well, now that we have laid out just a few of the areas where a system can become a ticking time-bomb, many may want to run to the hills now and stick their heads under their pillow. Not so fast, this is not the end of the web based applications, they are just getting started. Knowing the enemy is the first step in being able to defend against them. With some simple and not-so-simple steps, the applications being supported can become a safe zone of data (or as close to that as possible).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-2

Developing Dynamic Web Applications with MySQL and PHP


264

Chapter 15- Securing PHP and MySQL

15.2.1

PHP Configurations The first step in any process of securing an application is checking the configuration components that the software is running under. Some configuration options are crucial to the running of the software, while others can be shut down based on the needs of the applications that will run on the software. The first and probably the most extensive breadth is the safe_mode configuration option: Running PHP in Safe Mode When running PHP in a shared server environment, the use of Safe Mode needs to be considered and when possible implemented. With safe mode enabled, the unintended execution, review and modification of files not under the ownership of the executing user is prevented from taking place. With the file privilege system not being able to be modified (through proper configuration on the O/S), this mode can be advantageous to preventing a number of intentional or unintentional attacks. This is only one area where safe mode comes into play, the following configuration parameters are a few of the more important configuration directives that have an affect (or are affected) by safe_mode settings: safe_mode - When this mode is set to 1 (on), the following conditions apply: o Input/Output Functions - Any function that is responsible for inputting files or outputting data to files (fopen(), file(), include(), require(), for example) must be owned by the same owner who is calling or sending data to the file. o New Files - When new files are created, they must be created in a directory that the script owner owns. o External Scripts - Attempts to execute external scripts (with the likes of popen(), system(), or exec()) are only allowed to be executed from the safe_mode_exec_dir configuration option. o UserID with Authentication - The UserID (UID) of the owner of the authentication script is added to the authentication realm. o MySQL User - The username used to connect to MySQL server must be identical to the name of the owner of the file calling mysql_connect. safe_mode_gid - With this configuration option set to 1 (on), the group id is checked versus the user id. This gives users in the same group the ability to execute and run each others scripts. safe_mode_include_dir - Directories placed in this directory will ignore the safe_mode directives (if safe_mode is turned on). Multiple directories can be placed in this configuration by separating the directories with a semicolon. safe_mode_exec_dir - The directory placed in this configuration directive identifies which directory will be used for execution of files by functions such as system(), exec() or passthru(). This only works when the safe_mode is turned on.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-3

Developing Dynamic Web Applications with MySQL and PHP


265

Chapter 15- Securing PHP and MySQL

Other Security-Related Configuration Directives Beside safe mode, there are other security related configuration directives that assist in providing security for PHP. The following is the most common directives to be considered: disable_functions - Setting safe_mode can be a huge security leap for some programmers and an alternative is just disabling the functions that are not needed. To disable multiple functions, separate the functions by commas. This directive is not affected by safe mode. doc_root - This directive, when set, determines the location from which PHP files can be executed from. When this directive is empty, the PHP files are executed from wherever they are called from. If safe mode is turned on, PHP files can only be executed from this directory. max_execution_time - This directive identifies how long a PHP file (in seconds) can be taking up processing time before it is terminated. If set to zero (0), no time limit is set. open_basedir - This directive can establish a base directory to which all file operations will be restricted. By having a base directory identified, users are unable to manipulate PHP scripts to access otherwise restricted areas of the server. sql.safe_mode - When enabled, this mode will only use the localhost when connecting to the mysql server (with mysql_connect) regardless if another server is selected to be used. phpinfo.php The phpinfo.php file is extremely useful when setting up a LAMP environment; however, shortly after setting up the environment, this file should be removed. Keeping this file available for others to call up literally gives would-be attackers the keys to your complete system features. This level of information can greatly increase the potential for your servers to fall prey to attackers.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-4

Developing Dynamic Web Applications with MySQL and PHP


266

Chapter 15- Securing PHP and MySQL

15.3 Data Encryption


Data encryption is the process of scrambling stored or transmitted information so that it is unintelligible until it is unscrambled by the intended recipient. The intended recipient can then decode (or decrypt) the information. PHP offers multiple means to make this happen. However, none of these solutions are very effective without the applications running on secure servers and connections. The following are a list of the more common encryption functions in PHP: md5() - MD5 is a third-party hash algorithm that PHP can use to create a digital fingerprint of a piece of data. It is next to impossible to (efficiently) recover the original text when a piece of data has been encrypted with the md5 hash algorithm. It is also vastly unlikely that any different text string will create an identical hash - a 'hash collision'. These properties make hashes ideally suited for storing an application's passwords because although an attacker may compromise a part of the system and reveal the list of password hashes, they can't determine from the hashes alone what the real passwords are. The md5() function returns a 128-bit hash (32 hexadecimal characters) that can then be stored with the ultimate outcome of comparing it for security purposes.
<?php $string = "IamAbigFanofIceCream"; $string_md5 = md5($string); if (md5($string) = $string_md5) { print "$string = md5($string_md5)"; } ?>

Will print:
IamAbigFanofIceCream = md5(673d924425c45b1f2221fdfcbe2160cf)

sha1() - SHA-1 (Secure Hash Algorithm 1) is another hashing algorithm that can be used by PHP for encryption purposes. The sha1() function returns a 160-bit hash (40 hexadecimal characters).
<?php $string = "IamAbigFanofIceCream"; $string_sha1 = sha1($string); if (sha1($string) == $string_sha1) { print "$string = sha1($string_sha1)"; } ?>

Will print:
IamAbigFanofIceCream = sha1(e2a0049b70506530f7b9bfc8e5967505a5b366ec)

Numerous Encryption Methodologies By extending PHP with other open-source packages, such as mhash and mcrypt, that can be compiled with PHP to offer more advanced methods of encryption. Each has there advantages and disadvantages and should be evaluated prior to implementing into your systems. However, the open source community (as well as those of the more traditional closed development houses) is very interested in providing a level of hashing that will be "uncrackable". For the most part, the level of sophistication that is needed to crack an md5 and sha1 hash algorithm still makes these two solutions viable options for the less demanding (concerning security) applications.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-5

Developing Dynamic Web Applications with MySQL and PHP


267

Chapter 15- Securing PHP and MySQL

15.4 Securing the MySQL Server (mysqld)


MySQL Server, or mysqld, is the database server program. The server manages access to the actual databases on disk and in memory. MySQL Server is multi-threaded and supports many simultaneous client connections. Clients can connect via several connection protocols. For managing database contents, the MySQL server features a modular architecture that supports multiple storage engines that handle different types of tables (for example, it supports both transactional and non-transactional tables). In order to achieve a high level of security, the following should be implemented in the installation and configuration of MySQL: MySQL processes must run under a unique UID/GID that is not used by any other system process o The MySQL server should not be run as root but instead should be run as another user whose sole purpose is to execute the MySQL server. This can be accomplished by creating a user called mysql that is assigned to a group called mysql. Once the user is created, all the data directory (/usr/local/mysql/data) should be assigned to this user and group. In addition, the mysql directory should at least be assigned the mysql group (root can still own the directory). Only local access to MySQL will be allowed o MySQL listens by default to the 3306/tcp port; however, best practices would have the database only being used locally by installed PHP applications, thus listening on that port can be disabled. This will limit possibilities of attacking the MySQL database by direct TCP/IP connections from other hosts. Local communication will be still possible throw the mysql.sock socket. In order to disable listening on the mentioned port, the following parameter should be added to the [mysqld] section of the my.cnf file: skip-networking If, for some reason, remote access to the database is still required (e.g. to perform remote data backup), the SSH protocol can be used as follows: backuphost$ ssh mysqlserver /usr/local/mysql/bin/mysqldump -A > backup o In addition, disabling the use of LOAD DATA LOCAL INFILE command will help prevent unauthorized reading from local files. This matters especially when new SQL Injection vulnerabilities in PHP applications are found. For that purpose, the following parameter should be added in the [mysqld] section of the my.cnf file: set-variable=local-infile=0 MySQL root's account must be protected by a hard to guess password o One of the most important steps in securing MySQL is changing the database administrator's password, which is empty by default. The password should be changed only from inside the mysql client, because other users of the server may be able to access the commands from the operating system command line by using the "ps aux" command or reviewing history files (~/.history, ~/.bash_history etc), when improper access rights are set to them. To change the password within the mysql client, type: SET PASSWORD FOR root@localhost=PASSWORD('new_password'); The administrator's account should be renamed o It is also recommended to change the default name of administrator's account (root), to a different, harder to guess one. Such a change will make it difficult to perform brute-force and dictionary attacks on the administrator's password. In this case the intruder will have to guess not only the password, but first and foremost, the name of the administrator's account. From within the mysql client, type: update user set user="mydbadmin" where user="root"; ______________________________________________________________________________________________ flush privileges; ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-6

Developing Dynamic Web Applications with MySQL and PHP

Chapter 15- Securing PHP and MySQL

Remove default users/db o Anonymous access to the database (by using the nobody account) must be disabled and all sample databases and tables must be removed. From within the mysql client, type: drop database test; use mysql; delete from db; delete from user where not (host="localhost" and user="root"); flush privileges;

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-7

Developing Dynamic Web Applications with MySQL and PHP


268

Chapter 15- Securing PHP and MySQL

15.5 MySQL Access Privilege System


A MySQL account is defined in terms of a username and the client host(s) from which the user can connect to the server. The account also has a password. Therefore, when a user connects to the server, it checks not only the username that is specified, but also what host their connecting from and if their password authorizes a connection and action. shell> mysql --user=<username> --password=<password> db_name shell> mysql u <username> -p<password> db_name MySQL versus Operating System Accounts There are several distinctions between the way usernames and passwords are used by MySQL and the way they are used by the operating system: MySQL Usernames for authentication Not directly connected to OS Default can be easily over-ridden with user option Passwords are important because anyone can attempt to connect to the server using any username Usernames can be up to 16 characters Server login passwords have nothing to do with OS passwords Encrypts passwords using its own algorithm Same as PASSWORD() SQL function May be different for each OS (i.e., Unix is typically limited to 8 characters) OS login passwords have nothing to do with MySQL server passwords Different encryption used by Unix Same as ENCRYPT() SQL function Operating System (OS) Login names Windows and Unix login name not connected to MySQL username

15.5.1

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-8

Developing Dynamic Web Applications with MySQL and PHP


269

Chapter 15- Securing PHP and MySQL

15.5.2

Creating and Dropping User Accounts Three statements create, remove, or rename user accounts: CREATE USER creates a new account and optionally assigns it a password. This statement creates a record in the user table. It does not grant any privileges; to do so, use the GRANT statement later. The following statement creates an account for jim@localhost and assigns the account a password of Abc123. That is, a user named jim will be able to connect from the local host, but must specify a password of Abc123: CREATE USER 'jim'@'localhost' IDENTIFIED BY 'Abc123'; If the CREATE USER includes no IDENTIFIED BY clause, the account is created with no password. This is insecure and not recommended. DROP USER revokes all privileges for an existing account and then removes the account. It deletes all records for the account from any grant table in which they exist. To revoke privileges without removing the account itself, use the REVOKE statement. The following statement removes the jim@localhost account: DROP USER 'jim'@'localhost'; RENAME USER changes the account name for an existing account. It can change the username or hostname parts of the account name, or both: RENAME USER 'jim'@'localhost' TO 'john'@'localhost'; For all three statements, accounts are named in 'user_name'@'host_name' format.

15.5.3

Setting Account Password An initial password can be specified for an account by including an IDENTIFIED BY clause in the CREATE USER statement. However, To change an existing account's password without changing any of its privileges, the SET PASSWORD statement can be used. For example, to set the password for jim on the local host to NewPass, use this statement: SET PASSWORD FOR PASSWORD('NewPass'); 'jim'@'localhost' =

Any non-anonymous client can change its own password by omitting the FOR clause: SET PASSWORD = PASSWORD('NewPass'); Note that with SET PASSWORD, the PASSWORD() function is used to encrypt the password, whereas with CREATE USER it is not used.

Instructor Notes: The purpose of having a full understanding of user accounts is to be able to control your user ______________________________________________________________________________________________ security. How will user privileges protect or risk your data integrity? For example, an account management level ______________________________________________________________________________________________ is defined as allowing authorized users to do their work and prevent unauthorized users from accessing beyond their privileges. ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-9

Developing Dynamic Web Applications with MySQL and PHP


270

Chapter 15- Securing PHP and MySQL

15.6 Privileges
Several types of privileges can be granted to an account. Privileges should be granted according to how the account is to be used. Some examples: An account that needs only read access to a database can be given only the SELECT privilege. An account that needs to modify data can be given the DELETE, INSERT, and UPDATE privileges. Administrative accounts can be given the PROCESS or SUPER privileges for viewing client process activity or killing connections, or the SHUTDOWN privilege for stopping the server. The MySQL server bases access control on the contents of the grant tables in the mysql database. These tables define MySQL accounts and the privileges they hold. To manage their contents, use statements such as CREATE USER, GRANT, and REVOKE. These statements provide an interface to the grant tables that enables the specification of account-management operations without having to determine how to modify the tables directly. The MySQL server determines what changes to the grant tables are needed and makes the modifications necessary.

271

15.6.1

Types of Privileges That MySQL Supports Several types of privileges can be granted to a MySQL account, and privileges can be granted at different levels (globally or just for particular databases, tables, or columns). For example, a user can be allowed to select from any table in any database by granting the SELECT privilege at the global level. The privileges that MySQL supports are shown in the following tables. The first lists the administrative privileges and the second lists the privileges that control access to databases or objects stored in databases. Administrative Privileges: Privilege CREATE USER FILE LOCK TABLES PROCESS RELOAD REPLICATION CLIENT REPLICATION SLAVE SHOW DATABASES SHUTDOWN SUPER Operations Allowed by Privilege Create, drop, rename accounts Use statements that read or write files on the server host Explicitly lock tables with LOCK TABLES View process (thread) activity Use FLUSH and RESET Ask server for information about replication hosts Act as a replication slave See all database names with SHOW DATABASES Shut down the server Miscellaneous administrative operations

CREATE TEMPORARY TABLES Use TEMPORARY with CREATE TABLE

Instructor Notes: SUPER administrative privilege allows; set global, kill people, setting user=user (in ______________________________________________________________________________________________ CREATE VIEW statements) ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-10

Developing Dynamic Web Applications with MySQL and PHP


272

Chapter 15- Securing PHP and MySQL

Database-access Privileges: Privilege ALTER ALTER ROUTINE CREATE CREATE VIEW DELETE DROP EXECUTE GRANT OPTION INDEX INSERT SELECT SHOW VIEW UPDATE Operations Allowed by Privilege Modify tables with ALTER TABLE Alter or drop stored routines Create databases and tables Create views Remove rows from tables Drop databases and tables Execute stored routines Grant privileges to other accounts Create and drop indexes Add rows to tables Select records from tables Use SHOW CREATE VIEW Modify records in tables

CREATE ROUTINE Create stored routines

273

There are also some special privilege specifiers: ALL and ALL PRIVILEGES are shorthand for all privileges except GRANT OPTION. That is, they are shorthand for granting all privileges except the ability to give privileges to other accounts. USAGE means no privileges other than being allowed to connect to the server. Granting this privilege causes a record to be created in the user table for the account, but without any privileges. This causes the account to exist, and it can then be used to access the server for limited purposes such as issuing SHOW VARIABLES or SHOW STATUS statements. The account cannot be used to access database contents such as tables (although such privileges could be granted to the account at a later time).

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-11

Developing Dynamic Web Applications with MySQL and PHP

Chapter 15- Securing PHP and MySQL

274

15.6.2

Privileges can exist at different levels: Any privilege can be granted globally. An account that possesses a global privilege can exercise it at any time. Global privileges are therefore quite powerful and are normally granted only to administrative accounts. For example, a global DELETE privilege allows the account to remove records from any table in any database. Some privileges can be granted for specific databases: ALTER, CREATE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, GRANT OPTION, INDEX, INSERT, LOCK TABLES, SELECT, SHOW VIEW, and UPDATE. A database-level privilege applies to all tables and stored routines in the database. Some privileges can be granted for specific tables: ALTER, CREATE, DELETE, DROP, GRANT OPTION, INDEX, INSERT, SELECT, and UPDATE. A table-level privilege applies to all columns in the table. Some privileges can be granted for specific table columns: INSERT, SELECT, and UPDATE. Some privileges can be granted for specific stored routines: EXECUTE, ALTER ROUTINE, and GRANT OPTION. The Grant Tables Several grant tables in the mysql database contain most of the access control information used by the server. They contain information to indicate what the legal accounts are and the privileges held at each access level by each account: The user table contains a record for each account known to the server. The user record for an account lists its global privileges. It also indicates other information about the account, such as any resource limits it is subject to, and whether client connections that use the account must be made over a secure connection using the Secure Sockets Layer (SSL). The db table lists database-specific privileges for accounts. The tables_priv table lists table-specific privileges for accounts. The columns_priv table lists column-specific privileges for accounts.

275

The procs_priv table lists privileges that accounts have for stored procedures and functions. Every account must have a user table record because the server uses that table's contents when determining whether to accept or reject client connection attempts. An account also will have records in the other grant tables if it has privileges at other than the global level. Each grant table has columns that identify which accounts its records apply to: The server decides whether a client can connect based on the Host, User, and Password columns of the user table. An account is defined by a hostname and username, so for a client to be able to connect, some record in the user table must match the host from which the client connects and the username given by the client. In addition, the client must provide the password listed in the matching record.

After a client connects, the server determines its access privileges based on the Host and User columns of the user, db, tables_priv, columns_priv, and procs_priv tables. Any privileges enabled in the matching user table record may be used globally by the client. The privileges in the matching records of the other grant tables apply in more limited contexts. There is also another grant table named host that exists for historical reasons. It is not affected by the GRANT and REVOKE statements, so it is discussed no further here. The user_info table (if visible) is created by MySQL Administrator, but has nothing to do with access control, so it's not covered here. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-12

Developing Dynamic Web Applications with MySQL and PHP

Chapter 15- Securing PHP and MySQL

The grant tables are created during MySQL installation as MyISAM tables. The MyISAM storage engine is always guaranteed to be enabled, which is not true for optional storage engines such as InnoDB. (InnoDB is enabled by default, but it can be disabled so that it does not get enabled by default at startup.) As already mentioned, the server uses the information in the grant tables to determine whether to allow clients to connect, and to determine for every statement that a connected client issues whether it has sufficient privileges to execute it. However, the server does not actually access the on-disk grant tables each time it needs to verify client access because that would result in a great deal of overhead. Instead, the server reads the grant tables into memory during its startup sequence and uses the in-memory copies to check client access. The server refreshes its in-memory copies of the grant tables under the following conditions: A user account is modified in the on-disk tables by issuing a account-management statement such as CREATE USER, GRANT, REVOKE, or SET PASSWORD. The server reloads the tables explicitly by issuing a FLUSH PRIVILEGES statement or by executing a mysqladmin flush-privileges or mysqladmin reload command.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-13

Developing Dynamic Web Applications with MySQL and PHP


276

Chapter 15- Securing PHP and MySQL

15.6.3

Granting Privileges It's possible to manage MySQL accounts by modifying the grant tables directly with SQL statements such as INSERT, DELETE, and UPDATE. In general, however, the recommended way to set up and modify MySQL accounts is to use statements such as CREATE USER, GRANT, and REVOKE that are intended specifically for account management. These statements offer the following advantages: It's easier to use account-management statements than to modify the grant tables directly. Their syntax is more natural and less cumbersome for expressing privilege operations because that's what they're designed for. When statements are used such as CREATE USER and GRANT, the server determines the necessary modifications to the grant tables and makes the changes necessary. When an account-management statement is issued, the server automatically reloads the in-memory contents of the grant tables. If the tables are modified directly with a statement such as INSERT or DELETE, the server must be told explicitly to reload the tables afterward by using a FLUSH PRIVILEGES statement or a mysqladmin flush-privileges command.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-14

Developing Dynamic Web Applications with MySQL and PHP


277

Chapter 15- Securing PHP and MySQL

15.6.4

The GRANT Statement The syntax for the GRANT statement includes several sections. In simplest form, the following are specified: The privileges to be granted What the privileges apply to The account that should be given the privileges

A password As an example, the following statement grants the SELECT privilege for all tables in the world database to a user named jim, who must connect from the local host and use a password of Abc123: GRANT SELECT ON world.* TO 'jim'@'localhost' IDENTIFIED BY 'Abc123'; If the account does not already exist, GRANT creates it and assigns the designated privileges. If the account does exist, GRANT modifies it by adding the privileges. The parts of the statement have the following effects: The statement begins with the GRANT keyword and one or more privilege names indicating which privileges are to be granted. Privilege names are not case sensitive. To list multiple privileges, separate them by commas. For example, if jim needed to be able to manipulate records in the world database, not just retrieve them, write the GRANT statement like this: GRANT SELECT, INSERT, DELETE, UPDATE ON world.* TO 'jim'@'localhost' IDENTIFIED BY 'Abc123'; The ON clause specifies the level of the granted privileges (how broadly they apply). Privileges can be granted globally or for a specific database, table, or stored routine. The ON syntax for these levels is as follows: ON *.* ON db_name.* ON db_name.table_name ON db_name.routine_name For the formats that begin with db_name., it's allowable to omit the database name qualifier and specify just *, table_name, or routine_name. In these cases, the privileges are granted to all tables in the current database or to the named table or routine in the current database. Be sure that to verify the current database is the correct one, to avoid granting privileges to tables or routines in the incorrect database. The TO clause specifies the account to be granted the privileges. An account name consists of a username and the name of the client host from which the user must connect to the server. The account name is given in 'user_name'@'host_name' format. Note that the user and host parts of account names should be quoted separately. Quotes actually are necessary only for values that contain special characters such as dashes. If a value is legal as an unquoted identifier, the quotes are optional.

278

The IDENTIFIED BY clause is optional. If present, it assigns a password to the account. If the account already exists and IDENTIFIED BY is given, the password replaces any old one. If the account exists but IDENTIFIED BY is omitted from the GRANT statement, the account's current password remains unchanged. If an account has no password, clients can use it to connect to the server without a password! As a security measure, GRANT statements can prevented from creating new accounts unless an IDENTIFIED BY clause is given by enabling the NO_AUTO_CREATE_USER SQL mode. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-15

Developing Dynamic Web Applications with MySQL and PHP


279

Chapter 15- Securing PHP and MySQL

280

15.6.5

If it is necessary to give an account the capability to grant its privileges to other accounts, add a WITH GRANT OPTION clause to the statement. For example, if it is necessary for jim to have read access to the world database and to be able to create other users that have read access to that database, use this statement: GRANT SELECT ON world.* TO 'jim'@'localhost' IDENTIFIED BY 'Abc123' WITH GRANT OPTION; The SHOW GRANT Statement To find out what privileges a particular account has, use the SHOW GRANTS statement. It displays the GRANT statements that would be required to set up the account. To see the privileges assigned to the current user, use SHOW GRANTS without an account name or with CURRENT_USER(): SHOW GRANTS; SHOW GRANTS FOR CURRENT_USER(); To see the privileges for a specific account, specify that account name in the statement. It is not possible to see the privileges for other accounts unless the user has the SELECT privilege for the mysql database. Suppose that an account has been set up for a user jen who connects from the host myhost.example.com. To see this account's privileges, use the following statement:
mysql> SHOW GRANTS FOR 'jen'@'myhost.example.com'; +----------------------------------------------------------------+ | Grants for jen@myhost.example.com | +----------------------------------------------------------------+ | GRANT FILE ON *.* TO 'jen'@'myhost.example.com' | | GRANT SELECT ON `mydb`.* TO 'jen'@'myhost.example.com' | | GRANT UPDATE ON `test`.`mytable` TO 'jen'@'myhost.example.com' | +----------------------------------------------------------------+

The output displayed here by SHOW GRANTS consists of three GRANT statements. Their ON clauses indicate that jen has privileges at the global, database, and table levels, respectively. If the account has a password, SHOW GRANTS displays an IDENTIFIED BY PASSWORD clause, at the end of the GRANT statement which lists the account's global privileges. (The word PASSWORD after IDENTIFIED BY indicates that the password value shown is the encrypted value stored in the user table, not the actual password.) If the account can grant some or all of its privileges to other accounts, SHOW GRANTS displays WITH GRANT OPTION at the end of each GRANT statement to which it applies. SHOW GRANTS displays privileges only for the exact account specified in the statement. For example, the preceding SHOW GRANTS statement shows privileges only for jen@myhost.example.com, not for jen@%.example.com, jen@%.com, or jen@%.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-16

Developing Dynamic Web Applications with MySQL and PHP

Chapter 15- Securing PHP and MySQL

Lab 15-A
In this exercise you will create, grant privileges to and verify new users for the world database.

ACTION (You Do) 1. In the mysql client, show the grants set for the root on the localhost: SHOW GRANTS; 2. Create a student account at hostname example.com: CREATE USER 'student'@'example.com'; 3. Verify the new user: SELECT user, host, password FROM mysql.user WHERE user='student';

COMPUTER RESPONSE / Comments The grants for root@localhost shows that ALL privileges have been granted. The new user student is created and the result is OK.

There now exists an anonymous (unnamed) user; +---------+-------------+----------+ | user | host | password | +---------+-------------+----------+ | student | example.com | | +---------+-------------+----------+ The grants for student@example.com shows privileges set as GRANT USAGE ON for the current database of world. The privileges have been set and result is OK.

4. Show the grants set for the student on the example.com host: SHOW GRANTS for 'student'@'example.com'; 5. Grants the SELECT, INSERT, DELETE and UPDATE privileges to the student on the example.com host and password set to student_pass: mysql> GRANT SELECT, INSERT, DELETE, UPDATE ON world.* -> TO 'student'@'example.com' IDENTIFIED BY 'student_pass'; 6. Show the grants set for the student on the example.com host: SHOW GRANTS for 'student'@'example.com';

The new grants for student@example.com shows privileges set as GRANT USAGE ON as well as the newly added privileges of SELECT, INSERT, DELETE and UPDATE.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-17

Developing Dynamic Web Applications with MySQL and PHP


281

Chapter 15- Securing PHP and MySQL

15.6.6

Revoking Privileges Use the REVOKE statement to revoke privileges from an account. Its syntax has the following sections: The keyword REVOKE followed by the list of privileges to be revoked An ON clause indicating the level at which privileges are to be revoked A FROM clause that specifies the account name

Suppose that jim on the local host has SELECT, DELETE, INSERT, and UPDATE privileges on the world database, but it is necessary to change the account so that they have SELECT access only. To do this, revoke those privileges that allow the user to make changes:
REVOKE DELETE, INSERT, UPDATE ON world.* FROM 'jim'@'localhost';

To revoke all privileges held by an account at any level, REVOKE supports a special syntax (note that this form of REVOKE has no ON clause):
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'james'@'localhost';

To determine what REVOKE statements are needed to revoke an account's privileges, SHOW GRANTS might be helpful. Consider again the output from SHOW GRANTS for the jen@localhost account:
mysql> SHOW GRANTS FOR 'jen'@'myhost.example.com'; +----------------------------------------------------------------+ | Grants for jen@myhost.example.com | +----------------------------------------------------------------+ | GRANT FILE ON *.* TO 'jen'@'myhost.example.com' | | GRANT SELECT ON `mydb`.* TO 'jen'@'myhost.example.com' | | GRANT UPDATE ON `test`.`mytable` TO 'jen'@'myhost.example.com' | +----------------------------------------------------------------+

This output indicates that the account has global, database-level, and table-level privileges. To remove some or all of these privileges, convert the GRANT statements to the corresponding REVOKE statements. The privilege names, privilege levels, and account name must be the same as displayed by SHOW GRANTS. For example, to revoke the global FILE privilege and the table-level privilege for test.mytable, issue these statements:
mysql> REVOKE FILE ON *.* FROM 'jen'@'myhost.example.com'; mysql> REVOKE UPDATE ON test.mytable FROM 'jen'@'myhost.example.com';

After issuing the REVOKE statements, SHOW GRANTS produces this result:
mysql> SHOW GRANTS FOR 'jen'@'myhost.example.com'; +--------------------------------------------------------+ | Grants for jen@myhost.example.com | +--------------------------------------------------------+ | GRANT USAGE ON *.* TO 'jen'@'myhost.example.com' | | GRANT SELECT ON `mydb`.* TO 'jen'@'myhost.example.com' | +--------------------------------------------------------+

If REVOKE is used to remove all the privileges enabled by a record in the db, tables_priv, columns_priv, or procs_priv tables, REVOKE removes the record entirely. However, REVOKE does not remove an account's user table record, even if all privileges for the account are revoked. This means that although the account no longer has any privileges, it still exists and thus can be used to connect to the server. Use the DROP USER statement instead. After that, the account no longer exists and cannot be used to connect to the server.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-18

Developing Dynamic Web Applications with MySQL and PHP


282

Chapter 15- Securing PHP and MySQL

15.6.7

Changing Account Passwords A password can be specified for an account by including an IDENTIFIED BY clause in a CREATE USER or GRANT statement. For GRANT, the clause assigns the initial password or changes the current password, depending on whether the account is new or already exists. To change an existing account's password without changing any of its privileges, a grant statement may be used. Use GRANT with the USAGE privilege specifier at the global level and an IDENTIFIED BY clause: GRANT USAGE ON *.* TO 'jim'@'localhost' IDENTIFIED BY 'NewPass'; USAGE means no privileges, so the statement changes the password without granting any privileges. Note that with SET PASSWORD, the PASSWORD() function is used to encrypt the password, whereas with GRANT it is not necessary.

15.6.8

When Privilege Changes Take Effect When the grant tables are changed with an account-management statement, the effects of changes apply to existing client connections as follows: Table and column privilege changes apply to all statements issued after the changes are made. Database privilege changes apply with the next USE statement. Changes to global privileges and passwords do not apply to a connected client. They apply the next time the client attempts to connect.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-19

Developing Dynamic Web Applications with MySQL and PHP

Chapter 15- Securing PHP and MySQL

Lab 15-B
In this exercise you will create, drop and verify new users for the world database.

ACTION (You Do) 1. Show the grants set for the student on the example.com host: SHOW GRANTS for 'student'@'example.com';

COMPUTER RESPONSE / Comments The grants for student@example.com shows privileges set as GRANT USAGE ON for the current database of world.

2. Revoke the DELETE and UPDATE privileges The privileges have been revoked and result is OK. currently given to the student on the example.com host: mysql> REVOKE DELETE, UPDATE ON world.* FROM 'student'@'example.com'; 3. Show the grants set for the student on the example.com host: SHOW GRANTS for 'student'@'example.com'; The updated grants for student@example.com shows privileges set as GRANT USAGE ON as well as the newly changes privileges; ... GRANT SELECT, INSERT ON `world`.* TO 'student'@'example.com' 4. Change the password for the student on the example.com host to NewPass: mysql> GRANT USAGE ON *.* TO 'student'@'example.com' IDENTIFIED BY 'NewPass'; 5. Show the grants set for the student on the example.com host: SHOW GRANTS for 'student'@'example.com'; 6. Drop the student user account: DROP USER 'student'@'example.com'; The updated grants for student@example.com shows privileges set as GRANT USAGE ON as well as the newly changes privileges GRANT ALL PRIVILEGES. The student account is removed and the result is OK. The password has been changed and result is OK.

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-20

Developing Dynamic Web Applications with MySQL and PHP


283

Chapter 15- Securing PHP and MySQL

15.7 Chapter Summary


In this chapter, you have learned to: Explain PHP's Configuration Parameters that Support Securing an Application The first step in any process of securing an application is checking the configuration components that the software is running under. Some configuration options are crucial to the running of the software, while others can be shut down based on the needs of the applications that will run on the software. Data encryption is the process of scrambling stored or transmitted information so that it is unintelligible until it is unscrambled by the intended recipient. The intended recipient can then decode (or decrypt) the information. PHP offers multiple means to make this happen. However, none of these solutions are very effective without the applications running on secure servers and connections. MySQL Server, or mysqld, is the database server program. The server manages access to the actual databases on disk and in memory. MySQL Server is multi-threaded and supports many simultaneous client connections. Clients can connect via several connection protocols. A MySQL account is defined in terms of a username and the client host(s) from which the user can connect to the server. The account also has a password. Therefore, when a user connects to the server, it checks not only the username that you specify, but also what host their connecting from and if their password authorizes a connection and action.

Utilize PHP's Encryption Functions

Secure the mysqld daemon

Describe the MySQL Access Privilege System

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 15-21

Developing Dynamic Web Applications with MySQL and PHP

284

CHAPTER 16
285

CONCLUSION

Developing Dynamic Web Applications with MySQL and PHP

Chapter 16 - Conclusion

16 CONCLUSION
16.1 Course Objectives
This course provided developers with the development skills to use PHP and MySQL as a cohesive platform for the development of complex dynamic web applications. Upon completion of this course you should now be able to:
286

Verify the correct installation of the LAMP Components Utilize the basic components of PHP to build a foundation for more complex web applications Understand the basic components of MySQL to build a foundation for the development of fully dynamic and database-driven sites Manage databases within MySQL Manage Tables within MySQL Utilize SQL query commands to retrieve data from the MySQL Database Utilize SQL expressions Manipulate table data using the SQL Data Manipulation Language (DML) commands Retrieve data from multiple MySQL tables using Joins

287

Create web based forms that interact with the end user and the data within MySQL Utilize session handling within PHP to track user-specific behavior and preferences. Utilize error and exception handling in PHP to detect, log and report issues that may arise during program execution Integrate PHP's object oriented programming (OOP) functionality into the design of web applications Authenticate user identities utilizing PHP built-in authentication capabilities and MySQL's user and privilege management capabilities Securing PHP and MySQL to improve the integrity of the application and subsequent data Describe the MySQL client/server architecture

Instructor Notes: Just quickly go over the list (paraphrased on the slides) to review the information covered in the class. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 16-1

Developing Dynamic Web Applications with MySQL and PHP


288

Chapter 16 - Conclusion

16.2 Training and Certification Website


View the course catalog, schedule, certification program information, venue information (and more) on the Training and Certification website: http://www.mysql.com/training/ .
24H

Topic Menu

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 16-2

Developing Dynamic Web Applications with MySQL and PHP

Chapter 16 - Conclusion

Overview The home page for Training information. Links to all other training information. Certification Description of current certification program. Links to exam registration and more information. Curriculum Paths The categories and order in which training courses should be taken. Catalog Comprehensive course catalog. Links to more information on courses. Schedule Schedule of courses, listed by title. Links to course registration and more information. Delivery Options The available options for training delivery. Savings and Promotions Information about training bundles and credits. Training Bundles Available bundles and pricing. Training Partners List and links of MySQL training partners. Testimonials Training endorsements. FAQ Frequently asked questions and links to more other training information. Additional training information, including Articles, White Papers and Web Seminars, can be found on the Community web page: http://dev.mysql.com/ .
1

Instructor Notes: Just a reminder of where they can go for more information. Go through the brief descriptions of each training menu link. You may want to ask students if there is anything in particular that they want to know how to find on the training and/or main web site. ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 16-3

Developing Dynamic Web Applications with MySQL and PHP


289

Chapter 16 - Conclusion

16.3 Course Evaluation


We Need Your Evaluation! Please take the time to complete a course evaluation to let us know about your experience. We are continuously making improvements to our courses and our overall training program. And we count on the feedback of our students to assist in making the right choices. Please follow the instructions given by your instructor regarding completion of the evaluation form.

Thank you in advance for taking the time to give us your opinions!

Instructor Notes: Using the URL on the slide, have students fill out an online evaluation, using the code assigned to this specific class (see information on MySQL Training TI, or as ______________________________________________________________________________________________ emailed by MySQL coordination group). The URL is on the slide: http://www.mysql.com/training/evaluation.php. ______________________________________________________________________________________________
______________________________________________________________________________________________ ______________________________________________________________________________________________ course, as their input will help to improve future revisions of this courseware. **

** Make sure to tell students that previous course gave input to assist in improving this

Page 16-4

Developing Dynamic Web Applications with MySQL and PHP


290

Chapter 16 - Conclusion

16.4 THANK YOU!


We appreciate your attendance at this course. Congratulations on your completion. We hope that your training needs regarding this course topic have been fully met. Dont hesitate to contact us, if you have any training questions: Website: http://www.mysql.com/training/
1

Email: training@mysql.com
1

Phone: USA Toll Free: 1-866-697-7522 Worldwide: 1-208-514-4780

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 16-5

Developing Dynamic Web Applications with MySQL and PHP


291

Chapter 16 - Conclusion

16.5 Q&A Session


If you have more questions after the class, get answers from the MySQL Reference Manual FAQ page: http://dev.mysql.com/doc/refman/5.1/en/faqs.html . And if you would like to work on the exercises after completing this course, you may download the world database (which was used throughout the course) from the Documentation pag of our website: http://dev.mysql.com/doc . You may record any questions and answers that are shared at this point in the class, in the space provided below. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________

______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________ ______________________________________________________________________________________________

Page 16-6

Developing Dynamic Web Applications with MySQL and PHP

APPENDIX A INTRODUCTION TO LINUX

Developing Dynamic Web Applications with MySQL and PHP

Appendix A - Introduction to Linux

This appendix is intended as a quick introduction to the Linux operating system. The purpose is to allow individuals not familiar with Linux or the Linux command line the ability to navigate and create files, view directories. This document was created as part of the classes offered by MySQL so it is biased towards commands that we use in our classes. Windows in Linux? This document assumes that the Linux version being used is the most recent and that a graphical environment has been installed. The basic system for a graphical environment in Linux is X-Windows. X-windows or X-Free-86 is the Linux graphical user interface (GUI) and provides the basic framework for utilizing the Linux operating system. Running within X is a window manager or a more complete environment known as a desktop. The most common desktops are Gnome or Kde. There are other lightweight window manager's that run within X. Even though Linux offers a windows like environment, Linux is centered around the command line and will be the topic of major discussion in this document.

The Basics
Getting to the command line When Linux starts up it may launch a GUI interface but it will also launch a command line interface. If you start with the GUI then a command line can be obtained in one of the following ways: CTRL-ALT-F1 CTRL-ALT-F2 CTRL-ALT-F3 CTRL-ALT-F4 CTRL-ALT-F5 CTRL-ALT-F6 CTRL-ALT-F7 (BACK TO THE GUI) Starting X-Windows from a command line If the operating system starts up without loading the X-Windows environment (the display only showing the command line), or there is a need to have multiple windows environments, the X-Windows GUI can be loaded by entering one of the following ways: startx o When this command is entered on the command line it will start up the X-Windows server and display the default windows manager. startx --:# o When startx is executed without any parameters, it is actually starting the server with startx --:0. This identifies that it is loaded in display 0. Additional X-Windows servers can be loaded by executing the startx command with other display identifiers being passed through the parameter (eg. startx --:1 would create a second X-Windows server and supporting GUI). Several GUI terminals can be running concurrently with the following commands allowing switching between the environments: CTRL-ALT-F7 CTRL-ALT-F8 Getting to the command line from the GUI In most Linux distributions a command line or terminal is available in the windows manager as an application. In most operating system it is under APPLICATIONS => ACCESSORIES => TERMINAL. The Terminal application can be added to the "Start bar" by simply dragging the icon to the "Start panel" in most operating systems.

Page A-1

Developing Dynamic Web Applications with MySQL and PHP

Appendix A - Introduction to Linux

General Linux Notes Linux is CaSe-SeNsItIvE which is different from a Windows environment. Dog.txt, DOG.txt and doG.txt would be considered three different file names in Linux, where in Windows they would all be seen as one file. Three are other specific file name differences that must be taken into account when using Linux: Filenames can be up to 256 characters long and can contain letters, numbers, "." (dot), "_" (underscore), "-" (dash), for obvious reasons (spaces) should be avoided. If a file starts with a . it will be hidden. It will not usually show up in the ls or dir command (discussed in detail later in this appendix). Using ls -a will show hidden files. / is more or less equivalent to a Microsoft DOS \. The difference is that there is only one directory tree in Linux and it spans all disks. In Microsoft Windows there is one tree per disk. The Linux file system hierarchy is independent of the disks. Filenames can be up to 256 characters long and can contain letters, numbers, "." (dot), "_" (underscore), "-" (dash), for obvious reasons (spaces) should be avoided. In most files and programs (eg. the MySQL configuration file /etc/my.cnf), a line starting with a # is a comment. Assorted non-command features In Linux there are many time-saving features that are not available in most window like environments. The following is a listing of some of the most useful features: ALL commands available o Press <Tab> to see the listing of all available commands in the path selected. TAB completion o <TAB> in a text terminal will autocomplete the command if there is only one option. For example ls /usr/local/my<TAB> will return ls /usr/local/mysql thus completing the only possible command that fit what was typed in. Simply hitting enter allows the command, in this case loading the mysql client, to execute. Command history o <ARROWUP> will scroll through approximately the last 1000 commands that were executed (from the most recent on). The command displayed can be reexecuted by simply pressing the <ENTER> or <RETURN> key; however, it can also be altered and then executed with the new changes. Scroll through multiple page output o When the contents of the terminal window exceed the display size, using the scroll bar can move the display up and down through the contents. However, there is also keyboard commands that can accomplish this task also: <SHIFT><PgUp> and <SHIFT><PgDN>. Screen resolution in the GUI o The resolution of the screen can be changed using the following keyboard commands: <CTRL><ALT><+> - Increases the resolution (eg. 800x600 => 1024x768). <CTRL><ALT><-> - Decreases the resolution (eg. 1024x768 => 800x600). Note: In X-Windows it may be necessary to add the resolution setting sizes to the X-Windows configuration file (eg. /etc/X11/XF86Config). The first resolution size identified will be the default setting when X-Windows starts and the other settings will be used when the <CTRL><ALT><+> and <CTRL><ALT><-> keys are used. If the entries are not in normal resolution order (eg. "1024x767", "800x600", "640x480", etc.), then these keys may not necessarily increase or decrease as expected (it moves up and down through the list of resolutions not evaluating if it is smaller or larger than the resolution being used).

Page A-2

Developing Dynamic Web Applications with MySQL and PHP

Appendix A - Introduction to Linux

Terminating the GUI environment o There are times when it is not possible to terminate an X-Windows environment using proper procedures. In the event that this happens, the X-Windows environment can be "killed" by using either of the following key combinations: <CTRL><ALT><BACKSPACE> - This should terminate the X-Windows server and provide a command prompt. <CTRL><ALT><DELETE> - The majority of Linux environments will catch this and reboot the system. Terminating a running application o In addition to times when an X-Windows environment will not terminate properly, applications running within the X-Windows environment can also fail to terminate properly. To terminate the unresponsive application use the following key combinations: <CTRL><c>. This will send a KILL signal to the current process. Close a Terminal window o To terminate the current Terminal window use the following key combinations: <CTRL><d>. This sends an [End-of-File] to current open application. Caution: If this key combination is pressed twice, the system will log out the current user. Stopping and resuming transfers o If a terminal mysteriously stops responding, it may be in the process of receiving or sending actions. In this case, it is possible to stop a transfer being received by the terminal by pressing the following key combination: <CTRL><s>. The transfer can also be resumed by pressing the following key combinations: <CTRL><q>. Placing current process in the background o There are times when the current running application does not need to be monitored by the end user or no additional interaction is required by the end user, but the application still needs to be executing. Rather than starting another terminal window, the following key combination places the application execution in the background: <CTRL><z>.

Using the command line


In Linux there are distinct differences from other operating systems (such as Microsoft Windows) that must be understood to reduce frustration when attempting to execute applications. The first such difference is the fact that Linux is a file system with a single tree like structure that starts at "/". This type of file system supports what is known as absolute or relative file or directory references. Absolute path - This type of path is a full path that identifies the actual location of the file or directory being called without giving any thought to the current directory being used. This can be useful when it is necessary to start an application in a directory that the executables are not located in. By calling the executable full path (eg. /usr/local/mysql), from within another directory (eg. /tmp), any external dealings from within the application will take place in the directory started (unless otherwise identified by the application itself). Relative path - This type of path identification allows for application that are located within the current directory to be executed without having to identify the exact path (eg. executing mysql within the /usr/local directory). The operating system actually appends the current directory to the file name being executed (invisble to the end user). In addition, Linux also allows for user identified paths (or commands) to be relative no matter where they are executed from (such as many of the traditional applications like help which is located in a common operating system executables directory).

Time-saving features When using the command line there are many time-saving features that can be used to minimize the amount of typing that is needed. The following is a recap (or full description) of the most useful: TAB completion - <TAB> in a text terminal will autocomplete the command if there is only one option. Wildcards - Wildcards can subsituted for file names. The most common wildcard is *. By issuing the following command (with a wild card):, the entire contents of the directory are displayed (including all subdirectories and there contents):

Page A-3

Developing Dynamic Web Applications with MySQL and PHP

Appendix A - Introduction to Linux

ls /usr/local/* Shortcuts - In Linux there are multiple characters that assist in minimizing the amount of typing necessary. The following are the most common: o ~ (tilde) - This character is short for the current users home directory (most likely /home/username). If the following was entered: cd ~/my_dir, the operating system would go to the /home/username/my_dir directory. The command cd alone is equivalent to typing cd ~. o . (dot) - This character refers to the current directory. Sometimes this is necessary to execute applications located with the current directory. The following: ./my_program will attempt to execute the application my_program in the current working directory. o .. (two dots) - These characters (when used consecutively) will reference the parent directory to the current working directory. The following: cd .. when executed in the /usr/local directory will make the /usr directory the current working directory. o & (ampersand) - This character when placed following the application name (including a space between the application and ampersand) will run the application in the background. Common commands There are some commands that are absolutely necessary to know (or at least understand) when using the Linux command line. The following is a large number of these commands to include those that are most useful in this training along with some general need-to-know commands: Getting around - The first steps of learning Linux is learning how to get around. The following is a recap (or full description) of these commands: o ls - Under Linux, the command "dir" is an alias to ls and lists the contents of either the current directory (when executed without any parameters) or the contents identified by the parameters entered. The following is a feature of the ls command that is useful to know: ls -al|more - This can be used when the output flows off of the screen. The -al parameter identifies to list all the files (including hidden files). The |more command pauses the display after each screenful. o cd - This command is an acronym for "change directory". When followed by a directory name, that directory will become the active working directory. cd when used by itself is equivalent to cd ~ which changes the working directory to the users home directory. o pwd - This command is an acronym for "print working directory" and displays the current working directory. File management - The process of managing directories and files (copying, moving, renaming, etc.) is a crucial skill to understand in any operating system. The following is a listing of the most common Linux commands associated with managing files: o cp [source] [destination] - This command when used with parameters for the source file and the destination location will copy the source file to the destination location. For example cp /usr/local/mysql/support-files/my-large.cnf /etc/my.cnf would not only copy the file my-large.cnf to the /etc directory but also rename it to my.cnf. As stated earlier, to . (dot) character can be used as the destination to tell the operating system to copy the file to the current location. Recursive copy (-r) - When the cp command is executed with the -r parameter, the contents of the whole directory will be copied to the destination. For example, cp -r ~ /backup/username/. will copy all files (and directories) from the current users home directory to the /backup/username directory. o mv [source] [destination] - This command is similar to the cp command, except it will remove the file from the source location and place it in the new destination. This command can also be used to rename a file in the same directory by identifying the original name in the source and the new name in the destination.

Page A-4

Developing Dynamic Web Applications with MySQL and PHP o

Appendix A - Introduction to Linux

ln [source] [destination] - This command when used with parameters for the source file and the destination location will create a link (identified by the destination parameter) to the source parameter. There are two types of links that can created: Hard link - This type of link appears as a copy of the original files, but in reality only one copy of the file is kept, just two (or more) directory entries point to it. Any changes made to the file are automatically visible throughout. When one directory entry is removed, the other(s) stay(s) intact. Files that are hard linked have to be on the same file system. In addition, hard links to directories or special files are impossible. Soft links - Adding a -s prior to the source file name creates a symbolic (soft) link. The symbolic link just specifies a path where to look for the file. In contrast to hard links, the source and destination don't not have to be on the same file system. If the original file is removed, the link is "broken". In addition, symbolic links can also create circular references (like circular references in spreadsheets or databases, e.g., "a" points to "b" and "b" points back to "a"). o rm filename - This command will delete the file that is identified by the filename parameter. The user attempting to delete the file(s) must also be the owners of those files (with the exception of superusers). Most versions of the Linux operating systems will prompt the user verifying that they wish to delete the files. However, the user can force the deletion without this prompt by adding the -f option. Deleting large number of files - Using the rm command with wildcards can delete large number of files in a single command (eg. rm -f * will remove all files in the current working directory, no questions asked). Removing directories (rmdir) - Using the rmdir command, followed by the directory name, will delete empty directories. Removing directories and files - Using the -r option with the rm command will perform a recursive delete which will remove files, directories and their subdirectories. This of course can be a very useful command but can also be a very dangerous command (especially a user who has super privileges). The following is an example of how this can be used: rm -rf /usr/local/apache In this example, the /usr/local/apache directory (along with all the files and subdirectories it contains) will be removed from the system. The -f option is almost a necessity, otherwise, the end user would have to verify each deletion that takes place. There is no undo for this action. o mkdir directoryname - This command will create a subdirectory (identified by the directoryname parameter) in the current directory (unless an absolute path is used). This command will produce an error if the user creating the subdirectory does not have the required privilege or the directory name is already being used in the directory (either the working directory or the absolute path directory, if used). Viewing and editing files - The following is a listing of the most common Linux commands associated with viewing and editing files: o cat filename |more- This command will display the contents of the filename to the screen. If the file is a text-based file, then that which is displayed will most likely be readable. However, if the file is an application or other binary type file, the display will be unreadable and most likely cause havoc with the operating systems attempting to display it. The contents will be displayed with no pause unless the parameters |more are used. With the |more combination, the display is paused after every screenful is displayed. Note: Use the command reset after displaying a binary file to ensure that the character set displays the proper default character set. Other commands that are similar to the cat command: more filename - This command, which has been used as a parameter with other commands, can be used to scroll through the content of a file. less filename - This command is roughly equivalent to more but can be more convenient to use. Press the <q> key to terminate the command.

Page A-5

Developing Dynamic Web Applications with MySQL and PHP o

Appendix A - Introduction to Linux

vi filename - This command provides simple and standard text editing capabilities. There is a separate appendix that describes how to use the vi text editor. There are other text editors to choose from. The following is a list of the most common: emacs filename - This command utilizes the emacs text editor to display and manipulate text files. kwrite filename - This command utilizes the kwrite text editor to display and manipulate text files. nedit filename - This command utilizes the nedit text editor to display and manipulate text files. vim filename - This command utilizes the vim text editor to display and manipulate text files. o <Middle mouse button> - This hardware interface tells Linux to paste the text which is currently highlighted somewhere else. This is the normal "copy-paste" operation in Linux. o touch filename - This command will alter the date/time stamp of the file filename to the current time for files that exist. If a file does not exist with the identified filename, the operating system will create an empty file with that name. Finding files - The following commands provides the means in which the operating system searches for files versus the end user having to search each directory individually for a file or files: o find / -name "filename" - This command is used to find the file called "filename" on the file system starting the search from the root directory "/". The "filename" may contain wildcards (*,?). o locate filename - This command is used to find the file name of which contains the string "filename". This command is easier and faster than the find command but depends on a database that normally rebuilds at night. Getting help With the large number of commands offered by the Linux operating system, it is difficult to remember the syntax and/or parameters to perform the command action. This is where having a built-in manual for the majority of commands is helpful. The following are the most common ways to access the help features of Linux: commandname --help |more - These parameters used with most commands will display a brief help on a command. "--help" works similar to DOS "/h" switch. The "more" pipe is needed if the output is longer than one screen. help commandname is the equivalent to using the --help parameter. man commandname - The man command, followed by the commandname, displays the contents of the system manual pages (help) on the topic. Press "q" to quit the viewer. The command info commandname works similar to the man command but may contain more up-to-date information. For the majority of commands, the manual pages are hard to read and understand, it is advisable to use the commandname --help parameter first. If that does not answer the question being asked, then look in the /usr/doc directory for the specific command verbage file. To display a manual page from a specific section, add a section number between the man command and the commandname queried (eg. man 3 exit displays an info on the command exit from section 3 of the manual pages). apropos commandname - This command will provide a list of commands associated with the commandname entered.

Page A-6

Developing Dynamic Web Applications with MySQL and PHP Shutting Down

Appendix A - Introduction to Linux

Terminating the operating system is similar to Microsoft Windows when using the Linux GUI; however, to terminate the application from the command line the following commands can be used: exit - This command logs the user out of the current shell that is running. If there is only one Linux shell running, the operating system will be shutdown. shutdown -h now - This command, when used by the root user, will shut down the system to a halt. halt - This command, when used by the root user, will halt the machine. This command can be very useful on remote shutdown. reboot - This command, when used by the root user, will reboot the machine. This command can be very useful when managing a remote server. reset - This command can be used to rescue a window that has been frozen or messed up (usually trying to display a binary file with a command such as cat). The end user may not be able to see the typing of the command; however, continuing to type the command followed by the enter key should produce the desired result of reseting the operating system.

Obtaining system information


Collecting and reviewing system information can be an important aspect for system administrators and end users alike. System information can include everything from determining the name of the computer that is being used to determining if the computer can connect to the internet or to another machine on the network. The following are the most common commands that can be used to obtain system information: hostname - This command displays the name of the local host (the machine that the end user is connecting to). To alter the name of the local host, a user with root privileges can use the netconf command. ifconfig - This command (for root users) displays information about the network connection that the local host is using. The ethernet address for the local host will show up under eth0. Non-root users can use /sbin/ifconfig to display this information. ping ipaddress - This command sends an echo request (via packets) to the ipaddress (or computer name) identified looking for a response. Ping will provide not only information determining if the computer can be seen by the local host but alos how long the response took. time commandname - This command, when used with another command, will display how long the other command took to complete. This command should not be confused with the date command (which provides the current date and time according to the local host being accessed). ps - This command displays the current processes that the end user is running. The command ps axu | more displays additional information to includes the name of the user that owns each process. Many users use this command to find the process id (PID) of an application they wish to terminate. Once the end user has obtained the PID of an application to terminate, the following commands can be used: o kill PID - This command shuts down the application associated with the PID. If an application does not terminate with this command, the end user can append the kill command with a -9 argument. This argument tells the system to kill the process (no matter what) without determining if it will affect any other applications running. This argument should be used only as a last resort. o killall program_name - This command is similar to the kill PID command, except it uses the program name as an argument. This of course could cause problems if the end user is running two applications with the same name. The kill PID command is the better choice of the two. top - This command displays the current running processes, sorted by cpu usage (top users first). This command continues to run until the end user terminates the command. history | more - This command will display the last 1000 commands (or approximately 1000 commands) that have been issued by the end user. uptime - This command displays how long the local host has been running since the last reboot. uname -a - This command provides basic information currently available from the system. free - This command provides information about unused and used memory and swap space on the local host. Page A-7

Developing Dynamic Web Applications with MySQL and PHP

Appendix A - Introduction to Linux

df -h - This command will display the amount of disk space (including free disk space) for the file systems on the local host. The -h argument tell the df command to display the information in "human readable" form. du / -bh | more - This command displays detailed disk usage (thus the command name being du) for each subdirectory starting at the file system root (/). The -bh works together to display the information in "human readable" form. env - This command displays information about the current user environment. echo $PATH - This command displays a specific component of the current user environment called PATH (which displays the directories whose command can be executed without having to be in that specific directory).

Accessing a system remotely


There are times when it is necessary to access another physical system remotely from the system that the end user is currently using. The following commands are the most common used to accomplish remote access: ssh -1 username IPaddress - This command provides a secure shell login to a remote machine. The -l parameter specifies the user to log in as on the remote machine. The following is an example of Joe Smith (username: jsmith) logging into a remote machine securely located at the IP address of 192.168.0.1: ssh -l jsmith 192.168.0.1 scp source_filename username@IPaddress:destination_filename - This command (which is short for secure copy protocol) provides the means to copy files from the localhost to a remote machine. In addition, the end user can copy files from one remote machine to another remote machine by providing the required information in the source_filename parameter. The following is an example of Joe Smith (username: jsmith) copying the file My_file.txt from his local host to a remote machine securely located at the IP address of 192.168.0.1: scp My_file.txt jsmith@192.168.0.1:My_file.txt

File compression/decompression
Many files can be reduced in file size by compressing their contents. In addition, many file compression activities include combining multiple files (especially their directory structure) into one file for easily passing along to others or simply moving contents from one machine to another. The following commands are the most common commands used in Linux to handle the compression and decompression of files: tar -cvf file_name.tar filename(s)/directory - This command will bundle a bunch of files together and creates an archive file (tar = tape archive) in the location it was run (or identified by) in. This command does not provide compression, but simply puts multiple files together into one file name. The -cvf parameters tell the program to create (c) a new archive, display a verbose (v) output to the end user with a user defined file name (f) provided. The original files remain intact and the new archive file is created. The following is an example of creating a compressed tar file (or affectionately called a "tar ball" by most Linux users) that creates a single archive file called My_Documents.tar of all files and subdirectories of the My_Documents files in the end users home directory: tar -cvf My_Documents.tar ~/My_Documents/ gzip file_name.tar - This command is used to compress files (in most cases files that have been tar'd) using the Lempel-Ziv coding (LZ77) method. The original file is replaced with a new file with the same file name but an extended identifier that includes the characters (.gz) creating a file that is file_name.tar.gz. Sometimes these files will be shortened even further by other users to have an extension of only .tgz. tar -zxvf file_name.tar.gz - This command will separate and decompress files that have been tar'd and zipped using the tar and gzip commands. The -zxvf parameters tell the program to compress or decompress files automatically (z), extract (x) the contents of the archive, display a verbose (v) output to the end user with a user defined file name (f) provided. The following is an example of decompressing a compressed tar file that extracts the My_Documents directory to the root directory (~/)of the end user: ~/tar -zxvf My_Documents.tar.gz Page A-8

Developing Dynamic Web Applications with MySQL and PHP

Appendix A - Introduction to Linux

gunzip file_name.tar.gz - This command decompresses files that have been compressed with gzip. This command is useful with files that are tar'd and zipped if the end user only wants the archive file without having it untar'd in the process. bzip2 file_name - (bzip = big zip) This command compresses a file (identified by the file_name parameter) using the Burrows-Wheeler block sorting text compression algorithm, and Huffman coding. This type of compression is generally considered better than that achieved by the gunzip command which uses the Lempel-Ziv coding (LZ77) method. The original file is deleted and a new compressed file is created with the original name of the file but a new extension to identify it is zipped with bzip (*.bz2). The following are two examples of compressing files with bzip2. The first is a standard bzip action, while the second show hows to compress mutliple files into one bzipped file: bzip2 My_file.txt bzip2 My_file.txt His_file.txt Her_file.txt > Our_files.bz2 bunzip2 file_name.bz2 - This command decompresses files that have been compressed with bzip2. The Bzip compression tools are very useful for very large files. unzip file_name.zip - This command decompresses files that have been compressed with the PKZIP command for the Microsoft disk operating system (DOS).

User management
Adding, deleting and otherwise managing access for new and existing users is an important aspect for system administrators and for most users these commands are not going to be required for their day-to-day tasks. However, if these tasks are required for use in the classroom or it will be part of the tasks required of the end user, it is important to understand them. The following commands are the most common commands used in Linux to handle user management: adduser username - This command creates a user (identified by the username parameter) on the local host (or the remote host if being utilized). The useradd username command is equivalent to the adduser command. groupadd groupname - This command creates a new group (identified by the groupname parameter). A group can exist without having any members; however, it is not good user management to have groups without any members. passwd username password- This command changes the password (or adds a password for a new user) for the user identified in the username parameter. If the username parameter is ommited (basically there is only one parameter), the passwd program will change the current users password to the parameter entry. chmod permissions file_name - This command changes the file access permission for the files that the end user has ownership rights to (or all files if end user is root). File permissions are set using three modes: read (r), write (w) and execute (e) which are assigned by the class of users (three classes in all: owner, group and all). The following is an example of a file that has been given access to read, write and execute files for all three user groups: rwxrwxrwx. The permissions can be set using the format shown or using a binary equivalent. For example, to give the owner read, write and execute access while giving the group and all others only read and execute access the end user could enter rwxr-xr-x or 755 (which is equivalent to 111-101-101 in binary notation). chown owner_name file_name - This command changes (or adds) an owner (identified by the owner_name parameter) to a file (identified by the file_name parameter). This command should be run after a file has been copied from another system. chgrp group_name file_name - This command changes (or adds) a group (identified by the group_name parameter) to a file (identified by the file_name parameter). This command should be run after a file has been copied from another system. su username - (su = substitute user) This command allows the end user to log in as another user (such as root). The end user will be required to enter the password for the username that they wish to log into (except for root or another superuser account). Type exit to return the previous login. It is not advisable to habitually work on a machine as root. The root account is for administration purposes only and the su command is to ease access to the administration account when required.

Page A-9

Developing Dynamic Web Applications with MySQL and PHP

Appendix A - Introduction to Linux

Using the RPM package management utility


RPM (Red Hat's Package Manager) is a powerful software manager that can install, remove, query, and verify the software on a system. It is necessary to be the root user to successfully execute the RPM application. The following are some of the common commands associated with using this utility: rpm -ivh filename.rpm - This command installs a RPM package(s) and then provide a detailed output on what was accomplished. The -ivh parameters identify that the package should be installed (-i), provide a verbose (v) output and display hashes (h). rpm -qpi filename.rpm - This command reads the information on the content of the RPM file (identified by filename.rpm) without installing the actual RPM and provides information about the package. The qpi parameters identify that a query (-q) will be performed against a yet to be installed package (p) along with a display of the information (i) that the package contains. The difference between the i parameter (identifying the display of information) used here and the i parameter used in the previous command (identifying that the RPM should be installed) is where the i is located in the list. If the i comes after the dash (-i), it tell the RPM application to install the package. If the i is not the first character after the dash, it tells the RPM package to display the information. rpm -qpl filename.rpm - This command reads the information on the content of the RPM file (identified by filename.rpm) without installing the actual RPM and lists the files that the package contains. The qpl parameters identify that a query (-q) will be performed against a yet to be installed package (p) along with a listing (1) of the files the package contains. rpm -qf filename - This command displays the name of the *.rpm package to which the file filename (on belongs. This is a useful command if the original RPM package is unknown and there is a need to reinstall the application. rpm -e packagename - This command uninstalls the RPM package (identified by the packagename parameter). The packagename is the same name as the original RPM package installed but without the dash and version number (or the .rpm extension).

Page A-10

Developing Dynamic Web Applications with MySQL and PHP

APPENDIX B BASIC VI COMMANDS

Developing Dynamic Web Applications with MySQL and PHP

Appendix B - Basic vi Commands

Appendix B

Basic vi Commands (http://www.cs.colostate.edu/helpdocs/vi.html)

What is vi? The default editor that comes with the UNIX operating system is called vi (visual editor). [Alternate editors for UNIX environments include pico and emacs, a product of GNU.] The UNIX vi editor is a full screen editor and has two modes of operation: 1. 2. Command mode commands which cause action to be taken on the file, and Insert mode in which entered text is inserted into the file.

In the command mode, every character typed is a command that does something to the text file being edited; a character typed in the command mode may even cause the vi editor to enter the insert mode. In the insert mode, every character typed is added to the text in the file; pressing the <Esc> (Escape) key turns off the Insert mode. While there are a number of vi commands, just a handful of these is usually sufficient for beginning vi users. To assist such users, this Web page contains a sampling of basic vi commands. The most basic and useful commands are marked with an asterisk (* or star) in the tables below. With practice, these commands should become automatic. NOTE: Both UNIX and vi are case-sensitive. Be sure not to use a capital letter in place of a lowercase letter; the results will not be what you expect. To Get Into and Out Of vi

To Start vi To use vi on a file, type in vi filename. If the file named filename exists, then the first page (or screen) of the file will be displayed; if the file does not exist, then an empty file and screen are created into which you may enter text. vi filename edit filename starting at line 1 vi -r filename recover filename that was being edited when system crashed To Exit vi Usually the new or modified file is saved when you leave vi. However, it is also possible to quit vi without saving the file. Note: The cursor moves to bottom of screen whenever a colon (:) is typed. This type of command is completed by hitting the <Return> (or <Enter>) key. :x<Return> quit vi, writing out modified file to file named in original invocation quit (or exit) vi :wq<Return> quit vi, writing out modified file to file named in original invocation :q<Return> :q!<Return> quit vi even though latest changes have not been saved for this vi call

Page B-1

Developing Dynamic Web Applications with MySQL and PHP

Appendix B - Basic vi Commands

Moving the Cursor Unlike many of the PC and MacIntosh editors, the mouse does not move the cursor within the vi editor screen (or window). You must use the key commands listed below. On some UNIX platforms, the arrow keys may be used as well; however, since vi was designed with the Qwerty keyboard (containing no arrow keys) in mind, the arrow keys sometimes produce strange effects in vi and should be avoided. If you go back and forth between a PC environment and a UNIX environment, you may find that this dissimilarity in methods for cursor movement is the most frustrating difference between the two. In the table below, the symbol ^ before a letter means that the <Ctrl> key should be held down while the letter key is pressed. j or <Return> [or down-arrow] k [or up-arrow] h or <Backspace> [or left-arrow] l or <Space> [or right-arrow] 0 (zero) $ w b move cursor down one line move cursor up one line move cursor left one character move cursor right one character move cursor to start of current line (the one with the cursor) move cursor to end of current line move cursor to beginning of next word move cursor back to beginning of preceding word

:0<Return> or 1G move cursor to first line in file :n<Return> or nG move cursor to line n :$<Return> or G Screen Manipulation The following commands allow the vi editor screen (or window) to move up or down several lines and to be refreshed. ^f move forward one screen ^b move backward one screen ^d move down (forward) one half screen ^u move up (back) one half screen ^l redraws the screen ^r redraws the screen, removing deleted lines move cursor to last line in file

Page B-2

Developing Dynamic Web Applications with MySQL and PHP

Appendix B - Basic vi Commands

Adding, Changing, and Deleting Text Unlike PC editors, you cannot replace or delete text by highlighting it with the mouse. Instead use the commands in the following tables. Perhaps the most important command is the one that allows you to back up and undo your last action. Unfortunately, this command acts like a toggle, undoing and redoing your most recent action. You cannot go back more than one step. u UNDO WHATEVER YOU JUST DID; a simple toggle The main purpose of an editor is to create, add, or modify text for a file. Inserting or Adding Text The following commands allow you to insert and add text. Each of these commands puts the vi editor into insert mode; thus, the <Esc> key must be pressed to terminate the entry of text and to put the vi editor back into command mode. i insert text before cursor, until <Esc> hit I insert text at beginning of current line, until <Esc> hit a append text after cursor, until <Esc> hit A append text to end of current line, until <Esc> hit o open and put text in a new line below current line, until <Esc> hit O open and put text in a new line above current line, until <Esc> hit Changing Text The following commands allow you to modify text. r replace single character under cursor (no <Esc> needed) R cw cNw C cc Ncc or cNc replace characters, starting with current cursor position, until <Esc> hit change the current word with new text, starting with the character under cursor, until <Esc> hit change N words beginning with character under cursor, until <Esc> hit; e.g., c5w changes 5 words change (replace) the characters in the current line, until <Esc> hit change (replace) the entire current line, stopping when <Esc> is hit change (replace) the next N lines, starting with the current line, stopping when <Esc> is hit

Page B-3

Developing Dynamic Web Applications with MySQL and PHP

Appendix B - Basic vi Commands

Deleting Text The following commands allow you to delete text. x delete single character under cursor Nx dw dNw D dd Ndd or dNd delete N characters, starting with character under cursor delete the single word beginning with character under cursor delete N words beginning with character under cursor; e.g., d5w deletes 5 words delete the remainder of the line, starting with current cursor position delete entire current line delete N lines, beginning with the current line; e.g., 5dd deletes 5 lines

Cutting and Pasting Text The following commands allow you to copy and paste text. yy copy (yank, cut) the current line into the buffer Nyy or yNy copy (yank, cut) the next N lines, including the current line, into the buffer p Other Commands Searching Text A common occurrence in text editing is to replace one word or phase by another. To locate instances of particular sets of characters (or strings), use the following commands. /string search forward for occurrence of string in text ?string search backward for occurrence of string in text n N move to next occurrence of search string move to next occurrence of search string in opposite direction put (paste) the line(s) in the buffer into the text after the current line

Determining Line Numbers Being able to determine the line number of the current line or the total number of lines in the file being edited is sometimes useful. :.= returns line number of current line at bottom of screen := ^g returns the total number of lines at bottom of screen provides the current line number, along with the total number of lines, in the file at the bottom of the screen

Page B-4

Developing Dynamic Web Applications with MySQL and PHP

Appendix B - Basic vi Commands

Saving and Reading Files These commands permit you to input and output files other than the named file with which you are currently working. :r filename<Return> :w<Return> :w newfile<Return> :12,35w smallfile<Return> :w! prevfile<Return> read file named filename and insert after current line (the line with cursor) write current contents to file named in original vi call write current contents to a new file named newfile write the contents of the lines numbered 12 through 35 to a new file named smallfile write current contents over a pre-existing file named prevfile

Page B-5

Developing Dynamic Web Applications with MySQL and PHP

APPENDIX C UPLOAD FORM

Developing Dynamic Web Applications with MySQL and PHP

Appendix C - Upload Form

Appendix C

Upload Form

One of the things that those coming to PHP want to know is how to upload files using PHP. First of all, opening PHP to be able to upload files is a security risk that needs to be evaluated prior to implementing. With that said, here is the script that can be used to create an upload form with explanations where need be:
<html><head><title>Load Images to Server</title></head> <body> <h3>Upload Image to Server</h3> <form method="post" enctype="multipart/form-data"> Select Image File: <input type="file" name="uploadedFile" size="40"> <input type="hidden" name="MAX_FILE_SIZE" value="10000000"> <input type="submit" value="submit"> </form> <?php // Identify Current Working Directory $directory_self = str_replace(basename($_SERVER['PHP_SELF']), '', $_SERVER['PHP_SELF']); // Directory for image uploads to be stored $uploadsDirectory = $_SERVER['DOCUMENT_ROOT'] . $directory_self . 'uploaded_files/'; // fieldname used within the file <input> of the HTML form $fieldname = 'uploadedFile'; // Handle the uploaded image if(!isset($_FILES[$fieldname])) { echo '<p>Please select a file</p>'; } else { // PHP's built-in uploading error check ($_FILES[$fieldname]['error'] == 0) or error('There was an error on upload, please retry'); // File was a subject of an HTTP upload @is_uploaded_file($_FILES[$fieldname]['tmp_name']) or error('This form was not called properly'); // Validate that the upload was an image and store image info $image_size = @getimagesize($_FILES[$fieldname]['tmp_name']) or error('Only image uploads are allowed'); // make a unique filename for the uploaded file and check it is not already // taken... if it is already taken keep trying until we find a vacant one // sample filename: 1140732936-filename.jpg $now = time(); $file_name = $now.'-'.$_FILES[$fieldname]['name']; while(file_exists($uploadFilename = $uploadsDirectory.$now.''.$_FILES[$fieldname]['name'])) { $now++; $file_name = $now.'-'.$_FILES[$fieldname]['name']; } // Moving the file to its final location @move_uploaded_file($_FILES[$fieldname]['tmp_name'], $uploadFilename) or error('Could not store image in the image directory'); // Load the image data to the tblImage table include "connect_info.php"; $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass) or die("Could not connect to MySQL server"); $sql = "INSERT INTO images (login_name, image_size, file_name) VALUES ('Granny','{$image_size[3]}', '$file_name')";

Page C-1

Developing Dynamic Web Applications with MySQL and PHP


$sql_results = mysql_query($sql, $linkID1); mysql_close($linkID1); if ($sql_results) { print "<p>File uploaded and saved as $file_name</p>"; print "<p>Database successfully updated</p>"; } else { print "<p>File uploaded and saved as $file_name</p>"; print "<p>Database not updated, please check data</p>"; } } // The following function handles any error calls function error($error) { print "<p>An error has occured: <strong>$error</strong>"; exit; } // end error handler ?> </body> </html>

Appendix C - Upload Form

Page C-2

Developing Dynamic Web Applications with MySQL and PHP

APPENDIX D PHP'S STRINGS AND REGULAR EXPRESSIONS

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

Appendix D

PHP's and Strings Regular Expressions

A regular expression is a pattern of characters that are used to match a set of strings when performing searches. Regular expressions, when created, are enclosed in forward slashes and tested against a string. PHP offers functions associated with two types of regular expression tools: POSIX and Perl-style.

POSIX
This form of regular expression searching is compliant with extended regular expressions (EREs) defined in IEEE POSIX 1003.2. Extended regular expressions are similar in syntax to the traditional Unix regular expressions, with some exceptions. The true power of the ERE's is their ability to be combined together to form searches. The POSIX ERE's are utilized in three methods: Brackets, Quantifiers and Predefined Character Ranges. Brackets - Brackets ([ ]) provide the capability to find ranges of characters when searching through strings. In non-extended regular expressions, when a search is made against a string for the term "dog", only words that contain the letters d-o-g in sequence are found. With brackets, the search using the [dog] will find any words that contain the letter "d", or the letter "o" or the letter "g". The following are a list of the most commonly used character ranges: [0-9] matches any numeric digit from 0-9 [a-z] matches any lowercase characters from "a" through "z" [A-Z] matches any uppercase character from "A" through "Z" [A-Za-z] matches any character from uppercase "A" through lowercase "z" The ranges can be modified to control the searches desired, such as [4-7] to find all strings that contain the decimals 4, 5, 6 or 7. Quantifiers - Quantifiers are characters that have special meaning when used in the context of ERE's. For many of these quantifiers, the actual use of them is only useful in context with another ERE. The following are list of the most commonly used character quantifiers: a+ matches any string containing at least one "a" a* matches any string containing zero or more of the letter "a" a? matches any string containing zero or one letter "a" a{3} matches any string containing "aaa" a{2,3} matches any string containing "aa" or "aaa" a{3,} matches any string containing at least "aaa", which would also include those string that included "aaaa" or "aaaaa" and so on ^a matches any string that begins with the letter "a" a$ matches any string that ends with the letter "a" a.a matches any string that contains the letter "a", followed by another character, and then again by the letter "a" such as madam, radar and again The following list demonstrates how ERE's can be combined together to produce more productive searches: [^a-zA-Z] matches any string not containing any of the characters in the range of lowercase "a" to uppercase "Z" ^.{2}$ matches any string containing exactly two characters <table>(.*)</table> matches any string enclosed with <table> tags (the characters between the tags can be any length (or no characters at all) a(bc)* matches any string containing a letter "a" followed by zero or more of the sequence "bc" Predefined Character Ranges - PHP allows the searching of character ranges that have been predefined (also known as character classes). The standard pre-defined classes are: [:alpha:] matches any alphabetical character, equivalent to [A-Za-z] [:alnum:] matches any alphabetical character or numeric digit from 0-9, equivalent to [A-Za-z0-9]

Page D-1

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

[:cntrl:] matches control characters such as tab, escape and backspace [:digit:] matches any numeric digit from 0-9, equivalent to [0-9] [:graph:] matches any of the printable characters in the range of ASCII 33 (!) to ASCII 126 (~) [:lower:] matches any lowercase character from "a" to "z", equivalent to [a-z] [:upper:] matches any uppercase character from "A" to "Z", equivalent to [A-Z] [:punct:] matches any of the punctuation characters to include ~ ` ! @ # $ % ^ & * ( ) - _ = + { } [ ] ; : ' < > , . ? and / [:space:] matches any white space characters including the space, horizontal tab, vertical tab, new line, form feed or carriage return [:xdigit:] matches any of the hexadecimal characters, equivalent to [a-fA-F0-9] The ranges can be modified to control the searches desired, such as [4-7] to find all strings that contain the decimals 4, 5, 6 or 7.

Using POSIX regular expressions


Within PHP there are seven functions used for searching strings using POSIX-style regular expressions: ereg() - This function utilizes the POSIX-style regular expressions to search strings provided for a match and is case-sensitive. If there is a match, the function returns a TRUE, if the regular expression does not find a match, a FALSE is returned. <?php $phone_number = "1900Atlanta"; if (ereg("[^0-9]",$phone_number)) print "The Phone Number must contain only numeric digits"; ?> The result of the above php script, which tests for any characters in the $phone_number variable that are not numeric digits, would be the printing of "The Phone Number must contain only numeric digits". Another way to use the ereg() function is to utilize the optional parameter regs (the third parameter) to break up a string. The following demonstrates how this would work: <?php $phone_number = "515-435-6789"; $p = ereg("[[:digit:]]\- [[:digit:]]\- [[:digit:]]", $phone_number, $regs); print $regs[0]."<br>"; // Outputs the entire phone number print $regs[1]."<br>"; // Outputs the area code print $regs[2]."<br>"; // Outputs the first three local digits print $regs[3]."<br>"; // Outputs the last four numbers ?> eregi() - This function is identical to the ereg() function but is case insensitive, meaning it ignores case distinction when matching alphabetic characters. <?php $last_name = "DeMarco"; if (ereg("marco",$last_name)) print "Matched with ereg"; if (ereg("marco",$last_name)) print "Matched with eregi"; ?> The script above would print "Matched with eregi" but would not match with ereg(). This is because the ereg() function was looking for a lowercase "m" in the $last_name variable, where eregi() did not care if the "m" was lower or uppercase. ereg_replace()- This function is equivalent to ereg() in its case-sensitive searching capabilities; however, it adds the ability to replace the characters it is searching for with new characters instead of just simply locating them. If the search pattern is not found, the string it searched against is unchanged. <?php

Page D-2

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

$url = "MySQL http://www.mysql.com"; print ereg_replace("http://([a-zA-Z0-9./-]+)$", "<a href=\"\\0\">\\0</a>", $url); ?> The script above would change the text "MySQL http://www.mysql.com" to "MySQL <a href="http://www.mysql.com">http://www.mysql.com</a>". This change would allow the http reference to be replaced with the HTML code required to create a web link. The three components of this function include the pattern to search for ("http://([a-zA-Z0-9./-]+)$"), the replacement string ("<a href=\"\\0\">\\0</a>") and then finally the variable that is going to be searched and replaced. The \\0 tells the ereg_replace() function to repeat the complete matched pattern (in this case http://www.mysql.com). eregi_replace - This function is identical to ereg_replace(), except that it is case insensitive when searching. split - This function divides strings based on the pattern that it searches for and stored the separated text into an array. The searches are case-sensitive when dealing with alphabetical characters. <?php $csv_text = "5, \"Amsterdam\", \"NLD\", \"Noord-Holland\", 731200"; $csv_array = split("[,]",$csv_text); foreach ($csv_array as $csv_column) { print "$csv_column<br>"; } ?> The script above would create an array called $csv_row that contains the following element: [0] = 5, [1]="Amsterdam", [2]="NLD", [3]="Noord-Holland", [4]=731200). The foreach iterative control statement would print each of these elements on the screen on their own lines. A third component can be placed in the split function that would limit the number of array elements that would be created. By adding 3 to the split function in the above script (split("[,]",$csv_text, 3) the array elements that would be created would consist of: [0]=5, [1]="Amsterdam", [2]="NLD", "NoordHolland", 731200. spliti - This function is identical to split(), except that it is case insensitive when searching. sql_regcase - This function converts each alphabetical character into its equivalent lower and upper case representation surrounded by brackets. For those characters that are not alphabetical, no change is taken place. <?php $text = "MySQL's website is http://www.mysql.com"; print sql_regcase($text); // Outputs [Mm][Yy][Ss][Qq][Ll]'[Ss] [Ww][Ee][Bb][Ss][Ii][Tt] // [Ee] [Ii][Ss] [Hh][Tt][Tt][Pp]://[Ww][Ww][Ww].[Mm][Yy][Ss] // [Qq][Ll].[Cc][Oo][Mm] ?>

Page D-3

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

Perl-style
The Perl programming language is exceptional at parsing strings by providing a comprehensive regular expression language to the programmer. Rather than creating their own regular expression language, the developers of PHP made the Perl regular expression syntax available to PHP users. The Perl-style regular expression syntax was built from the POSIX regular expression syntax and thus hold many of the same features. In fact, PHP programmers can use many of the same POSIX regular expression syntax when using Perl-style regular expression syntax. The basic Perl-style regular expression syntax involves using forward slashes (/ /) to identify the pattern that will be searched for: /mysql/ will find any string that contains the pattern "mysql", /m+/ will find any string that contains the letter "m" followed by one or more characters (mysql, mom, mudd, my, etc.) and /m{2,4}/ will find any string that contains the letter "m" followed by 2 or 4 characters (mom, mysql, etc.). The Perl-style regular expressions are utilized in three methods: Quantifiers, Modifiers and Metacharacters. Quantifiers - The quantifiers used in Perl-style regular expressions are identical to those used in POSIX ERE's. Modifiers - These are specific commands that allow for a more defined search based on the specific needs of that search. These commands work by being added to the standard Perl-style regular expressions. The following is a list of the most common Perl-style modifiers: i - performs a case insensitive search (ex. /mysql/i will find "mysql" and "MYSQL" or any other combination of upper and lower case characters). g - finds all occurrences of the search pattern (ex. /iss/g will find 2 occurrences of "iss" in "Mississippi"). This is useful when performing a global search and replace. m - performs the search based on individual lines in a multiple line string. For example, when using the characters ^ (which is for matching at the beginning of the string) or $ (which is for matching at the end of the string), the programmer can search a string with multiple lines as if they were individual lines. (ex. /^Thomas/ would not be matched against the following sentence but /^Thomas/m would be: "My mother went to the store.\nThomas went with her.") x - this Perl-style modifier will ignore white space and comments within the regular expression. U - this Perl-style modifier will stop the searching after the first occurrence of the pattern is found. Metacharacters - These are specific characters that are preceded by a backslash that symbolize a special meaning for the character following. The following are a few of the metacharacters associated with Perl-style regular expressions: \A - matches patterns only at the beginning of the string \b - matches a word boundary (ex. /\bis\b/ will find only occurrences of "is" but not words like "dish" or "mist", /is\b/ would find not only "is" but also "his" because the boundary is looking for the only "is" at the end of the word, ignoring what would be in front of it). \B ignores word boundaries. \d - matches any numeric digit character. \D is the opposite matching any non-numeric character. \s - matches a white space character. \S matches non-white space characters. Other metacharacters that do not require the backslash include: $ - matches patterns at the end of the line ^ - matches pattern at the beginning of the line . - matches any pattern except for the new line ( ) - encloses a character grouping

Page D-4

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

Using Perl-style regular expressions


Within PHP there are seven functions used for searching strings using Perl-style regular expressions: preg_match() - This function utilizes the Perl-style regular expressions to search strings provided for a match. If there is a match, the function returns a TRUE, if the regular expression does not find a match, a FALSE is returned. <?php $phone_number = "1900Atlanta"; if (preg_match("/.\D/",$phone_number)) print "The Phone Number must contain only numeric digits"; ?> preg_grep() - This function is similar to the preg_match() function, but works only on arrays. The preg_grep() function is also useful in that it creates a new array based on those matches found in the search array. <?php $product_codes = ("NZ3456", "SUS5678", "SNZ3294", "US4678"); $NZ_Codes = preg_grep("/NZ/", $product_codes); print_r($NZ_Codes); //NZ3456 and SNZ3294 are displayed ?> The preg_grep() function can also take a third input parameter that has a unique capability. By placing the words PREG_GREP_INVERT in the third input parameter, only those elements that do not match the parameter searched for are returned. Using the example above, the opposite elements would be returned: <?php $product_codes = ("NZ3456", "SUS5678", "SNZ3294", "US4678"); $non_nz_Codes = preg_grep("/NZ/", $product_codes, PREG_GREP_INVERT); print_r($non_nz_Codes); // SUS5678and US4678are displayed ?> preg_match_all() - This function is similar to preg_match(); however, rather than searching for just one occurrence of the search parameter, this function will find all occurrences. In addition, each occurrence found will be placed into an array variable entered into the third input parameter. The array created will contain various sections of the subpatterns contained in the search pattern. Just like preg_match(), if there is a match, the function returns a TRUE, if the regular expression does not find a match, a FALSE is returned. <?php $text = "mysql_close, mysql_connect and mysql_error are all PHP functions used when working with MySQL."; if (preg_match_all("/mysql\w+/",$text,$mysql_commands) { print_r($mysql_commands); } else { print "No mysql commands were found"; } ?>

Page D-5

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

preg_quote() - This function places a backslash in front of all special regular expression characters. This is useful if a run-time string containing special regular expression characters has to be evaluated. The special regular expression characters are: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : <?php $text = "The rental is $300"; print preg_quote($text); // Returns "The rental is \$300" ?> preg_replace() - This Perl-syntax function is equivalent to the ereg_replace() function. This function works by replacing all occurrences of the pattern searched with the replacement characters and then returns the modified result. The fourth parameter is optional, but when a number is entered it determines how many occurrences of the pattern searched will be replaced. If no number is entered, all occurrences of the search pattern will be replaced. <?php $url = "MySQL http://www.mysql.com"; print preg_replace("/http:\/\/(.*)/","<a href=\"\${0}\">\${0}</a>", $url); ?> The script above changes the http reference to be replaced with the HTML code required to create a web link. The three components of this function include the pattern to search for ("/http:\/\/(.*)/"), the replacement string ("<a href=\"\${0}\">\${0}</a>") and then finally the variable that is going to be searched and replaced. The ${0} tells the preg_replace() function to repeat the complete matched pattern (in this case http://www.mysql.com). In addition to individual variables, the pattern and replacement components can also be arrays. The function will cycle through each element of each array, making replacements as they are found. <?php $text = "The dog barks, the bear growls and the cat meows"; $adults = array("/dog/", "/bear/", "/cat/"); $children = array("puppy", "cub", "kitten") print preg_replace($adults,$children, $text); ?>

Page D-6

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

preg_replace_callback() - With preg_replace(), the function itself is responsible for handling the replacement procedure. With preg_replace_callback(), the handling of the replacement procedure is handed off to another function to take care of. The syntax is identical to preg_replace() except where the replacement text would be located, a function name is present. This function is responsible for handling any of the replacement changes to the text that matches the pattern searched. <?php $text = "Dear <pnm>S</pnm>Ortiz,<br>&nbsp;&nbsp;&nbsp;&nbsp;I would like to thank you and <pnf>F</pnf>Picard for taking the time in talking to me today. Please feel free to contact me if you have any additional questions.<br>Sincerely,<br><pnm>E</pnm>Bob Riker"; function proper_name_m($matches) { $titles = array( 'E' => 'Mr. ', 'S' => 'Sr. ', 'F' => 'M '); if (isset($titles[$matches[1]])) { return $titles[$matches[1]]; } else { return $matches[1]; } } function proper_name_f($matches) { $titles = array( 'E' => 'Ms. ', 'S' => 'Sra. ', 'F' => 'Mme '); if (isset($titles[$matches[1]])) { return $titles[$matches[1]]; } else { return $matches[1]; } } $new_text = preg_replace_callback("/<pnm>(.*)<\/pnm>/U", 'proper_name_m', $text); $final_text = preg_replace_callback("/<pnf>(.*)<\/pnf>/U", 'proper_name_f', $new_text); print $final_text; ?> In the code presented above, a letter (which looks like a follow-up to a sales or interview meeting) has been written. The user did not know the proper titles to use with the names, so they were taught to place 'E' for English titles, 'S' for Spanish titles and 'F' for French titles. In addition, because of the need to address both genders, they were also taught to identify the gender in the tags used: <pnm>$language_code</pnm> for male and <pnf>$language_code</pnf> for female. The function proper_name_m handles the replacement for the <pnm> tags and proper_name_f handles the <pnf> tags. The first preg_replace_callback function handles the changing of the male titles and then places the new text into the variable $new_text. The second preg_replace_callback function handles the changing of the female titles and then finalizes the text by placing the replaced contents in the variable $final_text. preg_split - This Perl-style function is equivalent to the split() function previously discussed with the exception of allowing Perl-style regular expressions. The third optional component of the preg_split() function can be entered to limit the number of changes that take place. Failing to enter a numeric limit (or a -1), ensures that there is no limit on the changes that can take place. <?php $csv_text = "5, \"Amsterdam\", \"NLD\", \"Noord-Holland\", 731200";

Page D-7

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

$csv_array = preg_split("/\,/",$csv_text); foreach ($csv_array as $csv_column) { print "$csv_column<br>"; } ?> The script above creates an array called $csv_row that contains the following element: [0] = 5, [1]="Amsterdam", [2]="NLD", [3]="Noord-Holland", [4]=731200). The foreach iterative control statement prints each of these elements on the screen on their own lines. A third component can be placed in the split function that would limit the number of array elements that would be created. By adding 3 to the split function in the above script (preg_split("/\,/",$csv_text, 3) the array elements that would be created would consist of: [0]=5, [1]="Amsterdam", [2]="NLD", "NoordHolland", 731200.

Comparing Strings
As stated, PHP has poweful regular expressions that provide programmers with the tools necessary to complete difficult searching tasks. In addition to this regular expression capability, PHP provides built-in functionality for performing a wide range of string-specific tasks. Many of these tasks are based on string comparison operations. String Length One of the simplest comparison operators of strings is determining if the lengths are equivalent. This involves determining the length of the strings and then acting upon those lengths. The length function built-in to PHP is strlen() and is one of the more widely used string expressions. <?php function chk_passwd($input) { if (strlen($input) < 7) { print "Password is too short"; } else if (strlen($input) > 10) { print "Password is too long"; }else { print "Password is the proper length, proceed<br>"; } } chk_passwd("doggy1"); chk_passwd("Diabolical"); chk_passwd("rst 4567"); chk_passwd("run-^$#&"); chk_passwd("mydogspotruns"); ?> In the above example, the length of the password is the only test being evaluated. Of course, this would not be acceptable by itself; however, it does show how length can be used as a string test.

Page D-8

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

Comparing Two Strings


Following the password example just shown, there are many web sites today that force a person to type there password in twice to make sure that they truly are setting it to what they want (the chances of typing it identically wrong twice is very low). This is accomplished using such tools as strcmp() which is a built-in to PHP. <?php Function chk_passwds($input1, $input2) { if (strcomp($input1, $input2) = 0) { print "Passwords are equal, proceed<br>"; }else { print "Passwords are not equal<br>"; } } chk_passwds("doggy1", "Doggy1"); // strcmp is case-sensitive and thus these passwords are not equal ?> The strcomp() function has three possible results: 0 means the two strings are equal, -1 means that the first string is less than the second string and 1 means that the second string is less than the first string. In the example above, all that needs to be tested is if they are equal. It is not necessary to know the exact differences between the two strings. Of course, a statement like if ($input1 == $input2) would serve the same purpose, but would not result in the same output type.

Other String Comparison Functions


While the strcmp() function is the most commonly used string comparison function in PHP, there are other string comparison functions offered: strcasecmp - This string comparison function is equivalent to the strcmp() function except that it is not case sensitive. <?php function chk_emails($input1, $input2) { if (! strcasecomp($input1, $input2)) { print "E-mails are the same, proceed<br>"; }else { print "E-mails are not equal<br>"; } } chk_emails("jones@mysql.com","Jones@MySQL.com"); // strcasecmp is case-insensitive and thus these two e-mails // are the same ?> strspn - The strspn() function compares two strings to determine how closely related they are to each other. This is accomplished by returning the length of the first string containing characters that are also located in the second string. <?php function passwd_diff($n_passwd, $o_passwd) { if (strspn($n_passwd, $o_passwd) > (strlen($o_passwd) *.75)) { print "New password must be noticeably different from the old password<br>"; }else { print "The new password is acceptable<br>"; } } passwd_diff ("mydogskip","mydogskippy"); // The characters in the new password and old password are

Page D-9

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

// too similar to be allowed passwd_diff ("myfriendskip","mydogskippy"); // The characters are different enough between the two // passwords to be considered acceptable ?> strcspn - The strcspn() function is similar to the strspn() function in that it compares two strings to determine how closely related they are to each other. However, rather than giving a number related to the similarities it looks at each character from left to right and identifies the first segment in the first string containing characters not in the second string. <?php $alphabet1 = "abcdefghijklmnopqrstuvwxyz"; $alphabet2 = "ghijklmnopqrstuvwxyz"; print strcspn($alphabet1, $alphabet2); ?>

Manipulating String Cases


Case sensitivity is an issue that the programmer (and the end user) must deal with. Everything from commands to passwords are affected by case sensitivity. In PHP there are four functions that provide the tools to deal with the case sensitivity issue by allowing the string case to be manipulated. strtolower - This string case manipulation function converts all characters that are uppercase characters to lowercase characters. <?php $text = "MySQL http://WWW.MYSQL.COM"; print strtolower($text); // Returns "mysql http://www.mysql.com"; ?> strtoupper - This string case manipulation function converts all characters that are lowercase characters to uppercase characters. <?php $text = "MySQL http://WWW.MYSQL.COM"; print strtoupper($text); // Returns "MYSQL HTTP://WWW.MYSQL.COM"; ?> ucfirst - This string case manipulation function converts only the first character of the string to uppercase. The remaining characters are left alone. <?php $text = "mysql http://www.MySQL.com"; print ucfirst($text); // Returns "Mysql http://www.MySQL.com "; ?> ucwords - This string case manipulation function converts the first character of each word in the string to uppercase. The remaining characters in each word are left alone. <?php $text = "my mother said to pick the very best one and ..."; print ucwords($text); // Returns "My Mother Said To Pick The Very Best One And ..."; ?>

Page D-10

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

HTML Conversion
PHP's strength is in its ability to turn a static web page into a dynamic web page by interacting directly with the HTML. Part of this strength is PHP's ability to convert non-HTML (text only) strings to HTML and HTML strings to non-HTML strings. To make this happen, PHP provides multiple built-in functions designed specifically for HTML conversions. The following is a list of the most commonly used: Text to HTML Conversion Functions nl2br - This function name (nl2br) is an acronym for "newline to <br /> tags" due to the fact that this function will convert all newline characters (\n) in strings to their XHTML-compliant equivalent (<br />). <?php $text = "See Spot. See Spot run. See Spot fall. See Spot's friends laugh. Hear Spot growl. See Spot's friends run."; print nl2br($text); // The sentence will now read "See Spot.<br />See Spot run. // <br />See Spot fall.<br />See Spot's friends laugh.<br /> // Hear Spot growl.<br />See Spot's friends run." ?> htmlspecialchars - There are numerous characters that HTML identifies as special for completing certain tasks that are everyday characters in written language. For example; the ampersand sign (&) is used in many languages to abbreviate the word "and"; however, the ampersand sign is also used in HTML as a special character. If a programmer wants to actually use the ampersand sign as its original meaning, the following HTML code must be entered in its place: "&amp" as in "Jack &amp Jill". The PHP function htmlspecialchars() will convert all such special characters in HTML to their HTML equivalents. <?php $text="<<Storytime>> Jack & Jill went up the hill ... Jack fell down! Jill screamed \"Jack are you OK?\""; print htmlspecialchars($text); // The sentence will now read "&lt;&lt;Storytime&gt;&gt; Jack // &amp Jill went up the hill ... Jack fell down! Jill screamed // &quot;Jack are you OK?&quot;" ?> If using both the nl2br() and htmlspecialchars() functions against the same string, it is important to execute the htmlspecialchars() first and then nl2br() second. If the order is reversed, the XHTMLequivalent line returns (<br />) will be converted to &lt;br /&gt; defeating the purpose of the functions.

Page D-11

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

strtr - This function uses arrays to handle search and replace operations. It is similar in nature to the preg_replace() Perl-style regular expression function. The following is an example presented earlier using the preg_replace() function: <?php $text = "The dog barks, the bear growls and the cat meows"; $adults = array("/dog/", "/bear/", "/cat/"); $children = array("puppy", "cub", "kitten"); print preg_replace($adults,$children, $text); ?> The following is an example of using the strtr() function to recreate the above example: <?php $text = "The dog barks, the bear growls and the cat meows"; $translation_table = array("dog" => "puppy", "bear" => "cub", "cat" => "kitten"); print strtr($text, $translation_table); ?> With this capability, there are many uses that the strtr() function can provide to the programmer. However, due to the fact that the discussion now revolves around converting strings to HTML, it is time to talk about the get_html_translation_table() function. get_html_translation_table - PHP has built in arrays for handling the most common HTML equivalent characters. The arrays are referenced by calling them with the function get_html_translation_table(). The two arrays that are available are HTML_SPECIALCHARS and HTML_ENTITIES. The following examples demonstrate how these two arrays are called and utilized in PHP code: <?php $text="<<Storytime>> Jack & Jill went up the hill ... Jack fell down! Jill screamed \"Jack are you OK?\""; $translation_table=get_html_translation_table(HTML_SPECIALCHARS); print strtr($text, $translation_table); // The sentence will now read "&lt;&lt;Storytime&gt;&gt; Jack // &amp Jill went up the hill ... Jack fell down! Jill screamed // &quot;Jack are you OK?&quot;" ?> <?php $text="Jan and Felpe paid 13 a piece for gum."; $translation_table = get_html_translation_table(HTML_ENTITIES); print strtr($text, $translation_table); // The sentence will now read "J&uacute;an and Fel&iacute;pe //paid 13&cent; a piece for gum." ?> To see what characters are in the HTML_ENTITIES translation tables, use the following PHP code (view the source of the web page to see the HTML special characters): <?php $translation_table = get_html_translation_table(HTML_ENTITIES); foreach($translation_table as $row) print "$row<br>\n"; ?> HTML to Text Conversion Functions array_flip - This function is the opposite function for the get_html_translation_table() function by reversing HTML special characters back their original string characters. <?php

Page D-12

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

$html_text = "J&uacute;an and Fel&iacute;pe paid 13&cent; a piece for gum." $translation_table = get_html_translation_table(HTML_ENTITIES); $flipped = array_flip($translation_table); print strtr($html_text, $flipped); // The sentence will now read "Jan and Felpe paid 13 a piece for // gum" without any HTML translation ?> strip_tags() - This function removes all HTML and PHP tags from a string. <?php $html_text = "<a href=\"http://www.johnsgifts.com\"><strong> John's Gifts</strong></a>"; print strip_tags($html_text); // Returns John's Gifts with no HTML tags ?> In the even that a tag type should remain while all others are removed, that can be accomplished by adding the HTML tag in the optional second component of the function. <?php $html_text = "<a href=\"http://www.johnsgifts.com\"><strong> John's Gifts</strong></a>"; print strip_tags($html_text, "<strong>"); // Returns <strong>John's Gifts</strong> but without the <a> tags ?>

Page D-13

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

Modify String Length


When performing the duties of creating/manipulating web content, the PHP programmer will need to modify the lengths of strings, either by padding the strings to be a certain length or removing strings to be a certain length. PHP provides numerous built-in functions to accomplish these tasks. The following are the most common functions for modifying string lengths: ltrim - The name of this function identifies its purpose, to trim the string content starting from the left portion of the string. By default, the ltrim() function will remove all white space characters which includes the standard space, the horizontal tab(\t), vertical tab (\x0b), new line (\n), carriage return (\r) and NULL (\0). This function will continue to remove these characters until it reaches a non-white space character and then the function removal process will terminate. <?php $text = \n\t Jane wanted to listen to the troupe play."; print ltrim($text); // The new text printed will be "Jane wanted to listen to the // troupe play." ?> If there are other characters that must be removed from the left portion of the string, they can be placed into the second component of the function which is the optional parameter option. When there is a value in the optional parameter option, all other characters will remain (even white space characters). If the programmer requires white space characters to be removed also, they must enter them into the optional parameter option along with the additional required character. With the optional parameter option, the function will also continue to remove characters until it finds a character that is not in the optional parameter list and then terminate. <?php $text = "\ta) \n\tJane wanted to listen to the troupe play."; print ltrim($text, "\ta) "); // The new text printed will be "\n\tJane wanted to listen to the // troupe play." ?> rtrim - Is equivalent to the ltrim() function in how it performs, the only difference is it trims from the end of the string versus the beginning of the string. <?php $text = "Jane wanted to listen to the troupe play. \n"; print ltrim($text); // The new text printed will be "Jane wanted to listen to the // troupe play." Without the space and line return at the end ?> trim - Is equivalent to the ltrim() and rtrim() functions combined together. The trim() function trims the characters from the beginning of the string and the end of the string. <?php $text = "\n Jane wanted to listen to the troupe play. \n"; print ltrim($text); // The new text printed will be "Jane wanted to listen to the // troupe play." Without the space and line return on either end ?>

Page D-14

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

str_pad - This function will insert characters (spaces by default) into a string to force the string to be a certain length (which is defined in the second parameter of the function). <?php $text = "Title"; print str_pad($text, 15); // The new text printed will be "Title ?>

"

A PHP programmer can also change the default character (a space) to another character(s) by placing the character(s) into the third optional parameter option. <?php $text = "Title"; print str_pad($text, 15, "-|"); // The new text printed will be "Title-|-|-|-|-|" ?> By default the padding is added to the end of the string; however, by entering either STR_PAD_RIGHT, STR_PAD_LEFT or STR_PAD_BOTH into the fourth optional parameter option, the programmer can control where the padding will be added. When using the fourth optional parameter option, the third optional parameter option must also have a character (even if it just a space). <?php $text = "Title"; print str_pad($text, 15, " ", STR_PAD_BOTH); // The new text printed will be " Title ?>

"

Counting Strings
Due to the fact that PHP's regular expressions are so versatile, many functions that have been designed by PHP developers have been overlooked in the past because the tasks were able to be completed with regular expressions. However, there are two functions that should not be overlooked due to their simplicity in performing a more complex task. count_chars - This built-in function provides information about the number of times that an standard ASCII character appears in the string. <?php $text = "I went to Mississippi for the summer."; $letters = count_chars($text, 1); // 1 counts only the characters that show up more than zero times // 0 is the default and produces the entire listing of standard // ASCII characters, even those not showing up in the string // 2 returns only those ASCII characters that do not show up // 3 & 4 return byte info (all located and all unused, respectively) foreach($letters as $key=>$value) { print chr($key)." = ".$value; } // A list of characters followed by their frequency appears // The order is based on the standard ASCII order ?>

Page D-15

Developing Dynamic Web Applications with MySQL and PHP

Appendix D - PHP Strings/Regular Expressions

str_word_count - This built-in function works on a similar principal to the count_chars() function, but with the focus on the words themselves versus the characters. The basic function is to return a numeric count of the number of words contained in the string. <?php $text = "I went to Mississippi for the summer."; print str_word_count($text); // Returns the number of words found ?> Another way the function works is by placing each word in the string into an array. This array can be built one of two ways. By placing a numeric 1 in the second parameter option, the array will be built with just the words as the entities for the array. By placing a numeric 2 in the second parameter option, the array will be built with the entities built with the key being the numeric location of where the word was located in the array and the value of the word as the key. <?php $text = "I went to Mississippi for the summer."; $words = str_word_count($text,1); print_r($words,1); // The following will be "printed" out: // Array ( [0] => I [1] => went [2] => to [3] => Mississippi // [4] => for [5] => the [6] => summer ) ?> <?php $text = "I went to Mississippi for the summer."; $words = str_word_count($text,2); print_r($words,1); // The following will be "printed" out: // Array ( [0] => I [2] => went [7] => to [10] => Mississippi // [22] => for [26] => the [30] => summer ) ?>

Page D-16

Developing Dynamic Web Applications with MySQL and PHP

APPENDIX E FURTHER PRACTICE SOLUTIONS

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Appendix E

Further Practice Solutions

Chapter 3 PHP Foundations


1. 2. Create a procedure called comp_ops that has three (3) potential outcomes: Test the comp_ops function with the following values:
<?php function comp_ops ($var_a, $var_b) { if ($var_a != $var_b) { print "$var_a is not equal to $var_b<br>"; } else if ($var_a == $var_b) { print "$var_a is equal to $var_b<br>"; } else { /* This is a safety clause to make sure that there are no values that could slip by that can not be evaluated (ex. Nulls in SQL)*/ print "Solution is unknown<br>"; } } comp_ops(3,2); comp_ops(2,2); $i = Null; comp_ops(2,$i); ?> 3. Create a function called c_length that returns the value of a right triangles longest side based on input (from the end user) for the other two sides. Hint: The square root function in PHP is sqrt(). 4. Test the c_length function with the following values: 3, 4 11,15

<?php function c_length ($a=1, $b=2) { $c = sqrt(($a*$a)+($b*$b)); return printf("%01.2f",$c); } c_length(3,4); print "<br>"; // Placed here to put an "HTML line break" in c_length(11,15); ?>

Page E-1

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Bonus: Using arrays, create an HTML table that displays a times table based on a number entered. Once created, test with the numbers 3, 5, and 10. The following demonstrates an idea of what the final outcome should look like: 1 2 3 4 5 1 1 2 3 4 5 2 2 4 6 8 10 3 3 6 9 12 15 4 4 8 12 16 20 5 5 10 15 20 25

Hint: To create a dynamic array, use ${"identifier".$value}.


<?php

function times_table ($x=1) { print "<table border=1><tr><td>&nbsp;</td>"; for ($v1=1; $v1 <= $x; $v1=$v1+1) { for ($v2=1; $v2 <= $x; $v2=$v2+1) { ${"array".$v1}[$v2] = $v1 * $v2; } print "<td><b>$v1</b></td>"; } print "</tr>"; for ($v3=1;$v3 <= $x;$v3=$v3+1) { for ($v4=1;$v4 <= $x;$v4=$v4+1) { if ($v4==1) print "<tr><td><b>$v4</b></td>"; print "<td>".${"array".$v3}[$v4]."</td>"; if ($v4==$x) print "</tr>"; } } print "</table>"; } times_table(3); times_table(5); times_table(10); ?>

Page E-2

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 5 Managing Databases


1. 2. Login in to the mysql client using the login name and password provided by your instructor. View the existing databases that the MySQL Server is maintaining. mysql> SHOW DATABASES; 3. There should be only three databases that the MySQL Server is maintaining: INFORMATION_SCHEMA, mysql and test. Remove any additional databases that exist. If need be, mysql> DROP DATABASE db_name; 4. Create a new database called photo_album with a default character set of utf8. mysql> CREATE DATABASE photo_album CHARACTER SET utf8; 5. Using the mysql client, verify that the database was created. mysql> SHOW DATABASES; 6. View the contents of the /usr/local/mysql/data directory. Is there a new sub-directory associated with the database just created? >ls /usr/local/mysql/data/ 7. View the db.opt file located in the associated sub-directory to verify the correct default character set is being used. What collation type has been assigned as default? Does that make sense for the character set chosen? > more /usr/local/mysql/data/photo_album/db.opt

Page E-3

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 6 Managing Database Tables


1. 2. 3. 4. Login in to the mysql client using the login name and password provided by your instructor. View the existing databases that the MySQL Server is maintaining. Utilize the photo_album database. Create the first table called customers that will store the information related to the customers who have purchased access to the online photo album NOT NULL DEFAULT '', NOT NULL DEFAULT '', NOT NULL DEFAULT '', NOT NULL DEFAULT '', NULL, NOT NULL DEFAULT '', NOT NULL DEFAULT '', NOT NULL DEFAULT '', NOT NULL DEFAULT '', NULL, NOT NULL DEFAULT 0, 'False') NOT NULL DEFAULT

SHOW DATABASES; USE photo_album;

CREATE TABLE customers ( email_customer VARCHAR(50) f_name VARCHAR(20) l_name VARCHAR(30) addr1 VARCHAR(30) addr2 VARCHAR(30) addr_city VARCHAR(25) addr_state CHAR(3) addr_zip CHAR(10) primary_phone CHAR(12) secondary_phone CHAR(12) term_date DATE active_customer ENUM('True', 'True', PRIMARY KEY (email_customer) ) ENGINE=INNODB;

Page E-4

Developing Dynamic Web Applications with MySQL and PHP 5.

Appendix E - Further Practice Solutions

Create the second table called logins that will contain the login authentication data. Each customer will be able to have up to 5 logins for their site (this could be given to family and friends to access their photos).

CREATE TABLE logins ( login_name VARCHAR(30) NOT NULL DEFAULT '', email_customer VARCHAR(50) NOT NULL DEFAULT '', f_name VARCHAR(20) NOT NULL DEFAULT '', l_name VARCHAR(30) NOT NULL DEFAULT '', passwd VARCHAR(30) NOT NULL DEFAULT '', last_login DATETIME NOT NULL DEFAULT 0, active_login ENUM('True', 'False') NOT NULL DEFAULT 'True', PRIMARY KEY (login_name), INDEX (email_customer), FOREIGN KEY (email_customer) REFERENCES customers (email_customer) ON UPDATE CASCADE ) ENGINE=INNODB; ---- Note: The reason we do not want a DELETE CASCADE on this FK relationship is due to the fact that we do not want to lose the customer information. By setting the active_customer to False, we can simply code a response to the customer when they attempt to log in that there account has been closed. If they wish to pay us, we will be happy to open their account again and they have lost nothing. However, a policy would have to be in place on when data is archived. 6. Create the third table called images that will contain the information about the photos. The image information will include information to connect the images to other tables, the size of the image and the name of the image that was stored. Later in the course, the code will be created to upload these images with the image information being stored in the database.

CREATE TABLE images ( id_image INT UNSIGNED AUTO_INCREMENT NOT NULL, login_name VARCHAR(30) NOT NULL DEFAULT '', image_size VARCHAR(30) NOT NULL DEFAULT '', file_name VARCHAR(60) NOT NULL DEFAULT '', image_date DATE NOT NULL DEFAULT 0, active_image ENUM('True', 'False') NOT NULL DEFAULT 'True', PRIMARY KEY (id_image), INDEX (login_name) ) ENGINE=MYISAM; 7. Create the last table called comments that will be used to keep track of the comments attached to each picture. Each login associated with the images will be able to provide comments against the picture.

CREATE TABLE comments ( id_comment INT UNSIGNED AUTO_INCREMENT NOT NULL, login_name VARCHAR(30) NOT NULL DEFAULT '', id_image INT UNSIGNED NOT NULL DEFAULT 0, comments TEXT NOT NULL DEFAULT '', log_date TIMESTAMP NOT NULL, active_comment ENUM('True', 'False') NOT NULL DEFAULT 'True', PRIMARY KEY (id_comment), INDEX (id_image) ) ENGINE=MYISAM; 8. View the list of tables located in the photo_album database.

SHOW TABLES;

Page E-5

Developing Dynamic Web Applications with MySQL and PHP 9.

Appendix E - Further Practice Solutions

Review the details of each table created and verify that the tables were designed properly. If they are not correct, use the ALTER TABLE command to make the changes to correct the problems.

SHOW CREATE TABLE customers\G SHOW CREATE TABLE logins\G SHOW CREATE TABLE images\G SHOW CREATE TABLE comments\G

Page E-6

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 7 SQL SELECT Commands


1. 2. Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). In the photo_album databases, load the /tmp/photo_album.sql.data file into the database. USE photo_album; SOURCE /tmp/photo_album.sql; 3. Perform an aggregate select against each table to count the number of records located in each table. SELECT SELECT SELECT SELECT 4. COUNT(*) COUNT(*) COUNT(*) COUNT(*) FROM FROM FROM FROM customers; comments; images; logins;

Using the customers table, list the customers who are active from closest to farthest termination date (term_date). SELECT * FROM customers WHERE active_customer='True' ORDER BY term_date ASC;

5.

Using the logins table, list those with active logins and have logged in during the month of April 2007. SELECT * FROM logins WHERE active_login='True' && last_login LIKE '2007-04%';

6.

Using the images table, list the active images names from the most recent date to the oldest dates (image_date). SELECT file_name, image_date ORDER BY image_date DESC; FROM images WHERE active_image

7.

Using the comments table, list the user with the most active comments. SELECT login_name, COUNT(*) FROM comments WHERE active_comment = 'True' GROUP BY login_name DESC;

Page E-7

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 8 SQL Expressions


1. 2. 3. Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). View the existing databases that the MySQL Server is maintaining. SHOW DATABASES; Utilize the photo_album database. USE photo_album; ---- If Need be, recreate the database and load the SQL data in that will be used for this lab CREATE DATABASE photo_album; SOURCE /tmp/photo_album.sql; 4. Calculate how many days ago each person logged into the photo_album system. Note: Difference in dates are returned in microseconds when directly subtracted from each other. SELECT login_name, ROUND((NOW() - last_login)/24/60/60/60) FROM logins; 5. List the actual day name (Monday, Tuesday, etc.) for the last logins to determine if there is a trend in the day of the week for the last time a person logged into the photo_album system. SELECT login_name, DAYNAME(last_login) FROM logins; 6. Modify the statement above by having the output show 'Weekend' for Saturday and Sunday, and 'Weekday' for every other day. SELECT login_name, IF(DAYNAME(last_login) IN('Saturday','Sunday'),'Weekend','Weekday') FROM logins; 7. Show the expiration dates (term_date) for the customers with the first name Granny and Yogi, without using two where statements. SELECT f_name, term_date from customers WHERE fname IN('Granny','Yogi');

Page E-8

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 9 SQL DML Commands


1. 2. Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). View the existing databases that the MySQL Server is maintaining. SHOW DATABASES; 3. Utilize the photo_album database. USE photo_album; ---- If Need be, recreate the database and load the SQL data in that will be used for this lab CREATE DATABASE photo_album; SOURCE /tmp/photo_album.sql; 4. Search the customers records for the customer with the following e-mail address: hollywood@truedog.com SELECT * FROM customers WHERE email_customer = 'hollywood@truedog.com'\G 5. Search the logins records for logins associated with the customer identified in step 4. SELECT * FROM logins WHERE email_customer = 'hollywood@truedog.com'; 6. In the customers table, update the customers e-mail address, identified in step 4, to howleewood@truedog.com. UPDATE customers SET email_customer = 'howleewood@truedog.com' WHERE email_customer = 'hollywood@truedog.com'; 7. Review the customers records to see if the change (from step 6) took place. If the update did not take place, reissue the statement in step 6 to ensure the change takes place? SELECT * FROM customers WHERE email_customer = 'howleewood@truedog.com'\G 8. Review the logins table to see if the e-mails associated with the customer in step 6 were also changed. If the e-mail associated with that customer were also changed in the logins table, why? SELECT * FROM logins WHERE email_customer = 'howleewood@truedog.com'\G

Page E-9

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 10 SQL Joins


1. 2. 3. Login in to the mysql client using the login name and password provided by your instructor (if not already logged in). View the existing databases that the MySQL Server is maintaining. SHOW DATABASES; Utilize the photo_album database. USE photo_album; ---- If Need be, recreate the database and load the SQL data in that will be used for this lab CREATE DATABASE photo_album; 4. SOURCE /tmp/photo_album.sql; Query the database to display the active primary customer (email, first and last name) and all the associated active login names associated with that customer. SELECT customers.email_customer, customers.fname, customers.lname, logins.login_name FROM customers, logins WHERE customers.email_customer = logins.email_customer AND customers.active_customer = 'True' AND logins.active_login = 'True'; Modify the query just issued to also show the image name of all the active files associated with each one of the login names. SELECT customers.email_customer, customers.fname, customers.lname, logins.login_name, images.file_name FROM customers, logins, images WHERE customers.email_customer = logins.email_customer AND logins.login_name =images.login_name AND customers.active_customer = 'True' AND logins.active_login = 'True' AND images.active_image = 'True'; The customer with the login name of Frankie has requested that his login name be changed to just 'Frank' to make it easier for him to remember it. The only problem is that the change must also take place in the images table. This is not automatic due to the fact that this table is a MyISAM table (rightfully so) and there is no Foreign Key constraints that would make the change automatic. However, this is not a problem with the right update statement against the two tables at once. Can you make one query that will update both the tables at once? UPDATE logins, images, comments SET logins.login_name = 'Frank', images.login_name = 'Frank' WHERE logins.login_name = images.login_name AND logins.login_name = 'Frankie';

5.

6.

Page E-10

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 11 MySQL Data Driven Web Based Forms


1. Using the script view_images.php, view the image associated with id_image 8 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=8 Solution in the view_images1.php file 2. Using the view_images.php script again, add to the PHP script the ability to capture the image entered (id=#) and verify if it is a valid and active image id. Once completed attempt to enter an image identifier that is not in the database to see how the script will handle it. In addition, attempt to enter in an image_id that is not numeric. Solution in the view_images2.php file 3. Add to the view_images.php script the ability to move forward or backwards through the pictures without having to type in the next or previous imageID. Solution in the view_images3.php file 4. Add to the view_images.php script the ability to see the image name and the data associated with the picture. The data associated with the image must be able to be updated by the end user. Build the form to make this happen and the script to update the images table with the updated date. Test your script by making changes to multiple dates. Solution in the view_images4.php file 5. Add to the view_images.php the ability to delete the images (make them inactive). It is best not to truly delete the images, by making the active_image='False', the end user will no longer be able to view the image through the web interface; however, the image will remain for undoing purposes. In your own applications you would have to consider the implications of such a solution (security vs. undoing capabilities). Solution in the view_images5.php file Bonus: Add to the view_images.php script the ability to review and add comments to the picture displayed. At this point, hard code a login_name (such as 'Hank') into the comments table to track who entered the comment. Solution in the view_images6.php file

Page E-11

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 12 Session Handling


1. In the mysql client, recreate (or create) the photo_album database and source in the /tmp/photo_album.sql file to propogate the database with clean data. If the ./uploaded_files sub-directory is not created and/or propogated with images for use with the view_images.php script, please unzip the uploaded_files.zip file into that directory. DROP DATABASE photo_album; CREATE DATABASE photo_album; USE photo_album; SOURCE /tmp/photo_album.sql Create the sessions table in the photo_album database: Column Name session_id image_id date_created Data Type CHAR(60) INT TIMESTAMP Extra NOT NULL NOT NULL

2.

CREATE TABLE `sessions` (session_id CHAR(60) NOT NULL, image_id INT NOT NULL, date_created TIMESTAMP); Using the script view_images.php, ensure that the correct script is being used by viewing the image associated with id_image 15 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=15. Does the form contain links to move to the previous image and the next image? Does the form contain the ability to delete the image? Does the form have the ability to update the date? Does the form contain comments associated with the image and provide the ability to add comments? If so, then the correct version of the view_images.php file is being used. -- Browse to http://localhost/view_images.php?id=15 -- In the source files, view_images5.php is the version of the view_images file that should be used if not already set up from previous further practice labs Add the ability to keep track of the last image that was viewed using session handlers in the view_images.php file. Use the sessions table in the photo_album database to store the session ID and the associated data (image_ID and the date the session ID was created). Create the ability to store and retrieve the last image ID that was viewed using sessions. Solution in the view_images7.php file Open your web browser and open http://localhost/view_images.php. Go to image ID 9. Using the same web browser, open up the MySQL web page, http://www.mysql.com. Using the same web browser again, type in http://localhost/view_images.php. Does the image associated with ID 9 show up? If not, review the view_images.php script and determine where the problem is. Open the mysql client and perform a SELECT against the photo_album.sessions table. Is there session information in this table? SELECT * FROM photo_album.sessions;

Page E-12

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 13 OOP in PHP


1. In the mysql client, recreate (or create) the photo_album database and source in the /tmp/photo_album.sql file to propogate the database with clean data. If the ./uploaded_files sub-directory is not created and/or propogated with images for use with the view_images.php script, please unzip the uploaded_files.zip file into that directory. DROP DATABASE photo_album; CREATE DATABASE photo_album; USE photo_album; SOURCE /tmp/photo_album.sql Using the script view_images.php, ensure that the correct script is being used by viewing the image associated with id_image 15 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=15. Does the form contain links to move to the previous image and the next image? Does the form contain the ability to delete the image? Does the form have the ability to update the date? Does the form contain comments associated with the image and provide the ability to add comments? Can you shut down the browser, restart and return to the exact picture you left by typing in only the PHP file (http://localhost/view_images.php)? If so, then the correct version of the view_images.php file is being used. -- Browse to http://localhost/view_images.php?id=15 -- In the source files, view_images7.php is the version of the view_images file that should be used if not already set up from previous further practice labs Replace the ... or die ... script for connecting to the database with an exception handling script that will identify there is an error, display the file the error is associated to and the line of the error in the file. Solution in the view_images8.php file 4. 5. 6. After saving the changes, reload the http://localhost/view_images.php file in your browser. Is the script still working correctly? In the view_images.php script, replace the password ($dbpass) with an empty string (forcing the exception handling to be tested. After saving the changes, reload the http://localhost/view_images.php file in your browser. Is the script still working correctly? If not, is there a message letting you know what the problem is? Correct the view_images.php script, save the changes and refresh in the browser. Is everything working correctly again?

2.

3.

7.

Page E-13

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

Chapter 14 Establishing User Authentication


1. In the mysql client, recreate (or create) the photo_album database and source in the /tmp/photo_album.sql file to propogate the database with clean data. If the ./uploaded_files sub-directory is not created and/or propogated with images for use with the view_images.php script, please unzip the uploaded_files.zip file into that directory. DROP DATABASE photo_album; CREATE DATABASE photo_album; USE photo_album; SOURCE /tmp/photo_album.sql Using the script view_images.php, ensure that the correct script is being used by viewing the image associated with id_image 15 (?id=#) by typing in the following in the web browser: http://localhost/view_images.php?id=15. Does the form contain links to move to the previous image and the next image? Does the form contain the ability to delete the image? Does the form have the ability to update the date? Does the form contain comments associated with the image and provide the ability to add comments? Can you shut down the browser, restart and return to the exact picture you left by typing in only the PHP file (http://localhost/view_images.php)? If so, then the correct version of the view_images.php file is being used. -- Browse to http://localhost/view_images.php?id=15 -- In the source files, view_images8.php is the version of the view_images file that should be used if not already set up from previous further practice labs Add a database authentication to the view_images.php that check the users login name and password against the logins table in the photo_album database. Once access is granted, use the users login name to track the comments that they add to the database. Solution in the view_images8.php file 4. After saving the changes, reload the http://localhost/view_images.php file in your browser and attempt incorrect logins along with hitting the cancel button on the login prompt window. What happens? Was that expected? Reload the http://localhost/view_images.php file in your browser and login with the username Granny and the password Iam30andCounting. Was the login accepted? Add comments to any of the pictures. Do your comments get associated with Granny?

2.

3.

5. 6.

Page E-14

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

The following is the complete script for the view_images9.php file that contains all the further practice lab components:
<html><head><title>View Images</title></head> <body> <?php // Create the function that forces user authentication function userAuth() { //// This HTML header information forces authentication //// when the web page is viewed header('WWW-authenticate: Basic Realm="Access Photo Album"'); header('HTTP/1.0 401 Unauthorized'); //// If the authentication fails the following comment is //// displayed and then the script is terminated print "You must provide a valid login and password!"; exit; } // Test to see if authentication has already taken place //// $_SERVER['PHP_AUTH_USER'] holds the username that is //// needed for authentication, if it is not set call the //// userAuth function if (! isset($_SERVER['PHP_AUTH_USER'])) { userAuth(); } else { //// Load variables ($dbhost,$dbuser,$dbpass) that will be used in mysql_connect //// This script contains the three variables mentioned and are located in the //// same directory as the PHP scripts utilizing the variables (this is not the //// recommended practice - they should be in a directory not accessible through //// the web browser; however, for training purposes this is acceptable) include "connect_info.php"; // Connect to MySQL server and use photo_album database //// The ... or die ... script for connecting to the database has been replaced //// with an exception handling script that will identify there is an error, //// display the file the error is associated to and the line of the error in //// the file. try { $linkID1 = mysql_connect($dbhost,$dbuser,$dbpass); if (! $linkID1) { throw new Exception("Could not connect!"); } } catch (Exception $e) { echo $e->getMessage()." File: ".$e->getFile().", line ". $e->getLine()."<br>\n"; } // Identify which MySQL database to use //// Prepare the actual database to utilize in the MySQL server. //// If the connection to the database can not be completed (access issues, //// database not existing, etc.), a message will be displayed through the //// web browser that the script "Could not connect to the photo_album //// database" (the or die portion) mysql_select_db("photo_album",$linkID1) or die ("Could not connect to the photo_album database"); // Create variables for login data //// Within PHP these are the two pre-defined variables that are used //// in the authentication of users $serverLogin = $_SERVER['PHP_AUTH_USER']; $serverPass = $_SERVER['PHP_AUTH_PW'];

Page E-15

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

// Create and execute the verification //// The following SQL will test to see if the user name and SHA encoded //// passwords are correct against the database $login_query = "SELECT login_name FROM logins WHERE login_name = '$serverLogin' AND password = SHA('$serverPass')"; //// Execute the prepared SQL $login_results = mysql_query($login_query, $linkID1); // Verify user, otherwise prompt again //// If there are no rows returned (which states the user name and/or //// password was not correct) then recall the userAuth function if (mysql_numrows($login_results)==0) { userAuth(); //// If a row is returned (stating that the user name and password were //// correct) then store the user name into the $login_name variable } else { list($login_name) = mysql_fetch_row($login_results); } } // Start a Session //// It is necessary to tell PHP when to open up its eyes and prepare //// for the possibility of having to get to know an end user. This //// process is accomplished through the function session_start(). //// This function initializes the session data or continues the current //// session that is being passed by a request, such as a GET, POST or a cookie. session_start(); // Setup the session "key" //// After starting the session process, it is important to identify the "key" //// by which the user will be remembered. This key is stored on the end users //// machine and is called when interacting with the end user machine with the //// same function; session_id(). If there is not a session_id on the end users //// users computer, then one is created for it if (!session_id()) { session_id(md5(rand(1,5000))); }

// Load the id read in from the URL or the Session ID //// The (int) value will ensure that the value read in is forced //// to be an integer value, this is called type casting. If the //// value read in is not a numeric number (such as a string), the //// the value will be forced to be a zero if (isset($_GET['id'])) { // Load the id read in from the URL $getID = (int) $_GET['id']; //// if there is no id on the URL, then check to see if there is a session //// id out there that can be used to bring the customer back to the last //// image they were viewing } else { // Check to see if there is an image ID assigned to the sessionID //// Prepare the SQL to search for an image ID associated with the session ID $session_SQL = "SELECT image_id FROM sessions WHERE session_ID = '".session_id()."'"; //// Execute the prepared SQL $session_result = mysql_query($session_SQL, $linkID1); //// Check to see if the SQL statement returned any rows $session_rows = mysql_numrows($session_result); //// If the SQL statement returned a row, then store the image ID into the //// $getID variable used for remembering the last image viewed if ($session_rows > 0) { list($getID) = mysql_fetch_row($session_result); } }

Page E-16

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

// Update Date from form entry //// From the HTML form script created, there is a button called Submit //// that will be used when a change to the date is required. The actual //// value of the submit button when selected will be passed through onto //// the web page selected to handle the submission (in this case the same //// same web page). This if will test to see if the submit button has been //// passed across thus stating that the form has been updated and additional //// values have been passed (such as the date which we are looking for) if (isset($_POST['Submit'])) { //// Due to the fact that there are more than one submit button, the name of the //// button that was selected needs to be tested. The first test is to see if //// the update data was selected if ($_POST['Submit'] == 'Update Data') { //// The first step is to update the name of the image. There are no checks //// needed with the name of the image because it is a straight string field //// and only an update is needed. If there is no value in the image name field //// then that empty value will be placed into the database //// The value entered into the form is then passed into a variable that will be //// used in the update $imageName = $_POST['picName']; //// This is the actual SQL that will be used to perform the update of the image //// name against the images table $update_sql = "UPDATE images SET image_name = '$imageName' WHERE id_image = $getID"; //// The SQL is executed and the results of the update are then placed //// into a variable ($update_results) that will be tested to ensure the //// update was successful $update_results = mysql_query($update_sql, $linkID1); //// If the SQL is executed successfully, then the $update_results variable //// will be loaded and a response is provided to the end user making such //// a claim if ($update_results) { print "<p>Image name successfully updated</p>"; //// If the update was not successful, the $update_results variable will be //// empty and the end user will be notified that there was a problem } else { //// The mysql_error() function displays the last error that was //// issued on the MySQL server (in this case, the error that caused //// the update to fail) print "<p>Update aborted, ".mysql_error()."</p>"; } //// The next step is to check and see if there was an entry in the form //// field for the date (in this case picDate). If there was an entry passed //// across, then run some additional tests to make sure it is a good value //// (in this case a valid date). If there is no value in the form field, then //// state so with the else statement that the field was empty when the submit //// button was chosen if (isset($_POST['picDate'])) { // Separate Date Characters //// One of the easist ways to test a date field (make sure it is a valid //// date) is to force the data entry to be certain pattern. The first //// step for the testing of the date is to get each character broken up //// into an array that can then be put together as we see fit. The str_split //// function does just that and creates an array ($dateArray) that has each //// character as a single entity in the array $dateArray = str_split($_POST['picDate']); //// The first four array values are put together to create the year for the //// picture. Again the (int) statement forces the value to be an integer //// value. $year = (int) "$dateArray[0]$dateArray[1]$dateArray[2]$dateArray[3]"; //// The fifth array character (in this case the #4 array because the first //// is identified as zero) will be a dash (-) thus it is skipped and the next //// two characters (#5 and #6) are selected and put together as the month $month = (int) "$dateArray[5]$dateArray[6]"; //// The eighth array character (in this case the #7 array because the first //// is identified as zero) will be a dash (-) thus it is skipped and the next //// two characters (#8 and #9) are selected and put together as the day $day = (int) "$dateArray[8]$dateArray[9]"; //// With the values for the month, day and year now put together in their //// perpective variable, the checkdate function is used to determine if it

Page E-17

Developing Dynamic Web Applications with MySQL and PHP


//// //// //// //// the

Appendix E - Further Practice Solutions

is a good date. If it is a valid date, then an update statement will be sent to the photo_album database to change the date value in the images table. If the date is not valid (either because it is a bad date or the the values were not entered correctly) then a statement is sent back to

//// end user telling them the update was aborted if (checkdate($month, $day, $year)) { //// Now that we have a valid date, it is time to put them all together //// into one variable ($updatedDate) that will be used in the update //// SQL $updatedDate = "$year-$month-$day"; //// This is the actual SQL that will be used to perform the update //// against the images table $update_sql = "UPDATE images SET image_date = '$updatedDate' WHERE id_image = $getID"; //// The SQL is executed and the results of the update are then placed //// into a variable ($update_results) that will be tested to ensure the //// update was successful $update_results = mysql_query($update_sql, $linkID1); //// If the SQL is executed successfully, then the $update_results variable //// will be loaded and a response is provided to the end user making such //// a claim if ($update_results) { print "<p>Date successfully updated</p>"; //// If the update was not successful, the $update_results variable will be //// empty and the end user will be notified that there was a problem } else { //// The mysql_error() function displays the last error that was //// issued on the MySQL server (in this case, the error that caused //// the update to fail) print "<p>Update aborted, ".mysql_error()."</p>"; } //// If the date entered was not valid, then the user is not only told that it //// was not valid, but also how to actually enter the date just in case they //// did not enter it correctly } else { print "<p>Update aborted, the date entered must be a valid date (YYYY-MM-DD)</p>"; } //// If the submit button for the update date was selected but no date was provided //// the end user is told that a date must be entered for the picture to be updated } else { print "<p>Please enter a date for the picture</p>\n"; } //// If the submit button is selected that is connected to deleting the image only //// the delete action will be processed } else if ($_POST['Submit'] == "Delete Image") { //// The following SQL is designed to "delete" the image (select it to false) $delete_sql = "UPDATE images SET active_image = 'FALSE' WHERE id_image=$getID"; //// The prepared SQL is executed agains the images database $delete_results = mysql_query($delete_sql, $linkID1); //// If there is a result back (the SQL was executed successfully) then the //// end user is notified that the image was removed if ($delete_results) { print "<p>Image sucessfully removed</p>"; //// If there is no results returned (the update did not take place successfully, //// then the user is notified that the delete did not take place and //// what the last error received by MySQL was } else { print "<p>Delete aborted, ".mysql_error()."</p>"; }

Page E-18

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

$getID = $_POST['afterID']; //// If the submit button is selected that is connected to adding comments to the //// imagel, then the comment addition is the only action handled } else if ($_POST['Submit'] == "Add Comment") { //// The comment submitted is first sanitized by using the //// mysql_real_escape_string function $update_comment = mysql_real_escape_string($_POST['comment']); //// The SQL is prepared with the login name of the authorized user //// and the comments are added to the comments table $addComm_SQL = "INSERT INTO comments SET id_image = $getID, login_name = '$login_name', comments ='$update_comment'"; //// The prepared SQL is executed against the database $addComm_Result = mysql_query($addComm_SQL, $linkID1); //// If the MySQL server responds with a positive response, then //// the $addComm_Result variable will be set and the end user //// will be notified that the comment was added successfully if ($addComm_Result) { print "<p>Comment Added Successfully!</p>"; //// If the MySQL server did not respond, then there was an error //// and the end user will be provided with comments that were derived //// from the MySQL server error handling } else { print "<p>Problem encountered, ".mysql_error()." </p>"; } } } // Test to see if there is an image ID read in for the // picture to show and it is a valid image ID, if not // use the first valid image id in the database //// Prepare the SQL that will be sent to the MySQL Server //// This particular SQL will lookup the image id entered in //// $getID and test to see if it is a valid image id (active //// customer, active image, actually exists, etc.) $goodID_SQL = "SELECT id_image FROM images, logins, customers WHERE logins.login_name = images.login_name AND logins.email_customer = customers.email_customer AND active_customer = 'True' AND active_image = 'True' AND id_image=$getID"; //// Execute the SQL prepared ($goodID_SQL) against the server $goodID_Result = mysql_query($goodID_SQL, $linkID1); //// Count the number of rows returned. There should be only //// one row returned; however, if the image id is not valid, //// no rows will be returned telling us the image id is not //// valid for one reason or another $goodID_Rows = mysql_numrows($goodID_Result); // Determine the first image ID and the last image ID //// In the event that the image id entered is not valid, it is //// important to provide a valid image to be displayed. The following //// SQL not only determines the first valid image id but also the last //// valid image id (might come in handy and easy to obtain) $imageBound_SQL = "SELECT MIN(id_image), MAX(id_image) FROM images, logins, customers WHERE logins.login_name = images.login_name AND logins.email_customer = customers.email_customer AND active_customer = 'True' AND active_image = 'True'"; //// Execute the SQL prepared ($imageBound_SQL) against the server $imageBound_Result = mysql_query($imageBound_SQL, $linkID1); //// Separate out the results of the SQL (first and last valid image id`s) list($firstID, $lastID) = mysql_fetch_row($imageBound_Result);

Page E-19

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

// Set the imageID to the first image in the table if the id in the URL is bad //// If the count for the number of rows returned (stating if the image id //// is valid) is less than one, then the image id is not valid (zero rows //// were returned) then use the first valid image id to display the associated //// image if ($goodID_Rows < 1) { $getID = $firstID; } // Get the image information for the image id //// Prepare the SQL that will be sent to the MySQL Server //// The image_date and image_name value is also collected for the fourth version //// of our view images script and is used to show the date and name given to the //// image $image_sql = "SELECT image_size, file_name, image_date, image_name FROM images WHERE id_image=$getID"; //// Execute the SQL prepared (#image_sql) against the server $image_results = mysql_query($image_sql, $linkID1); //// Separate out the results of the SQL (size of the image, the file name and //// the name assigned to the image - image_name) list($image_size, $file_name, $image_date, $image_name) = mysql_fetch_row($image_results); // Get current Script Name for linking purposes //// The same web page will be used when moving through the images or updating //// image information and thus the current web page name is stored into a //// variable ($currentLocation) to ensure that the same page is used when //// moving through the images or making updates to the image information $currentLocation = $_SERVER['PHP_SELF']; // Create the left control (going back through the images) //// With the first ID ($firstID) identified, the first step is to test //// the image being displayed. If the image being displayed is the first //// image then there is no need to have a previous image link (nothing to //// go to); otherwise, show a previous link if ($getID != $firstID) { //// This variable ($goodID) will be used in a while loop below. While the //// good ID variable is false, the loop will continue to process; otherwise //// the loop will terminate and display the previous image link $goodID = 'False'; //// This variable ($prevImageID) will be used to determine which image ID //// should be used as the value for the previous image $prevImageID = $getID; //// This while loop will continue to run until the variable $goodID is false //// This variable ($goodID) will be changed to true once a previous image ID //// is set while ($goodID == 'False') { //// During each loop the variable $prevImageID will be set to one less //// until the script finds an image ID value that can be used for the //// previous image link $prevImageID= $prevImageID - 1; //// This SQL is designed to use the $prevImageID variable along with //// numerous tests against the data to determine which image ID should //// be used for the previous image ID in the link $prevImage_SQL = "SELECT id_image FROM images, logins, customers WHERE logins.login_name = images.login_name AND logins.email_customer = customers.email_customer AND active_customer = 'True' AND active_image = 'True' AND id_image=$prevImageID"; //// With the SQL created it is time to execute it against the database $prevImage_Result = mysql_query($prevImage_SQL, $linkID1); //// The number of rows returned are now stored into a variable //// ($prevImage_Rows) $prevImage_Rows = mysql_numrows($prevImage_Result); //// If the number of rows returned is greater than zero, then the //// the image ID can be used for a previous link if($prevImage_Rows > 0) { //// The first step is to terminate the loop - By setting the $goodID //// to True, the while loop will be terminated when it tries to run //// again $goodID = 'True'; //// To be on the safe side, the image ID returned from the SQL - $prevID

Page E-20

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

//// (versus the value sent in) is used in the previous link list($prevID) = mysql_fetch_row($prevImage_Result); //// The actual HTML code is designed and displayed for the previous image //// link print "<a href='$currentLocation?id=$prevID'>&lt;- Previous Image</a>\n"; } } }

// Place the file name obtained and the image size into the // HTML needed to display the image (uploaded_files is the subdirectory // where the images are located) print "<img src=\"uploaded_files/$file_name\" $image_size>\n"; // Create the right control (going forward through the images) //// With the last ID ($lastID) identified, the first step is to test //// the image being displayed. If the image being displayed is the last //// image then there is no need to have a next image link (nothing to //// go to); otherwise, show a next link if ($getID != $lastID) { //// This variable ($goodID) will be used in a while loop below. While the //// good ID variable is false, the loop will continue to process; otherwise //// the loop will terminate and display the previous image link $goodID = 'False'; //// This variable ($nextImageID) will be used to determine which image ID //// should be used as the value for the next image $nextImageID = $getID; //// This while loop will continue to run until the variable $goodID is false //// This variable ($goodID) will be changed to true once a next image ID //// is set while ($goodID == 'False') { //// During each loop the variable $nextImageID will be set to one more //// until the script finds an image ID value that can be used for the //// next image link $nextImageID= $nextImageID + 1; //// This SQL is designed to use the $nextImageID variable along with //// numerous tests against the data to determine which image ID should //// be used for the next image ID in the link $nextImage_SQL = "SELECT id_image FROM images, logins, customers WHERE logins.login_name = images.login_name AND logins.email_customer = customers.email_customer AND active_customer = 'True' AND active_image = 'True' AND id_image=$nextImageID"; //// With the SQL created it is time to execute it against the database $nextImage_Result = mysql_query($nextImage_SQL, $linkID1); //// The number of rows returned are now stored into a variable //// ($nextImage_Rows) $nextImage_Rows = mysql_numrows($nextImage_Result); //// If the number of rows returned is greater than zero, then the //// the image ID can be used for a next link if($nextImage_Rows > 0) { //// The first step is to terminate the loop - By setting the $goodID //// to True, the while loop will be terminated when it tries to run //// again $goodID = 'True'; //// To be on the safe side, the image ID returned from the SQL - $nextID //// (versus the value sent in) is used in the previous link list($nextID) = mysql_fetch_row($nextImage_Result); //// The actual HTML code is designed and displayed for the next image //// link print "<a href='$currentLocation?id=$nextID'>Next Image -&gt;</a>\n"; } } }

Page E-21

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

// Setup image id to go to after the image is "deleted" //// If this was not done, after a deletion it would always //// return to the first picture (not good if you are at picture 300) //// If there is a previous ID value (that is it is not on the first image) then //// that value is used after the image is "deleted" if ($prevID) { $afterID = $prevID; //// If the image "deleted" was the first image, then the next image is displayed //// after the image is deleted } else { $afterID = $nextID; }

// Form for Changing Data (END; needs to have no whitespace in front of it) //// The END commands below helps to provide large chunks of HTML versus having to use //// individual print lines print <<<END <!-- This is HTML Comments code The following is the form that contains the update fields, the name of the form is Update_Image (which is not used but is good practice) and the action is to pass the image id through to the same form --> <form name="Update_Image" method="post" action="$currentLocation?id=$getID"> <!-- The image name field not only displays the current image name but also allows for the image name to be changed --> <p><input name="picName" type="input" id="picName" maxlength="60" value="$image_name"> <!-- The ability to "Delete" an image is now added to the form and placed to the right of the image name --> <input type="submit" name="Submit" value="Delete Image"></p> <!-- The date of the picture is not only displayed but also provides for an update of the date --> <p>Date of Picture: <input name="picDate" type="input" id="picDate" maxlength="10" value="$image_date"> <!-- This hidden form field is not displayed any where on the web page but is used to pass a hidden value on. This value will be used with the delete image button but otherwise will be ignored by the script when it receives it --> <input type="hidden" name="afterID" value="$afterID"> <!-- The submit button is assigned the name Submit and the display for the button is Update Data --> <input type="submit" name="Submit" value="Update Data"> </p> <!-- A table is being created to hold the comments associated with the images The table will be 700 pixels wide with a 1 pixel width border The table will have three columns: The user who made the update, the comment associated with the update and the date the update was made --> <table width="700" border="1"><tr><th scope="col">User</th> <th scope="col">Comment</th><th scope="col">Date</th></tr> END; //// The SQL portion of the script must be accomplished outside of the HTML block above //// Here the SQL is being prepared that will draw the information needed from the //// database to fill the comments table $loadComm_SQL = "SELECT l_name, f_name, comments, log_date FROM logins, comments WHERE logins.login_name = comments.login_name AND comments.id_image = $getID AND comments.active_comment = 'True' ORDER BY log_date"; //// The actual SQL is executed against the MySQL server $loadComm_Results = mysql_query($loadComm_SQL, $linkID1); //// Here each comment associated with the image is read and dealt with //// When there are no longer any comments to handle (rows in the database) while (list($lname, $fname, $comments, $log_date) = mysql_fetch_row($loadComm_Results)) { print "<tr><th>$lname, $fname</th><th>$comments</th><th>$log_date</th>\n"; }

Page E-22

Developing Dynamic Web Applications with MySQL and PHP

Appendix E - Further Practice Solutions

//// The following is the control buttons for adding comments to the images //// This section not only provides the controls but also the closing out of the //// HTML code required to close the table and form print "<tr><th><input name=\"Reset\" type=\"reset\" id=\"Reset\" value=\"Reset\"></th> <th><textarea name=\"comment\" cols=\"40\"></textarea></th> <th><input type=\"submit\" name=\"Submit\" value=\"Add Comment\"></th><tr>\n"; print "</table></form>"; // Store the Session Data to the session table //// Check to see if there is a row associated with the session_id in the sessions table //// Prepare the SQL to search for an image ID associated with the session ID $session_SQL = "SELECT image_id FROM sessions WHERE session_ID = '".session_id()."'"; //// Execute the prepared SQL $session_result = mysql_query($session_SQL, $linkID1); //// Check to see if the SQL statement returned any rows $session_rows = mysql_numrows($session_result); //// If the SQL statement returned a row, then update the image ID if ($session_rows > 0) { //// If the session ID already exists in the sessions table, the following SQL will //// update the image_ID with the last image viewed //// Prepare the SQL to perform the update action $update_session_SQL = "UPDATE sessions SET image_id = $getID WHERE session_id = '".session_id()."'"; //// Execute the prepared SQL $update_session_result = mysql_query($update_session_SQL, $linkID1); //// If the session_id is not in the sessions table, add the session_id and the associated values } else { //// Prepare the SQL to perform the insert action $insert_session_SQL = "INSERT INTO sessions SET session_id = '".session_id()."', image_id = $getID"; //// Execute the prepared SQL $insert_session_result = mysql_query($insert_session_SQL, $linkID1); } ?> </body> </html>

Page E-23

Das könnte Ihnen auch gefallen