Creating A Crud Application With Php

  • July 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Creating A Crud Application With Php as PDF for free.

More details

  • Words: 13,367
  • Pages: 46
Creating a CRUD Application with PHP Lesson 1: Creating a MySQL Database This lesson describes the last preliminary step in developing the Wish List application, that of creating a sample database with test data. To complete the steps in this tutorial, you will need a database in which to store data of wishers. With the NetBeans IDE you can perform all these activities through the IDE interface. Before starting, see the tutorial requirements described in Creating a CRUD Application with PHP - Main page. Creating the User of the Database Before you create a database you need to create its User who will be granted the right to perform any operations on the database. Creating a database User involves: •

Connecting to the MySQL server as the root user.



Connecting to the MySQL system database as a root user. This step is necessary to enable running an SQL command for creating a user because you cannot run an SQL command without being connected to any database.



Executing a user creation MySQL statement.

1. Start the IDE, switch to the Services window, and expand the Databases node. 2. To connect to the MySQL database server, navigate to the MySQL Server node and from the context

menu choose Connect.

The MySQL Server Properties dialog box appears. 3. If you have not previously configured MySQL, a dialog opens in which you fill in the fields: ○

In the Server host name field, type localhost.



In the Server port number field, type 3306.



In the Administrator user name field, type root.



In the Administrator password field, type the root user's password that you set during the installation of the MySQL server.

○ Switch on the Save password checkbox and click OK.

The NetBeans IDE connects to the MySQL server, checks for the databases available through the server, detects the system mysql database, and adds the corresponding new node mysql to the Databases tree.

4. To execute an SQL command, you need to be connected to a database. Because only the MySQL

system is available, you need to connect to it. To connect to the system database, navigate to the mysql node and from the context menu choose Connect. If a connection does not already exist, the New Database Connection dialog box appears. The User Name field is by default filled in with root. In the Password field, enter the root user's password.

The New Database Connection dialog box shows the message "Connection established." Click OK. A new node named jdbc:mysql://localhost:3306/mysql is added to the Databases tree. 5. Navigate to the jdbc:mysql://localhost:3306/mysql node and from the context menu choose

Execute Command.

An SQL Command window opens. In the SQL Command window, use syntax similar to the following statement: 6. CREATE USER 'phpuser'@'localhost' IDENTIFIED BY '!phpuser'

From the context menu, choose Run Statement. If the command is executed successfully, the Status bar shows the message: "SQL Statement(s) executed successfully". If another message is displayed, check the syntax and follow the message hints. Creating the Sample Database To create the database:

1. Navigate to the MySQL Server at localhost:3306 node and from the context menu choose Create

Database. The Create MySQL Database dialog box appears. Fill in the fields: ○

In the Database Name field, enter wishlist.



Switch on the Grant full access to user checkbox and from the drop down list select phpuser@localhost phpuser @ localhost Click OK.

The "Grant full access to user" function does not always work. If it does not work, connect to the database as the root user and send the SQL query GRANT ALL ON wishlist.* TO phpuser@localhost phpuser @ localhost . 2. The New Database Connection dialog box appears. Establishing Connection to the Sample Database In the New Database Connection dialog box, fill in the fields: 1. From the Name drop down list, choose MySQL (Connector/J driver)

2. In the Database URL edit box, specify the host, the port, and the database as follows: jdbc:mysql://localhost:3306/wishlist

3. In the User Name and Password edit boxes, enter the name and the password specified in section

Creating the Owner (User) of the Database (in our example phpuser and !phpuser respectively). Click OK. The corresponding new connection node is displayed in the Databases tree.

4. (Optional) Now you can delete the default mysql connection by navigating to the jdbc:mysql://localhost:3306/

node and choosing Disconnect and then Delete from the context

menu. Designing the Structure of the Sample Database To arrange and store all the necessary data you need two tables: •

A wishers table for storing names and passwords of registered users



A wishes table for storing descriptions of wishes

The wishers table contains three fields: 1. id - the unique ID of a wisher. This field is used as the Primary Key

2. name 3. password The wishes table contains four fields: 1. id - the unique ID of a wish. The field is used as the Primary Key 2. wisher_id - the ID of the wisher to whom the wish belongs. The field is used as the Foreign Key.

3. description 4. due_date - the date by when the wish is requested

The tables are related through the wisher's ID. All the fields are mandatory except due_date in wishes. Creating the Tables 1. To connect to the database, on the jdbc:mysql://localhost:3306/wishlist connection, click the

right mouse button and choose Connect from the context menu. Note: If the menu item is disabled, you are already connected. Continue with step 2. 2. From the same context menu, choose Execute Command. An empty SQL Command window opens. 3. To create the wishers table, a. Type the following SQL query (note that you need to explicitly set character sets to UTF-8 for internationalization): b. CREATE TABLE wishers( c. id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, d. name CHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL UNIQUE, password CHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL )

Note: You can get a unique auto generated number from MySQL by specifying the AUTO_INCREMENT property for a field. MySQL will generate a unique number by incrementing the last number of the table and will automatically add to the auto incremented field. In our example the ID field is auto incremented. e. Click the right mouse button on the query and then choose Run Statement from the context menu. Note: The default storage engine for MySQL is MyISAM, which does not support foreign keys. If you want to use foreign keys, consider using InnoDB as the storage engine. To create the wishes table: a. Type the following SQL query: b. CREATE TABLE wishes( c. id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, d. wisher_id INT NOT NULL, e. description CHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, f. due_date DATE, FOREIGN KEY (wisher_id) REFERENCES wishers(id) )

g. Click the right mouse button on the query and then choose Run Statement from the context menu. To verify that the new tables are added to the database, switch to the Services window and then navigate to the jdbc:mysql://localhost:3306/wishlist connection node. Click the right mouse button and choose Refresh. The nodes wishers and wishes appear in the tree. Entering the Test Data To test your application you will need some data in the database. The example below shows how to add two wishers and four wishes. 1. On the jdbc:mysql://localhost:3306/wishlist connection, click the right mouse button and choose

Execute Command. An empty SQL Command window opens. 2. To add a wisher, use syntax similar to the example below: 3. INSERT INTO wishers (name, password) VALUES ('Tom', 'tomcat');

Click the right mouse button on the query and from the context menu choose Run Statement. Note: The statement does not contain a value for the id field. The values are entered automatically because the field type is specified as AUTO_INCREMENT. Enter another test wisher: INSERT INTO wishers (name, password) VALUES ('Jerry', 'jerrymouse');

4. To add the wishes, use syntax similar to the example below: 5. INSERT INTO wishes (wisher_id, description, due_date) 6. VALUES (1, 'Sausage', 080401); INSERT INTO wishes (wisher_id, VALUES (1, INSERT INTO wishes (wisher_id, 8. VALUES (2, INSERT INTO wishes (wisher_id, VALUES (2,

7.

description) 'Icecream'); description, due_date) 'Cheese', 080501); description) 'Candle');

Select the queries, click the right mouse button on each query and from the context menu choose Run Selection. Note: You can also execute the queries one after another as described in item 2.

9. To view the test data, click the right mouse button on the relevant table and from the context menu

choose View Data.

Lesson 2: Designing the Application. Reading from the Database In this lesson you create and configure the PHP project to develop your application, create a list of pages in the application, and define the relations between them. You will also develop a piece of the basic application functionality and test it against the data you entered in the sample database in lesson 1. Creating a PHP Project For information on creating and configuring a PHP project, see Setting Up a PHP Project. Defining a Page Flow Diagram The scope of your application covers the following use cases: 1. The user views the wish list of a person. 2. The user registers as a new wisher. 3. The user logs in and creates her/his wish list. 4. The user logs in and edits his/her wish list. To cover this basic functionality, you will need to implement the following pages: 1. The "front" page index.php for logging in, registering, and switching to wish lists of other users. 2. The wishlist.php page for viewing the wish list of a particular wisher. 3. The createNewWisher.php for registering as a wisher. 4. The editWishList.php page for editing a wish list by its owner. 5. The editWish.php page for creating and editing wishes.

Basic Functionality: Viewing the Wish List of a Person Now that you have finished the preliminary steps, you can start implementing the basic functionality of your application. Start with viewing the wish list of a wisher. This feature does not involve any validations and can be easily tested as you have already entered the test data into the database. The feature's functionality will be implemented on two pages, index.php and wishlist.php. Create the wishlist.php File 1. Start the NetBeans IDE. 2. Click the right mouse button on the Source files node and from the context menu choose New > PHP File. 3. On the New PHP File panel, in the File Name: edit box, type wishlist and press Finish.

4. According to your project setup, the index.php file is already created. If not, create it as described above. 5. Switch to the Projects window, expand your project node, and double click the index.php file. The index.php file opens in the main IDE editor area. The file contains a template for entering HTML and PHP code.

Note: You can ignore warnings from the HTML validator.

. Transferring Data from index.php to wishlist.php The index.php file will not contain any PHP code so you can easily remove the following block:

This file is used for two purposes: •

Displaying a page with controls for entering data.



Transferring the entered data to another page.

These actions are performed using HTML forms. Each form contains: •

A set of fields that correspond to the controls on the page with their types specified



The destination URL address that corresponds to the page where the entered data must be transferred.

The data is received and processed on the destination page. In our example, the data is entered on the index page (index.php) and transferred to the wishlist.php page. You need to implement data transferring in index.php and data reception in wishlist.php. Internationalizing the Form

To use international UTF-8 characters, insert the following element inside the element, if it is not present. <meta http-equiv="content-type" content="text/html; charset=UTF-8">

HTML Form in index.php Enter the following code block into the body of index.php:

Show wish list of:


The above piece of code consists of the following elements: •

Enclosing tags




The opening
tag that contains the action field for entering the name of the file where the data must be transferred (wishlist.php) and the method to be applied to transferring data (GET). PHP creates a special array $_GET and populate there values of the fields from the original form.



The text that appears on the page: Show wish list of:



A text input field for entering the name of the user whose wish list one wants to view. The name ("user") is the key to pick the data on the destination form.



An input field of the "submit" type with the text "Go". The type "submit" means that the input field appears on the page as a button and the data is transferred when exactly this control is affected.

Testing index.php To test the front index.php page of your application: 1. Click the right mouse button on the Sources node and choose Run Project from the context menu or click the Run Main Project icon project as Main.

on the toolbar if you have set your

2. In the Show wish list of: edit box, enter Tom and click Go. An empty page with the following URL appears: http://localhost:90/Lesson2/wishlist.php?user=tom. This URL indicates that your main page works properly. Receiving and Processing Data in wishlist.php 1. Double click the wishlist.php file. The template that opens is different from index.php. Begin and end the file with and tags as the file will contain HTML code too. 2. 3. 4. 11.

12.To display the title, enter the following code block immediately after the opening tag, before the generated ";?>

The code now looks like this:

Wish List of ";?>
*/ ?>

The PHP code block displays the data that is received through the method GET in the field "user". This data is transferred from index.php where the name of the wish list owner Tom was entered in the text field "user". Repeat the steps from Testing index.php to see that wishlist.php works properly.

13.Delete the commented section in the template PHP block. Paste the following code block where the comments were. This code opens the connection to the database. 14.$con = mysql_connect("localhost", "phpuser", "!phpuser"); 15.if (!$con) { 16. die('Could not connect: ' . mysql_error()); 17.}

mysql_query("SET NAMES 'utf8'");

The code attempts to open a connection to the database and gives an error message if there is a failure. 18.Beneath the code to open the connection to the database, in the same PHP block, type or paste the following code. This code retrieves the ID of the wisher whose wish list was requested: 19.mysql_select_db("wishlist", $con); 20.$wisher = mysql_query("SELECT ID FROM wishers WHERE name='".mysql_real_escape_string($_GET["user"])."'"); $wisherID = mysql_result($wisher, 0); The data is selected from the wishlist database through the $con connection. The

selection criterion is the name received from the index.php as "user". The syntax of a SELECT SQL statement can be briefly described as follows: ○

After SELECT, specify the fields from which you want to get data. An asterisk (*) stands for all fields.



After FROM clause, specify the name of the table from which the data must be retrieved.



The WHERE clause is optional. Specify the filter conditions in it.

Security Note: The $_GET["user"] parameter is escaped in order to prevent SQL injection attacks. See Wikipedia on SQL injections and the mysql_real_escape_string documentation. Although in the context of this tutorial you are not at risk of harmful SQL injections, it is best practice to escape strings in MySQL queries that would be at risk of such an attack. 21.Above the code to retrieve the ID of the wisher, type or paste the following code. This code kills the process and displays an error message if the requested wisher is not found in the database: 22.if (mysql_num_rows($wisher)<1) { 23. die("The person " .$_GET["user"]. " is not found. Please check the spelling and try again" ); }

This PHP block is now complete. The wishlist.php file now looks like this: Wish List of ";?>
$wisherID = mysql_result($wisher, 0); ?>

If you test the application and enter an invalid user, the following message appears.

24.Beneath the PHP block, type or paste the following HTML code block. This code opens a table, specifies the color of its borders (black), and "draws" the table header with the columns "Item" and "Due Date." 25. 26. 27. 28. 29.
ItemDue Date


The tag closes the table.

30.Enter the following PHP code block above the closing tag: 31." . strip_tags($desc,'

').""; echo "". strip_tags($dueDate)."\n"; } mysql_close($con); ?>

Within the code: ○

The SELECT query retrieves the wishes with their due dates for the specified wisher by his ID, which was retrieved in step 4, and stores the wishes and due dates in an array $result.



A loop displays the items of the $result array as rows in the table while the array is not empty.



The tags form rows, the tags form cells within rows, and \n starts a new line.



The strip_tags function removes any html tags from the displayed description and date. Note that
,

, and

tags are allowed in the description. The strip_tags function cannot accept a variable passed as a reference, which is why the variables $desc and $dueDate are created.



The $con connection to the database is closed.

Note: By default, MySQL is configured to be case sensitive. Make sure you type the names of database fields exactly as they are specified during the database table creation. Security note: Strip tags from database entries before displaying them in order to prevent cross-site scripting. Although this is not a risk in the context of this tutorial, it is best practise to always write code that is free of vulnerabilities. 33.To test the application, run the project as described in section Testing index.php.

Lesson 3: Creating a New Application User In this lesson you expand the application with the Create a New Wisher functionality. The implementation will affect the index.php file and two new files will be created named createNewWisher.php and editWishList.php. Adding a Link to Start Creating a New Wisher Enter the following code block into the body of index.php: Still don't have a wish list?! Create now

Where: •

Still don't have a wish list?! is the text that will be displayed on the page next to



is the code that implements a link that opens the



Create now is the text that will be displayed as a link.

the link.

createNewWisher.php page.

Creating New PHP Files Create two new PHP files in your project's Source Files, as described in Lesson 2. •

createNewWisher.php



editWishList.php

Leave editWishList.php with its default content. You will modify this file in later lessons, but you need it to exist now because createNewWisher.php references it. For the remainder of this lesson, you modify createNewWisher.php. Adding an HTML Form for Entering the Data of a New Wisher Type or paste the following HTML block into createNewWisher.php, beneath the PHP block: <meta http-equiv="content-type" content="text/html; charset=UTF-8"> Welcome!


Your name:
Password:
Please confirm your password:


Note: The password type is a special type of a text field where characters are replaced with asterisks. The code presents an HTML form for a user to enter the name and password of the new wisher in the text fields. When the user clicks the "Register" button, the entered data is transferred for validation to the same page, createNewWisher.php. Note: You can ignore warnings from the HTML validator. Validating Data and Adding It to the Database

The PHP block must be above all HTML code, empty lines, or whitespace. The position of the PHP code block is important to enable correct functioning of the redirection statement. Within the PHP block, type or paste the code blocks described below in this section, in the order they are written. Add the following code to validate data: 1. Initialize variables. The first variables pass database credentials and the others are the variables that will be used in the PHP operations. 2. /** database connection credentials */ $dbHost="localhost"; $dbUsername="phpuser"; $dbPasswd="!phpuser"; 3. 4. /** other variables */ 5. $userNameIsUnique = true; 6. $passwordIsValid = true; 7. $userIsEmpty = false; 8. $passwordIsEmpty = false; 9. $password2IsEmpty = false; 10.

11.Below the variables, add an if clause. The parameter of the if clause checks that the page was requested from itself via the POST method. If not, the further validations are not performed and the page is shown with empty fields as described above. 12.if ($_SERVER["REQUEST_METHOD"] == "POST") { 13. }

14.Within the curly braces of the if clause, add another if clause that checks whether the user has filled in the wisher's name. If the text field "user" is empty, the value of $userIsEmpty is changed to true. 15.if ($_SERVER["REQUEST_METHOD"] == "POST") { 16. 17. 18. if ($_POST["user"]=="") 19. $userIsEmpty = true; }

20.Add code that establishes a database connection. If the connection cannot be established, the MySQL error is sent to the output. 21.if ($_SERVER["REQUEST_METHOD"] == "POST") { 22. 23. 24. if ($_POST["user"]=="") { 25. $userIsEmpty = true; 26. } 27.

28. 29. 30. 31. 32.

}

$con = mysql_connect("localhost", "phpuser", "!phpuser"); if (!$con) { die('Could not connect: ' . mysql_error()); } mysql_query("SET NAMES 'utf8'");

33.Add code that checks whether a user whose name matches the "user" field already exists. The code does this by trying to find a wisher ID number for a name matching the name in the "user" field. If such an ID number exists, the value of $userNameIsUnique is changed to "false." 34.if ($_SERVER["REQUEST_METHOD"] == "POST") { 35. 36. 37. 38.

if ($_POST["user"]=="") { $userIsEmpty = true; }

39. 40. 41. 42. 43.

$con = mysql_connect("localhost", "phpuser", "!phpuser"); if (!$con) { die('Could not connect: ' . mysql_error()); }

44.

mysql_query("SET NAMES 'utf8'");

45.

mysql_select_db("wishlist", $con); $wisher = mysql_query("SELECT id FROM wishers WHERE name='". $_POST["user"]."'"); $wisherIDnum=mysql_num_rows($wisher); if ($wisherIDnum) { $userNameIsUnique = false; } }

46.Add an if clause that checks whether the user entered and confirmed a password correctly. The code checks that the Password ("password") and Confirm Password ('password2) fields are not empty in the form and that they are identical. Otherwise the values of the corresponding boolean variables are changed accordingly. 47.if ($_SERVER["REQUEST_METHOD"] == "POST") { 48. 49. 50. 51.

if ($_POST["user"]=="") { $userIsEmpty = true; }

52. 53. 54. 55. 56. 57. 58.

$con = mysql_connect("localhost", "phpuser", "!phpuser"); if (!$con) { die('Could not connect: ' . mysql_error()); } mysql_query("SET NAMES 'utf8'");

59.

mysql_select_db("wishlist", $con); $wisher = mysql_query("SELECT id FROM wishers WHERE name='". $_POST["user"]."'"); $wisherIDnum=mysql_num_rows($wisher); if ($wisherIDnum) { $userNameIsUnique = false; } if ($_POST["password"]=="") $passwordIsEmpty = true;

if ($_POST["password2"]=="") $password2IsEmpty = true; if ($_POST["password"]!=$_POST["password2"]) { $passwordIsValid = false; } }

60. Complete the if clause by adding code that inserts a new entry into the "wishers" database. The code checks that the name of the wisher is specified uniquely and that the password is entered and confirmed validly. If the conditions are met, the code takes the "user" and "password" values from the HTML form and inserts them into the Name and Password columns, respectively, of a new row in the wishers database. After creating the row, the code closes the database connection and redirects the application to the page editWishList.php. 61.if ($_SERVER["REQUEST_METHOD"] == "POST") { 62. 63. 64. 65.

if ($_POST["user"]=="") { $userIsEmpty = true; }

66. 67. 68. 69. 70.

$con = mysql_connect("localhost", "phpuser", "!phpuser"); if (!$con) { die('Could not connect: ' . mysql_error()); }

71.

mysql_query("SET NAMES 'utf8'");

72. 73.

mysql_select_db("wishlist", $con); $wisher = mysql_query("SELECT id FROM wishers WHERE name='". $_POST["user"]."'"); $wisherIDnum=mysql_num_rows($wisher); if ($wisherIDnum) { $userNameIsUnique = false; } if ($_POST["password"]=="") $passwordIsEmpty = true; if ($_POST["password2"]=="") $password2IsEmpty = true; if ($_POST["password"]!=$_POST["password2"]) { $passwordIsValid = false; }

74.

if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && ! $password2IsEmpty && $passwordIsValid) { mysql_select_db("wishlist", $con); mysql_query("INSERT wishers (name, password) VALUES ('". $_POST["user"]."', '".$_POST["password"]."')"); mysql_close($con); header('Location: editWishList.php' ); exit; } }

Displaying Error Messages in the Input Form Now you implement the display of error messages when the entered data is invalid. The implementation is based on the validations and changes to the values of the boolean variables described in Validating Data and Adding It to the Database.

1. Enter the following PHP code block inside the HTML input form, below the wisher's name input: 2. Welcome!
Your name:
3. 4. 5. 6. 7. 8. 9. 10. 11.

"); } if (!$userNameIsUnique) { echo ("The person already exists. Please check the spelling and try again"); 12. echo ("


14.Enter the following PHP code block inside the HTML input form below the code for the password input: 15.Password:
16. 17."); 21. } ?>

22.Enter the following PHP code blocks inside the HTML input form below the code for password confirmation: 23.Please confirm your password:
24. 25. 26. 27."); 31. } 32. if (!$password2IsEmpty && !$passwordIsValid) { 33. echo ("The passwords do not match!"); 34. echo ("


Testing the Create New Wisher Functionality 1. Run the application. The index page opens.

2. On the index page, click the link next to the text Still don't have a wish list? The following form opens:

3. Leave only the Your name field empty and click Register. An error message displays.

4. Enter the name of a registered wisher, for example, Tom in the Your name field, fill in the other fields correctly, and click Register. An error message displays. 5. Fill in the Password and Please confirm your password fields with different values and click Register. An error message displays. 6. Enter Bob in the Your name field, specify the same password in both password fields and click Register. The page that opens is empty but the redirection passed correctly as the URL ends with editWishList.php:

7. To check that the data is stored in the database, navigate to wishers on the Services window below the wislist1 node and from the context menu choose View Data

Lesson 4: Optimizing the Code with Classes and Objects In this lesson you optimize the code to facilitate maintaining it in the future. This affects the files createNewWisher.php and wishlist.php. Additionally, a new file called db.php is created. Your application's code contains several similar blocks with queries to the database. To make the code easier to read and maintain in the future, you can extract these blocks, implement them as functions of a separate class called WishDB, and place WishDB in db.php. Afterwards you can include the db.php file in any PHP file and use any function from WishDB without code duplication. Such an approach ensures that any changes to queries or functions will be made in one place and you will not have to parse the entire application code. When you use a function from WishDB, you do not change the value of any of WishDB's variables. Instead, you use the WishDB class as a blueprint for creating an object of WishDB, and you change the values of variables in that object. When you finish working with that object, it is destroyed. Because the values of the WishDB class itself are never changed, you can reuse the class an unlimited number of times. In some cases you may want to have multiple instances of a class in existance at the same time, and in other cases you may prefer a "singleton" class, where you only have one instance in existance at any one time. WishDB in this tutorial is a singleton class. Note that the term for creating an object of a class is "instantiating" that class, and that another word for an object is an "instance" of a class. The general term for programming with classes and objects is "objectoriented programming," or OOP. PHP 5 uses a sophisticated OOP model. See php.net for more information. Creating the db.php File Create a new subfolder in the Source Files folder. Name the folder Includes. Create a new file named db.php and place it in Includes. Later you can add more files to this folder that will be included in other PHP files. To create db.php in a new folder:

1. Click the right mouse button on the Source files node and choose New > Folder from the context menu. The New Folder dialog opens. 2. In the Folder Name field, type Includes. Then click Finish. 3. Click the right mouse button on the Includes node and choose New > PHP File from the context menu. The New PHP File dialog opens. 4. In the File Name field, type db. Then click Finish.

Creating the WishDB Class To create the WishDB class, you need to initialize the variables of the class and implement a constructor of the class. Open the file db.php and type the following code in it:

The object (or "instance") of the WishDB class is stored in the $instance variable. In the code above, it is declared null. You also declare database configuration variables for storing the name and password of the database owner (user), the name of the database, and the database host. All these variable declarations are "private," meaning that the initial values in the declarations cannot be accessed from outside the WishDB class (See php.net). Instantiating the WishDB class For other PHP files to use functions in the WishDB class, these PHP files need to call a function that creates an object of ("instantiates") the WishDB class. WishDB is designed as a singleton class, meaning that only one instance of the class is in existance at any one time. It is therefore useful to prevent any external instantiation of WishDB, which could create duplicate instances. Inside the WishDB class, type or paste the following code: //This method must be static, and must return an instance of the object if the object //does not already exist. public static function getInstance() { if (!self::$instance instanceof self) { self::$instance = new self; } return self::$instance; } // The clone and wakeup methods prevents external instantiation of copies of the Singleton class, // thus eliminating the possibility of duplicate objects. public function __clone() { trigger_error('Clone is not allowed.', E_USER_ERROR); } public function __wakeup() { trigger_error('Deserializing is not allowed.', E_USER_ERROR); }

The getInstance function is "public" and "static." "Public" means that it can be freely accessed from outside the class. "Static" means that the function is available even when the class has not been instantiated. As the getInstance function is called to instantiate the class, it must be static. The double-colon (::), called the Scope Resolution Operator, and the self keyword are used to access static functions. Self is used from within the class definition to refer to the class itself. When the double-colon is used from outside the class definition, the name of the class is used instead of self. See php.net on the Scope Resolution Operator. Adding a Constructor to the WishDB Class A class can contain a special method known as a 'constructor' which is automatically processed whenever an instance of that class is created. In this tutorial, you add a constructor to WishDB that connects to the database whenever WishDB is instantiated. Add the following code to WishDB: // private constructor private function __construct() { $this->con = mysql_connect($this->dbHost, $this->user, $this->pass) or die ("Could not connect to db: " . mysql_error()); mysql_query("SET NAMES 'utf8'"); mysql_select_db($this->dbName, $this->con) or die ("Could not select db: " . mysql_error()); }

Note the use of the pseudovariable $this instead of the variables $con, $dbHost, $user, or $pass. The pseudovariable $this is used when a method is called from within an object context. It refers to the value of a variable within that object. Functions in the WishDB Class In this lesson you will implement the following functions of the WishDB class: •

get_wisher_id_by_name for retrieving the id of a wisher based on the wisher's name



get_wishes_by_wisher_id for retrieving a list of wishes of the wisher with a specific id



create_wisher for adding a new wisher record to the table wishers

Function get_wisher_id_by_name The function requires the name of a wisher as the input parameter and returns the wisher's id.

Type or paste the following function into the WishDB class, after the WishDB function: public function get_wisher_id_by_name ($name) { $name = mysql_real_escape_string($name); $result = mysql_query("SELECT id FROM wishers WHERE name = '" . $name . "'"); if (mysql_num_rows($result) > 0) return mysql_result($result, 0); else return null; } The code block executes the query "SELECT ID FROM wishers WHERE Name = '" . $name . "'",

where $name is the name of the wisher. The query result is an array of id's from the records that meet the query. If the array is not empty this automatically means that it contains one element because the field name is specified as UNIQUE during the table creation. In this case the function returns the first element of the $result array (the element with the zero numbered). If the array is empty the function returns null.

Security Note: The $name string is escaped in order to prevent SQL injection attacks. See Wikipedia on SQL injections and the mysql_real_escape_string documentation. Although in the context of this tutorial you are not at risk of harmful SQL injections, it is best practice to escape strings in MySQL queries that would be at risk of such an attack.

Function get_wishes_by_wisher_id

The function requires the id of a wisher as the input parameter and returns the wishes registered for the wisher. Enter the following code block: public function get_wishes_by_wisher_id($id) { return mysql_query("SELECT * FROM wishes WHERE wisher_id=" . $id); } The code block executes the query "SELECT * FROM wishes WHERE wisher_id=" . $id and

returns a resultset which is an array of records that meet the query. The selection is performed by the wisher_id, which is the foreign key for the table wishes. Function create_wisher

The function creates a new record in the wishers table. The function requires the name and password of a new wisher as the input parameters and does not return any data. Enter the following code block: public function create_wisher ($name, $password){ $name = mysql_real_escape_string($name); $password = mysql_real_escape_string($password); mysql_query("INSERT INTO wishers (name, password) VALUES ('" . $name . "', '" . $password . "')"); } The code block executes the query "INSERT wishers (Name, Password) VALUES ('".$name."', '".$password."')", where $name is the name of the new wisher and $password is the wisher's

password. The query adds a new record to the "wishers" table with the fields "name" and "password" filled in with the values of $name and $password respectively.

Refactoring Your Application Code Now that you have a separate class for working with the database, you can replace duplicated blocks with calls to the relevant functions from this class. This will help avoid misspelling and inconsistency in the future. Code optimization that does not affect the functionality is called refactoring. Refactoring the wishlist.php File Start with the wishlist.php file because it is short and the improvements will be more illustrative. 1. At the top of the block, enter the following line to enable the use of the db.php file: require_once("Includes/db.php");

2. Replace the following code block: 3. $con = mysql_connect("localhost", "phpuser", "!phpuser"); 4. if (!$con) { 5. die('Could not connect: ' . mysql_error()); 6. } 7. 8. mysql_query("SET NAMES 'utf8'"); 9. mysql_select_db("wishlist", $con); 10.$wisher = mysql_query("SELECT ID FROM wishers WHERE name='".mysql_real_escape_string($_GET["user"])."'"); 11.if (mysql_num_rows($wisher)<1) { 12. die("The person " .$_GET["user"]. " is not found. Please check the spelling and try again" ); 13.} $wisherID = mysql_result($wisher, 0);

with the following lines of code: $wisherID = WishDB::getInstance()->get_wisher_id_by_name($_GET["user"]);

if (!$wisherID) { die("The person " .$_GET["user"]. " is not found. Please check the spelling and try again" ); }

This code first calls the getInstance function in WishDB. getInstance returns an instance of WishDB, and the code calls the get_wisher_id_by_name function within that instance. If the requested wisher is not found in the database, the code kills the process and displays an error message. No code is necessary here for opening a connection to the database. The connection is opened by the constructor of the WishDB class. If the name and/or password changes, you need to update only the relevant variables of the WishDB class. 14.Replace the following code: $result = mysql_query("SELECT * FROM wishes WHERE Wisherid=". $wisherID); with a call of the function get_wishes_by_wisher_id: $result = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID);

15.Remove the following line: mysql_close($con);

The code is not necessary because the connection to the database is automatically closed as soon as the WishDB object is destroyed. Refactoring the createNewWisher.php File

Refactoring will not affect the HTML input form or the code for displaying the related error messages. 1. At the top of the block, enter the following code to enable the use of the db.php file: require_once("Includes/db.php");

2. Replace the following code block: 3. $con = mysql_connect($dbHost, $dbUsername, $dbPasswd); 4. if (!$con) { 5. die('Could not connect: ' . mysql_error()); 6. } 7. mysql_query("SET NAMES 'utf8'"); 8. 9. mysql_select_db("wishlist", $con); 10.$wisher = mysql_query("SELECT id FROM wishers WHERE name='".$_POST["user"]."'"); 11.$wisherIDnum=mysql_num_rows($wisher); 12.if ($wisherIDnum) { 13. $userNameIsUnique = false; 14.}

with code that calls that gets an instance of WishDB and calls the get_wisher_id_by_name function from that instance: $wisherID = WishDB::getInstance()->get_wisher_id_by_name($_POST["user"]); if ($wisherID) { $userNameIsUnique = false; } The WishDB object exists as long as the current page is being processed. It is destroyed

after the processing is completed or interrupted. The code for opening a connection to the database is not necessary because this is done by the WishDB function. The code for closing the connection is not necessary because the connection is closed as soon as the WishDB object is destroyed. 15.Replace the following code block:

16.if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { 17. mysql_select_db("wishlist", $con); 18. mysql_query("INSERT wishers (name, password) VALUES ('".$_POST["user"]."', '".$_POST["password"]."')"); 19. mysql_close($con); 20. header('Location: editWishList.php' ); 21. exit; }

with:

if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { WishDB::getInstance()->create_wisher($_POST["user"], $_POST["password"]); header('Location: editWishList.php' ); exit; }

Lesson 5: Adding Security. Implementing Application User Logon In this lesson you implement the logon functionality for a wisher. This affects the following files: •

index.php



createNewWisher.php



editWishlist.php



db.php

Implementing the Logon functionality consists of the following steps: •

Saving the wisher's ID in the Session upon the creation of a wisher



Validating that the user who attempts to edit a wish list is logged in



Logging on wisher from the index.php page

Saving the Wisher's ID in the Session Upon Creation A Session is a persistent storage for transferring information from one page to another without using an HTML input form. This functionality is supported through a predefined PHP array $_SESSION. For the sake of security, after a new wisher is created he should be logged on automatically without filling in a form. Therefore you need to modify the createNewWisher.php file to implement the following functionality: •

Add a new wisher to the database.



Open a session.



Store the wisher's name in the session.



Transfer the wisher's name in the session when the wisher is redirected to the editWishList.php page.

In the createNewWisher.php file, locate the line: WishDB::getInstance()->create_wisher($_POST["user"], $_POST["password"]);

and enter the following code block right below: session_start(); $_SESSION["user"] = $_POST["user"];

The code block starts a session, which means opening the $_SESSION array for entering or retrieving data. Then the code adds an element to the $_SESSION array. The added element contains a value and an identifier (key). The value is the name of the newly created wishers and the identifier is "user". Then the program redirects the wisher to the editWishList.php page.

Validating User Logon When a user reaches the editWishList.php page the application should confirm that the page is accessed by the same person who was just registered on the createNewWisher.php page.

Implementing this functionality consists of two steps: •

Retrieving the wisher's name from the Session



Redirecting the user to the index.php if retrieving the wisher's name from the Session failed

Retrieving the Wisher's Name from the Session Replace the default code in the PHP block of editWishList.php with the following: session_start(); if (array_key_exists("user", $_SESSION)) { echo "Hello " . $_SESSION["user"]; }

The code block opens the $_SESSION array for retrieving data and verifies that $_SESSION contains an element with the identifier "user". If the check is successful, the code prints a welcome message. To check that the session is implemented correctly: 1. Run the createNewWisher.php file and create a new wisher, for example Jack. The editWishList.php opens with Hello Jack. 2. Clear session cookies in your browser or end the session and run editWishList.php from the IDE. The editWishList.php file opens with Hello because no user has been transferred through a session. This is not correct because it enables someone who is not logged in and not registered to create or edit a wish list. In order to avoid this, the user needs to be redirected to the index.php page. Redirecting a User Who Is Not Logged In Add the following code block to editWishList.php, below the if clause: else { header('Location: index.php'); exit; }

The code redirects the user to the index.php page and cancels PHP code execution. To check that the functionality is implemented correctly, run the editWishList.php file. The expected result is that the index.php page opens.

Logging In from the index.php Page The logon from the index.php page consists of two steps: •

Entering the user's name and password in an HTML input form and submitting the data for validation to the index.php page.



Validating the logon

HTML Form for Logon on index.php In the index.php file, enter the following code before the closing tag: Username: Password


Note: You can ignore warnings from the HTML validator. The code presents an HTML form that enables entering the name and password of the user in the text fields. When the user clicks Edit My Wish List, the data is transferred to the same page, index.php.

Logon Validation

Logon validation involves: •

Checking where the user was redirected from.



Verifying the user's name and password.



Saving the user name to the Session and redirecting the user to the editWishList.php page or Displaying an error message.

Source of Redirection

A user may access the index.php page on starting the application, or from the editWishList.php page, or when redirected from the index.php page after entering name and password. Because only in the last case is the HTML request method POST used, you can always learn where the user was located when they accessed index.php. In the index.php file, create a block above the HTML block, with the following code:
?>

The code block enables the use of the db.php file and initializes the $logonSuccess variable, which will be used later to display error messages. Verifying the User's Credentials Replace the comment // verify user's credentials with the following code block: if ($_SERVER["REQUEST_METHOD"] == "POST"){ if (WishDB::getInstance()->verify_wisher_credentials($_POST["user"], $_POST["userpassword"]) == 1) { session_start(); $_SESSION["user"] = $_POST["user"]; header('Location: editWishList.php'); } else { $logonSuccess = false; } }

If the request method is POST, which means that the user was redirected from the index.php page, the code block calls the verify_wisher_credentials function with the name and password entered during logon. If the verify_wisher_credentials function returns 1, which means that a wisher with the specified combination of name and password is registered in the database, the $_SESSION array is opened for entering data. Then a new element is added to the $_SESSION array. The element contains a value and an identifier (key). The value is the name of the wisher and the identifier is "user". Then the user is redirected to the editWishList.php page in order to edit the wish list. If the verify_wisher_credentials function does not return 1, the value of the $logonSuccess variable is changed to false. The value of the variable is used in displaying an error message. Function verify_wisher_credentials

In order to implement verification of the wisher's credentials, you need to add a new function to the WishDB class in the db.php file. The function requires a name and a password as the input parameters and returns 0 or 1. Enter the following code block:

public function verify_wisher_credentials ($name, $password){ return mysql_num_rows(mysql_query("SELECT * FROM wishers WHERE name = '" . $name . "' AND password = '" . $password . "'")); } The code block executes the query "SELECT * FROM wishers WHERE Name = '" . $name . "' AND Password = '" . $password . "'" and returns the number of records that meet the

specified query. 1 is returned if such record is found and 0 is returned if there is no such record in the database. Displaying Error Messages In order to enable the application to display error messages, enter the following code block into the logon form in index.php, below the input fields but above the button:

The code block checks the value of the $logonSuccess variable and if it is false, displays an error message.

Testing the Logon from the index.php Page To check that the logon functionality works correctly on the index.php front page: 1. Run the application. 2. On the index.php page, enter Tom in the Username edit box and Tim in the Password edit box. 3. Press Edit My Wish List. An error message is displayed:

4. Enter Tom in the Username edit box and tomcat in the Password edit box. 5. Press Edit My Wish list. The editWishList.php page is displayed:

Lesson 6: Writing a New Entry into the Database In this lesson you expand the application functionality with two features: •

Adding a new wish



Returning to the front index.php page

The implementation affects the editWishList.php file and a new file editWish.php is created. Submitting a New Wish The user submits a new wish in the following steps: 1. The user logs in, switches to the editWishList.php page, and presses the Add Wish button. The editWish.php page opens, displaying an HTML form. 2. In the HTML form, the user enters a description of a wish and possibly the date by when he/she wants it and presses the Save Changes button. 3. If a form is submitted without a description of the wish, the user is returned to the form to try again. If the user submitted a due date but no description, that date is redisplayed when the form reloads.

To enable this procedure for the user, you add the following functionality to the application: •

User interface components, consisting of an HTML form for adding wishes and a button in editWishList.php that redirects the user to the form.



Code for redisplaying the due date if an incomplete form is submitted.

Adding the User Interface Components

To add functionality for adding a new wish: 1. Implement the Add Wish button. In the editWishList.php file, enter the following HTML form below the PHP block: 2. 3. 4. 5. 6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7. 8. 9.
10. 11.
12.

Note: You can ignore warnings from the HTML validator. The form contains an "Add Wish" input field of the submit type. This field implements the "Add Wish" button. When the user clicks Add Wish, they are redirected to the editWish.php page. Because no data is transferred through this form, no Server Request method is used. 13.Add a table above the Add Wish button that displays the existing wishes for the wisher. Type or paste the following code (similar to wishlist.php): get_wisher_id_by_name(mysql_real_escape_string($_SESSION["user"])); $result = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID); while($row = mysql_fetch_array($result)) { strip_tags($row["description"],'

'); echo "

"; strip_tags($row["due_date"],'

'); echo "

"; echo "\n"; } ?>
ItemDue Date
" . $row["description"]."".$row["due_date"]."


14.Create the editWish.php file in the Source Files folder.

15.In editWish.php, implement the Add Wish form. Type or paste the following code below the block: 16. 17. 18. 19. 20. 21. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 22. 23. 24.
Describe your wish:
When do you want to get it?
25.
26.

The Add Wish form contains: •

Two empty text fields for entering the wish description and due date.



The texts to be printed next to the input fields.



A submit field that represents a Save Changes button



A submit field that represents a Back to the List button for returning to the editWishList.php page

Upon pressing the Add Wish button, the form submits the entered data to the same page, editWish.php, through the Request method POST. Redisplaying the Due Date after an Unsuccessful Submission

If the user does not fill in a description in the Add Wish form, an error message is displayed and the user returns to the editWish.php page. When the user returns to editWish.php, the Add Wish form should show the value of dueDate if it was entered. In the current implementation of the form, both fields are always empty. To keep entered values, you need to save the data of the new wish in an array. The array will consist of two elements named description and due-date. You then need to change the Add Wish form so it retrieves the value of the dueDate field from the array. Note: The code that reloads the input form if no description is entered is included in the code that validates the data and enters it to the database. This code is not described in this section. The code in this section only preserves the value of dueDate so that it is displayed if the form is reloaded . To redisplay the input form after the user submits it unsuccessfully: 1. Type or paste the following code block inside the HTML element of editWish.php, directly above the input form: 2. $_POST["wish"], "due_date" => $_POST["dueDate"]); else $wish = array("description" => "", "due_date" => ""); ?>

The code checks which Request Server method was used for transferring the data and creates an array named $wish. If the method is POST, which means that the input form is displayed after an unsuccessful attempt to save a wish with an empty description, the elements description and due_date accept the values transferred through POST. If the method is not POST, which means that the input form is displayed for the first time after redirection form the editWishList.php page, the elements description and due_date are empty.

Note: In either case the description is empty. The difference is only in the dueDate. 4. Update the Add Wish form so that the values of its input fields are retrieved from the $wish array. Replace the lines in the Add Wish form: 5. Describe your wish:
When do you want to get it?


with:

Describe your wish:
When do you want to get it?


Verifying the Wisher's Logon In the editWish.php file, enter the following session handling code inside the block at the top of the file: session_start(); if (!array_key_exists("user", $_SESSION)) { header('Location: index.php'); exit; }

The code: •

Opens the $_SESSION array for retrieving data..



Verifies that the array $_SESSION contains an element with the identifier "user".



If the check fails, which means that the user is not logged on, redirects the application to the front index.php page and cancels the PHP processing.

To check that session handling works correctly, run the editWish.php file from the IDE. The index.php page opens, because no user has been transferred to the editWish.page through a session. Inserting the New Wish to the Database After the user submits a new wish, the application needs to add the wish to the "wishes" database. To enable this functionality, add the following code to the application: •



Add two more auxiliary functions to the WishDB class in db.php. ○

One function adds a new record to the wishes table.



The other function converts dates into the format that the MySQL databases server supports.

Add code to editWish.php that will use the new auxilliary functions in WishDB to enter the new wish into the database.

Adding the insert_wish Function to WishDB

This function requires the wisher's id, a description of the new wish, and the due date of the wish as the input parameters and enters this data to the database in a new record. The function does not return any values. Open db.php and type or paste the following code into the WishDB class: function insert_wish($wisherId, $description, $duedate){ $description = mysql_real_escape_string($description); return mysql_query("INSERT INTO wishes (wisher_id, description, due_date)" . " VALUES (" . $wisherId . ", '" . $description . "', " . $this->format_date_for_sql($duedate) . ")"); }

The code calls the function format_date_for_sql to convert the entered due date into a format that can be processed by the MySQL server. Then the query INSERT INTO wishes (wisher_id, description, due_date)is executed to enter the new wish to the database.

Adding the format_date_for_sql Function to WishDB

The function requires a string with a date as the input parameter. The function returns a date in the format that can be processed by the MySQL database server or null if the input string is empty. Type or paste the following code into the WishDB class: function format_date_for_sql($date){ if ($date == "") return "NULL"; else { $dateParts = date_parse($date); return $dateParts["year"]*10000 + $dateParts["month"]*100 + $dateParts["day"]; } }

If the input string is empty, the code returns NULL. Otherwise, the internal date_parse function is called with the $date as the input parameter. The date_parse function returns an array that consists of three elements named $dateParts["year"], $dateParts["month"], and $dateParts["day"]. The final output string is constructed of the elements of the $dateParts array. Entering the New Wish Record in the Database

Now that you have developed the auxiliary functions, add code to validate the new wish data and enter the data to the database if it is valid. If the data is not valid, the code must reload the Add Wish form. If the data is invalid because no description has been entered but there is a due date, the due date is saved and redisplayed when the form reloads, thanks to code you developed earlier. Enter the following code inside the block of editWish.php, below the session handling code: require_once("Includes/db.php"); $wisherId = WishDB::getInstance()->get_wisher_id_by_name($_SESSION["user"]); $wishDescriptionIsEmpty = false; if ($_SERVER["REQUEST_METHOD"] == "POST"){ if (array_key_exists("back", $_POST)) { header('Location: editWishList.php' ); exit; } else if ($_POST["wish"] == "") { $wishDescriptionIsEmpty = true; } else { WishDB::getInstance()->insert_wish($wisherId, $_POST["wish"], $_POST["dueDate"]); header('Location: editWishList.php' ); exit; } }

The code performs the following functions: •

Enables the use of the db.php file



Gets or creates an instance of the class WishDB



Retrieves the id of the wisher who is attempting to add a wish by calling the function get_wisher_id_by_name



Initializes the $wishDescriptionIsEmpty flag, which will be used later for showing error messages.



Checks that the Request method is POST, which means that the data was submitted from the form for entering the wish data on the editWish.php page itself.



Checks whether the $_POST array contains an element with the "back" key

If the $_POST array contains an element with the "back" key, the Back to the List button was pressed before submitting the form. In this case the code redirects the user to the editWishList.php without saving any data that was entered in the fields and stops PHP processing. If the $_POST array does not contain an element with the "back" key, the data was submitted by pressing the Save Changes button. In this case the code validates whether the wish description is filled in. The code does it by checking whether the element with the "wish" key in the $_POST array is empty and, if the key is empty, changes the $wishDescriptionIsEmpty flag to true. Note that with no further code executed in the PHP block, the Add Wish form reloads. If the Back to the List button was not pressed and the wish description is filled in, the code calls the function insert_wish with the wisher's id, the description, and the due date for the wish as the input parameters. The code then redirects the user to the editWishList.php page and stops the PHP processing. Displaying Error Messages If the user attempts to save a wish but has not entered a description for it, an error message must be displayed. Enter the following block inside the HTML input form, below the "Describe your wish" input field: "; ?> The error message is displayed if the $wishDescriptionIsEmpty flag is true. The flag is

processed during the input form validation.

Returning to the Front index.php Page The user should be able to return to the front page of the application at any time by pressing a button. To implement this functionality, enter the following HTML input form in the editWishList.php file, before the closing tag:


The form redirects the user to the front index.php page upon pressing the Back to Main Page button.

Testing the Add Wish Functionality 1. Run the application. On the index.php page, fill in the fields: in the Username field, enter "Tom", in the Password field, enter "tomcat".

2. Press the Edit My Wish List button. The editWishList.php page opens.

3. Press the Back to Main Page button. The index.php page opens. 4. Logon as Tom and press the Edit My Wish List button again. The editWishList.php page opens. 5. Press the Add Wish button. The editWish.php page opens. Fill in the form.

Press the Back to the List button. The editWishList.php page opens but the entered wish is not added. 6. Press the Add Wish button again. The editWish.php page opens. Fill in the due date and leave the description empty. Press the Save Changes button. The editWish.php page displays the input form with an error message and filled in due date. 7. Press the Add Wish button again. The editWish.php page opens. Fill in the form and press the Save Changes button. The editWishList.php page shows an updated list of

wishes.

Lesson 7: Updating and Deleting Entries in the Database In this lesson you will expand the application's functionality with two features: •

Editing a wish



Deleting a wish

The implementation of these two features will affect the editWishList.php and editWish.php files. A new file deleteWish.php will be created. The current document is a part of the Creating a CRUD Application in the NetBeans IDE for PHP tutorial. Editing a Wish The functionality supports the following use case: •

On the editWishList.php page, the user presses the Edit button to the right of a wish. The editWish.php page with the data of the selected wish opens.



The user changes the description and/or the due date of the wish and presses the Save Changes button.



If the description is not filled in, an error message is displayed and the user returns to the editWish.php page.



If the description is filled in, the application returns to the editWishList.php page, where the wish is updated.

The implementation consists of the following steps: •

Adding an Edit button on the editWishList page



On the editWish.php page, updating the array $wish for storing wish data



Updating the input form on the editWish.php page..



Validation of the submitted data and updating the wish in the database..

Implementing the Edit Button

In editWishList.php, a table with the wishes of a wisher is implemented by a loop (a while statement) that displays rows with wishes while the wishes are selected from the database. Add an Edit button as the extreme right cell in a row. 1. To transfer the ID of a wish through the HTML input form, store it in a variable. Enter the following code line at the end of the while loop: 2. $wishID = $row["id"]; ?>

3. To implement the Edit button, add a table inside the "while" loop. To put an HTML table inside the loop, first delete the closing curly braket from the loop, then type or paste the following code beneath the PHP block. The while loop is now closed by the bracket in the PHP block you added after the table, after the echo "\n"; operation. 4. 5.
6. 7. 8.
9. 10.\n"; 12.} ?>

The entire table, including the form with the Edit button inside the while loop, now looks like this: get_wisher_id_by_name(mysql_real_escape_string($_SESSION["user"])); $result = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID); while($row = mysql_fetch_array($result)) { strip_tags($row["description"],'

'); echo "

"; strip_tags($row["due_date"],'

'); echo "

"; echo "\n"; $wishID = $row["id"]; ?> \n";

} ?>
ItemDue Date
" . $row["description"]."".$row["due_date"]."
>"/>



The form contains a submit field, which implements the Edit button, and a hidden field wishID for transferring the ID of the wish displayed to left of the Edit button. The ID of the wish is stored in the $wishID variable. 13.Remove the first echo "\n"; operation, the one above $wishID = $row["id"]. Otherwise you close the row before the last and your table will not display correctly. Expanding the $wish Array

Upon pressing the Edit button on the editWishList.php page, the ID of the selected wish is transferred to the editWish.php page through the Server Request method GET. To store the id of the wish, you need to add a new element to the $wish array. As when adding a new wish, the input form can be accessed both from the editWishList.php page and from the editWish.php page after an unsuccessful attempt to save. The cases are distinguished by the Server Request method through which the data is transferred. GET indicates that the form is displayed when the user first gets to the page by pressing Edit Wish. POST indicates that the user is redirected to the form after attempting to save a wish without a description. Replace the PHP block in the HTML above the EditWish input form with the following:

$_POST["wishID"], "description" => $_POST["wish"], "due_date" => $_POST["dueDate"]); else if (array_key_exists("wishID", $_GET)) $wish = mysql_fetch_array(WishDB::getInstance()->get_wish_by_wish_id($_GET["wishID"])); else $wish = array("id" => "", "description" => "", "due_date" => ""); ?>

The code initializes the $wish array with three elements: id, description, and due_date. The values of these elements depend on the Server Request method. If the Server Request method is POST, the values are received from the input form. Otherwise, if the Server Request method is GET and the $_GET array contains an element with the key "wishID", the values are retrieved from the database by the function get_wish_by_wish_id. Finally, if the Server Request method is neither POST nor GET, which means the Add New Wish use case takes place, the elements are empty. The preceding code covers the cases for creation and editing wishes. Now you need to update the input form so that it can be also used for both cases. Updating the HTML Input Form - Unifying the Implementation of Creation and Editing Currently the input form works for creation of a new wish when the wish has no id. To unify the tasks of creating and editing wishes, you need to add a hidden field for transferring the ID of a wish. The value of the hidden field must be retrieved from the $wish array. The value must be an empty string during the creation of a new wish. If the wish is edited, the value of the hidden field must change to the ID of the wish. To create this hidden field, add the following line to the top of the EditWish input form: " />

Updating the Wish in the Database

Now you need to update the code that verifies the input data and inserts the wish to the database. The current code does not distinguish between creating a new wish case and updating an existing one. In the current implementation, a new record is always added to the database because the code does not verify the value of the wish ID transferred from the input form. You need to add the following functions: •

If the transferred element "wishID" is an empty string, create a new wish.



Otherwise, if the element "wishID" is not an empty string, update the wish.

To update editWish.php so that it verifies if a wish is new and updates it if it is not new: 1. Add the update_wish function to db.php. 2. public function update_wish($wishID, $description, $duedate){ 3. $description = mysql_real_escape_string($description); return mysql_query("UPDATE wishes SET description = '" . $description . "', due_date = " . $this->format_date_for_sql($duedate) . " WHERE id =" . $wishID); }

4. Add the get_wish_by_wish_id function to db.php. 5. public function get_wish_by_wish_id ($wishID) { return mysql_query("SELECT * FROM wishes WHERE id = " . $wishID); }

6. In the main PHP block of editWish.php, add a condition to the else statement that inserts the wish to the database, changing it to an else if statement: else if ($_POST["wishID"]=="") { WishDB::getInstance()->insert_wish($wisherId, $_POST["wish"], $_POST["dueDate"]);

header('Location: editWishList.php' ); exit; }

7. Type or paste another else if statement below the one you just edited: 8. else if ($_POST["wishID"]!="") { WishDB::getInstance()->update_wish($_POST["wishID"], $_POST["wish"], $_POST["dueDate"]); header('Location: editWishList.php' ); exit; }

The code checks that the wishID element in the $_POST array is not an empty string, which means that the user was redirected from the editWishList.php page by pressing the Edit button and that the user has filled in the description of the wish. If the check is successful, the code calls the function update_wish with the input parameters wishID, description, and dueDate. These parameters are received from the HTML input form through the POST method. After update_wish is called, the application is redirected to the editWishList.php page and the PHP processing is canceled. Testing the Edit Wish Functionality 1. Run the application. On the index.php page, fill in the fields: in the Username field, enter "Tom", in the Password field, enter "tomcat".

2. Press the Edit My Wish List button. The editWishList.php page opens.

3. Click Edit next to Icecream. The editWish.php page opens.

4. Edit the fields and press Back to the List. The editWishList.php page opens but the changes are not saved.

5. Press Edit next to Icecream. Clear the Describe your wish field and press Save Changes. An error message is displayed.

6. Enter Chocolate icecream in the Describe your wish field and press Save Changes. The editWishList.php page opens with the updated list.

Deleting a Wish Now that you can create, read, and update wishes, add functionality for deleting a wish. To enable the user to delete wishes: 1. Add a delete_wish function to db.php. 2. function delete_wish ($wishID){ return mysql_query("DELETE FROM wishes WHERE id = " . $wishID); }

3. Create a new PHP file named deleteWish.php and enter the following code into the block: require_once("Includes/db.php"); WishDB::getInstance()->delete_wish ($_POST["wishID"]); header('Location: editWishList.php' );

The code enables the use of the db.php file. It then calls the function delete_wish from an instance of WishDB, with the wishID as the input parameter. Finally, the application is redirected to the editWishList.php page. 4. To implement the Delete button, enter the following code block inside the while loop in editWishList.php, directly below the code block for the editWish button: 5. 6.
7. 8. 9.
The HTML input form contains a hidden field for the wishID and a submit button labelled

Delete.

Testing the Delete Wish Functionality To check that the functionality is implemented correctly, press Delete next to any item on the editWishList.php page. The item is no longer on the list.

Lesson 8: Making the Application Look Better Using the CSS Technology In this lesson you learn how to do the following: •

Hide input forms when they are not used by implementing JavaScript functions



Improve the appearance of tables with empty cells.



Define the styles and positioning of page elements by applying Cascading Style Sheet



Implement the application design using divs.

The current document is a part of the Creating a CRUD Application in the NetBeans IDE for PHP tutorial. Hiding Forms

Presently, the main index.php page of your application always displays the entire logon and showWishList forms. To improve the appearance of your application, you can hide the forms and replace them with buttons. When the user presses a button the corresponding hidden form expands. To implement this behavior: 1. Add a <script> block to the index.php file right above the closing tag. 2. Develop two JavaScript functions inside the tags. 3. Make some minor changes to the index.php file JavaScript Functions

JavaScript functions do not require any input parameters and do not return any result. The following code checks the visibility status of the corresponding form and changes it to the opposite status. It also changes the text on the button. To accomplish these changes, enter the following code inside the <script> tags: function showHideLogonForm() { if (document.all.logon.style.visibility == "visible"){ document.all.logon.style.visibility = "hidden"; document.all.myWishList.value = "My Wishlist >>"; } else { document.all.logon.style.visibility = "visible"; document.all.myWishList.value = "<< My Wishlist"; } } function showHideShowWishListForm() { if (document.all.wishList.style.visibility == "visible") { document.all.wishList.style.visibility = "hidden"; document.all.showWishList.value = "Show Wish List of >>"; } else { document.all.wishList.style.visibility = "visible"; document.all.showWishList.value = "<< Show Wish List of"; } }

Updating index.php 1. Add a style attribute to the logon form:
"> The style attribute defines whether the form is hidden or visible. The block is

used to keep the form visible until the user logs on successfully. 2. Enter the following code above the logon input form code:

The code implements a button with the text "My Wishlist >>". The button stands in place of the logon form. Pressing the button calls the showHideLogonForm function. 3. Add a style attribute to the showWishList form: 4. Show wish list of:


5. Enter the following code above the showWishList form:

6. Remove the following code from the form because it is already placed on the button: Show wishlist of:

Improving the Appearance of Tables To make empty cells in tables look better, use the   special character. Below is an example of this method from the wishlist.php file. You can apply it to the table in the editWishList.php file.
get_wishes_by_wisher_id($wisherID); while($row = mysql_fetch_array($result)) { echo ""; echo "\n"; } ?>
ItemDue Date
 " . $row["description"]." ".$row["due_date"]."


Defining Styles Using the Cascading Style Sheet Presently the controls in your application "stick" to each other and are usually placed in the upper left-hand corner of the screen. To improve the appearance of you application's pages, specify the size, position, color, font, and other parameters of controls by defining styles and assigning these styles to particular controls. Styles are defined in a separate Cascading Style Sheet (CSS) file. All the recommendations and suggestions concerning the application design are optional. The style definitions below are intended just to give you an example of improving the application appearance. The settings are appropriate for screen resolution 1024x768 pixel or higher. Creating a CSS File 1. Click the right mouse button on the Source Files node and from the context menu choose New > Cascading Style Sheet. 2. On the Cascading Style Sheet panel, in the File Name edit box enter wishlist. Click Finish.

The new file wishlist.css is shown in the project tree.

Defining CSS Styles

The NetBeans IDE provides a friendly Style Builder code generation tool that enables you to define styles . Just choose the appropriate setting from a list and evaluate the presentation of the sample text in the Preview area. The code to implement the style is generated automatically. All the changes you make to a style are immediately reflected so you can tune the appearance of your application to your taste and habits. Open the wishlist.css file. The file already contains a "root" class, which you can remove. Please, find the CSS styles for the application in the wishlist.css file that you can download here. The code is intuitively clear and contains: •

Two styles: "body" and "input" - that are automatically applied inside any or tag.



CSS classes that are applied when explicitly specified. The names of classes have dots in preposition, for example,.createWishList. Some classes are used several times, for example, the ".error" class is applied to all error messages in the application. Other classes are used only once, for example, ".showWishList", ".logon".

Implementing the Design Using HTML Divs All the recommendations and suggestions concerning the application design are optional. Like the style definitions above they are intended just to give you an example of how to improve the application's appearance. The example below shows how you can improve the appearance of the index.php page. index.php 1. To enable using the CSS classes that you defined, enter the following code inside the block:

The styles "body" and "input" are automatically applied inside the corresponding tags so you do need to indicate them explicitly. 2. To apply any other style (class) to an area, enclose the code that implements the area in the
tags:


Note: When a class is specified within a tag, no dot is required in preposition. 3. You can use embedded
tags:

"> Username: Password:




The class "logon" is applied to the entire form, and the class "error" is applied to an error message within the form.

Lesson 9: Deploying the Application on a Remote Web Server Normally, a real-life PHP application is run on a remote server and is accessed through a File Transfer Protocol (FTP). To deploy your CRUD application on a remote server, you will need to register an account on a hosting provider, register an FTP account, and create a remote database. You can use any hosting you like. The current document describes the deployment procedure on the X10HOSTING free hosting. All the user names, passwords, and email addresses are fake and used as examples only. The administration of the hosting blocks an account if the user does not show up on the forum fore more than a week. So you may fail to apply exactly the same user names, passwords, email addresses, and other credentials from the tutorial. In this lesson you learn how to do the following: •

Register a hosting account



Register an FTP account



Create a remote MySQL database



Set up your project to use the registered remote web hosting



Change your database connection settings to use the remote database

Registering an Email Account Create an email account, if you have not created it before. In this example the email address is [email protected]. phpuser65 @ googlemail.com. Registering a Hosting Account To create a hosting account on the X10HOSTING free hosting, follow the steps in their wizard, entering the following settings. You will enter similar information on any other hosting site. Account Setting Email Address Domain name Subdomain Hosting Account Username (also for login to cPanel) Hosting Account Password (also for login to cPanel) Forum Username Forum Password FTP Account name FTP User Name FTP Server Remote Database Host Name Remote Database Remote Database Username Remote Database User Password

Value [email protected] phpuser65 @ gmail.com x10Hosting.com phpuser phpuser qwerty1234 phpuser qwerty uploader [email protected] uploader @ phpuser.x10hosting.com ftp.phpuser.x10hosting.com phpuser wishlist phpuser !phpuser

Registering an FTP Account Now that you have a hosting account, you need an FTP account where you will transfer your PHP source and other related files for executing them on the server. For x10Hosting, you opent the cPanel and select New FTP Account, then follow their wizard.

Creating a Remote Database Because the CRUD application uses a database you will also need to deploy the wishlist MySQL database on the remote server where you have a hosting account. Setting Up a PHP Project with Existing Sources and Remote Web Site Run Configuration 1. Download the source files that correspond to the state of the application after the previous lesson is

completed. Extract the files. 2. Save the source files in the htdocs folder. 3. Create a PHP project with existing sources:

○ Specify the location of the downloaded sources in the Source folder ○

Choose the Remote Web Site run configuration and configure the FTP connection

4. Complete the project creation. Updating the Class WishDB So far you have developed and run the Wish List application on the local web server and used a local MySQL database server. To make your application work with the remote database, you need to update the connection settings specified through the variables of the class WishDB. 1. Open the file db.php. 2. Change the variables of the class WishDB: 3. 4. 5. 6.

var $user = var $pass = var $dbName var $dbHost creation>";

""; ""; = ""; = "
In this example the variables will be updated as follows: var var var var

$user = $pass = $dbName $dbHost

"phpuser"; "!phpuser"; = "wishlist"; = "phpuser";


Related Documents