I’m an idealist. I don’t know where I’m going, but I’m on my way.—Carl Sandburg, Incidentals (1904)
Chapter Objectives/Student Learning Outcomes
Create a data class that inserts, updates, and deletes XML or JSON data
Explain how to create a data class that updates MySQL data using a SQL script
Create a PHP program that creates a change backup log
Create a PHP program that can recover data from a previous backup
Apply changes to create up-to-date valid information
Use dependency injection to attach a data class to another class in the BR tier
Create a three-tier PHP application
The Data Class
The interface and business rules tiers should not store application information. These tiers should not even be aware of how the information is stored (text file, XML, or database) or the location of the stored information. Any information that is stored must be passed from the business rules tier to the data tier. The data tier is also responsible for reacting to requests for information from the business rules tier.
Security and performance—When using databases, it may seem logical to build a SQL string in the business rules tier and pass the string to the data tier. This would cause a major security hole in the application. Hackers could pass any SQL string (including a delete string). It may also seem logical to pass SQL update commands (DELETE, UPDATE, and INSERT) into the data tier. Again, this provides a major hole. Passing data for a WHERE SQL command is also a bad idea as it might allow hackers to delete or change any combination of data in the database.
A data class should provide complete functionality for manipulating information. This includes the ability to read, insert, update, and delete information. Even if the current application does not require all these commands, logically, they should exist in the data class for future use.
A balance should be achieved between performance and the requirement to store information. While highly important information might require immediate storage, other information can be held in a data structure (list, array, and dataset) in the application until the user has completed any updates. Holding and making changes to information in the memory of the server, instead of the storage location, is much more efficient. Storing the information only after all changes have been completed will reduce several calls to the storage location down to two (initial retrieval of the information and saving of the updated information). Making changes to information in memory is always more efficient than making changes on a storage device (such as a hard drive).
However, conflicts can occur when data changes. The live data residing in the data structure might be updated while the application is also making changes. There are many ways in which the chances of conflicts can be reduced or eliminated. The approach required depends on the frequency of the use and changes to the data. Locking mechanisms can be designed to restrict access to the data currently being used. These techniques are usually handled within the data structure itself. For frequently changed data, these techniques are necessary to retain valid data. The data used in the examples in this book infrequently change. Thus, the likelihood of conflicts is greatly reduced.
As you can see, there is no longer a mixture of arrays and SimpleXML objects. An associate array has been created that uses keywords instead of numerical values for subscripts (indexes). In the previous example, an array called "dog" has been created with two rows (each row is represented by an array). In each row, the columns (cells) are referenced by a column name (dog_name, dog_weight, dog_color, and dog_breed) instead of indexes (0, 1, 2, 3). These rows and columns can be manipulated using some of the techniques we have seen in previous chapters.
There are many ways that you can create XML data in PHP. The previous example takes a simplistic approach by supplying the XML tags from the array. As seen in the structure, there are three sets of arrays in this multidimensional array. The first foreach loop is used to flow through the first array (dogs). The second foreach loop handles the dog arrays (rows). Once inside this loop, the third foreach loop controls the columns in each dog array (each row).
The third loop retrieves the column names (from $column) and places them in XML tags. $column is also used to pull the value in the column ($dog_value[$column]). The $xmlstring supplies the same tags and structure as in the original XML file. Note that each line includes a newline character ( ) to display different lines in the file. The structure would work without this addition. However, it makes the file more readable in a text editor.
Once the $xmlstring has been created, the code uses a combination of the PHP file_put_contents method and the get_dog_application method (from Chapter 4) to open the XML file, replace the contents with the string contained in $xmlstring, and close the file.
By default, XML parsing errors will cause the system to display the errors to the user and shut down the program. The libxml_user_internal_errors(true) method will suppress the errors. When the string is converted to XML format via the simplexml:load_string method , the XML is parsed to determine if it is valid. If it is not valid, the method will return FALSE instead of the XML information. The if statement shown will create an $errorString and use the foreach statement to loop through each error returned by the libxml_get_errors method (which returns an array containing the errors). Once all errors are collected, it will raise an exception passing the $errorString. The dog_interface program will catch this error and process it, as shown in Chapter 6.
This example does make one bad assumption (which simplifies the example). It assumes that the $errorString does not exceed the maximum capacity of 120 characters for the log file. A very badly formatted file could quickly cause $errorString to exceed this size. This limit can be adjusted in the PHP configuration file.
With the data automatically being saved whenever the data object is removed from memory, the insert, update, and delete methods only need to adjust the contents of the multidimensional associative array. Let us take a first look at creating a delete method since you have already seen an example in Chapter 6.
In the previous deleterecord method , the number of rows in the array and the array itself were passed into the method. The array in dog_data class is populated by the XML file containing the dog information. There is no property set with the number of records. This is not a problem. The PHP method count will return the size of an array. We can access and update the dogs_array (which is a protected private property) using the $this pointer. Methods in classes can use the this pointer to access and update protected properties; it is not necessary to pass them into a method. The only property we need to pass to the deleteRecord method is the record number ($recordNumber) to delete.
The associate array has three dimensions. The outer dimension is related to the dogs tag from the XML structure. Although there is only one “row” for dogs, a loop is still needed to move into the next array (dog). The foreach loop penetrates the dogs array and provides access to the dog array (which was created from the dog tags in the XML file). $dogs will contain the number of the dog row currently used. $dogs_value will contain the contents of the row (an array with the values in dog_name, dog_weight, dog_color, and dog_breed).
To move through each row (array) contained in the dog array, the method uses a for loop . The conditional statement ($J < count($dogs_value) -1) uses the count method to determine the size of the dog array. The count method returns the size of the array, not the last position of the array. Thus, the loop count must be less than (<) the size returned from count. One is subtracted from this value. As stated in Chapter 6, any row after a deleted row must be moved up one from its current position. The last position of the array will no longer be needed, which reduces the number of loops needed by one.
In the Chapter 5 example, a for loop was used to pull each column from the row and place it in the row above. With an associate array, we use a foreach loop . The $column parameter contains the column name ($J contains the row number) to place the values in the columns into the proper locations. After the values in the rows have been moved, the last position of the array is removed using the PHP unset method.
Similar logic can be used in almost any programming language. However, PHP associate arrays allow index numbers to be skipped. Unlike other languages which would place a NULL value in a missing index, PHP associate arrays just skip the actual index. Thus, any array could have indexes of 0, 1, 2, 4, and 5, and a foreach loop would properly loop through the array. With this in mind, we can greatly simplify the previous delete example to only contain one line of code, just the unset command shown. The unset command would remove the index passed into the method from the dog_array. Any for loop using the dog_array would still properly loop through the array.
As you can see, the readRecords method is more simplistic than the displayRecords method. All formatting of the results of this method are left to the calling program (if needed). Remember that displaying and formatting of output occurs in the interface tier, not the data tier (or business rules tier).
This method allows the calling program to request all records or a specific record. In either case it returns an array with either one row (the specific record requested) or all rows. When all rows are returned, the top array (representing the rows XML tag) is removed to keep the number of dimensions (two) the same for either selection.
The process of creating the dog_array using the JSON functions shown previously will create one inconsistency in creating the dog_array. If the dog_data.xml file contains only one record, the JSON functions will not create a numeric index (such as '0'). When more than one record is contained in the xml file, the numeric indexes will be created (such as '0', '1').
In the insertRecords method, all records are added to the end of the array (the calling program can sort them if needed). The current size of dogs_array is determined by the count method and stored into $dogs_array_size. The count method is also used inside the for structure to determine the size of the $records_array and to determine the number of loops. Since the results of the count method produce the size of the array, which is one more than the last subscript position, the result of count also gives the next position available to insert a record.
In the first loop, $I is 0. The first record of $records_array is placed into $dogs_array_size plus 0, or $dogs_array_size (the first open row to place a record). The next time through the loop, the second record of $records_array ($I was incremented by the loop) is placed into position $dogs_array_size plus 1. This is the next position available after the first record has been inserted. The loop will continue until there are no more records in the $records_array. By the way, this method also works well with just one record to insert (as long as it is passed as an associate array). The loop will execute only once.
Dynamically built arrays are not required to have values for every position in the array. If the dynamic array shown previously is passed into the updateRecords method , records 0 and 2 would be updated with the new information. The value in position 1 in the dogs array would remain untouched.
Take a moment to look at these methods. There are only two XML tags that have been coded in the methods (dogs and dog). Even those two could have been retrieved from the XML file. However, the assumption that these tags will always exist in a valid dog XML file makes logical sense. By dynamically pulling all of the other tags (dog_name, dog_weight, dog_color, and dog_breed) from the XML file, changes can be made to the file without causing any code changes. Additional tags can be added, removed, and/or changed.
The dog_data.php file
The testdata.php file
Example 7-2 tests some of the possible scenarios of using the dog_data class. Notice the last line of code calls the destructor (to save the data). This is accomplished by setting the pointer to the object ($tester) to NULL, which releases the object. This will inform the garbage collector of the operating system that the object should be removed from memory. This will cause the destructor to execute, which will update the XML file and remove the object from the memory of the server.
JSON Data
The complete code for the destructor requires only two lines. The json_encode method will convert the associate array data into JSON format. The file_put_contents method will then save the information to the proper location of the JSON file ($this->dog_data_JSON). No changes are required to any of the other methods in dog_data.
MySQL and NoSQL Data with MySQL 8+
This is a good time to give a brief example of adjustments we can make to the constructor and destructor methods to access and update database information. The current version of MySQL allows both the creation of MySQL and NoSQL data.
For information on installing the latest version of MySQL, visit https://dev.mysql.com/doc/refman/8.0/en/installing.html.
Whenever external data storage techniques are used, all security measures should be implemented to completely protect all data. All database systems include data security tools to validate information before it is stored.
Most of the code required for the constructor method is associated to connecting, retrieving, and disconnecting from the database. The mysqli_connect method uses the server location ($server), database user ID ($db_username), database password ($db_password), and database name ($database) to connect to the database. If mysqli_connect_errno contains any errors, an Exception is thrown describing the error. If there are no errors, a SQL SELECT statement ($sql) is used to retrieve all the records from the Dogs table in the database. If no records are retrieved, another exception is thrown. If records are retrieved, the mysqli_fetch_assoc method will convert the data into an associate array. The mysqli_free_result statement releases the data from $result. The mysqli_close method closes access to the database.
The destructor method attempts to connect to the database. If the connection is successful, the method removes any preexisting Dogs table and creates a new one with the required fields. (Note: It would probably be better to rename the old one and create a new one.) If the old table can be removed and the new table created, then the method attempts to insert rows into the table. The SQL INSERT statement places the values from $dog_name, $dog_weight, $dog_color, and $dog_breed into a row in the table. The foreach loops retrieve each row from the associate array to be placed into the table. If any of the inserts are not successful, an exception is thrown.
Programming note—The Apache server must be properly configured, and MySQL must be properly installed to run this (or a similar) database example. $server must be set to the URL, “localhost”, or “127.0.0.1”. $db_username must be set to the user ID name to access the database ('root' if a user ID has not been configured). $db_password must be set to the database password (or '' if there is no password). $database must be set to the database name. There is a large variety of ways to access and manipulate databases in the PHP language .
Do It
- 1.
Download the example files for this section from the book’s web site. Adjust the deleteRecords method to allow the ability to delete multiple records. However, also include a check to limit the amount of records that can be deleted. It would not be very secure to allow all records to be deleted. If an attempt is made to delete all records (or too many records), an exception should be raised. The exception should cause the calling program (eventually dog_interface) to write an error message to the main log file, email the support personnel, and display the general message to the users (shown in Chapter 6). Adjust the testdata program to test the ability to delete multiple records and catch the exceptions.
- 2.
Download the example files for this section from the book’s web site. Adjust the testdata program to test all remaining scenarios that have not already been tested. These are related to inserting, updating (more than one), reading, and deleting records. Be sure to test improperly formatted information. Create a try catch block in the testdata program to capture any exceptions. You can use the try catch block from dog_interface in Chapter 6 as an example.
Backup and Recovery
There is always a possibility that something can go wrong when changes are made to stored information. While a well-developed application must filter and clean data before it is saved, it must also be prepared to handle the possibility that bad data may still flowed through and corrupt the information. In addition to intentional corruption, unforeseen problems (such as system crashes) may occur. An application must provide the ability to recover without the loss of data. This can be accomplished by logging change requests and backing up valid information. Recovery can be accomplished by using a valid backup and reapplying valid changes to the backup files to produce up-to-date information.
Security and performance—In a “live” environment, it would be more secure to pass “codes” into this type of method instead of using a value that indicates the action that will take place. For example, 101 could be used to indicate an update. The switch statement could easily be adjusted to examine the codes to determine which method to call.
This format provides all the information needed to help with the recovery process. If the current version of the dog data file is corrupted, the change log file can be used to apply changes to a good version of the file to develop a new current version.
Before the destructor uses the file_put_contents method to apply changes to the XML file, a backup should be created in case the changes cause corruption to the current data. The recovery process will allow the support personnel to select which data file contains good data and which change file(s) will be applied to the data to produce the correct current version of the data.
Because this process may use a backup file of the data, which includes a file name with a date and time, the preg_replace method is used to remove any numerical information from the data file name. The regular expression (/[0-9]+/) in the first parameter directs the method to search for all occurrences of numbers in $this->dog_data_xml. If any occurrence is found, it is replaced with the value in the second parameter (''). In this case, nothing. The new file name is then placed in $new_valid_data_file. This will not cause any change to a “normal” nonbackup file name because it does not contain any numerical information. A new backup file name is created using the file name in $new_valid_data_file with the date and time information. The new backup file name is stored in $oldxmldata.
Now the last valid data can be moved to the new backup file using the rename method. The data in $this->dog_data_xml (the location of the good data without changes) is copied to the new backup file location ($oldxmldata). If the file cannot be renamed, an exception is thrown.
Finally, the valid changed data (located in $xmlstring) can be placed into the new location of the valid data (which is the same file name without any date information) contained in the $new_valid_data_file property.
The dogdata.php file with logging as well as backup and recovery processes
Once the user has selected a change file, the contents of the file will be displayed in the same manner as shown in Chapter 6. The display_Process method will provide this information. The user can decide to remove some entries in the change file selected. If deletions are needed, the delete_Process method will complete the process, using the same techniques shown in Chapter 6. In addition, the same method will allow the user to select the most recent valid data file to apply changes.
Once the data file has been selected, update_XML_File_Process will apply the changes to the file using the dogdata program (in Example 7-3). The process will display a changes completed message to the user.
The load_Array method is very similar to the constructor in the dog_data class. This method retrieves the value in change_file and places it in $change_File. This file is then opened and all entries in the file are placed into $change_Array. The explode method will produce three columns (date/time, change type, array or string used for the change). It returns this array to the calling program (display_Process).
displayRecords displays the contents of the change log file using almost exactly the same logic used in the displayRecords method of the readerrorlog program (in Example 6-8). It also uses almost the same logic as the selectFileProcess (Shown previously) to display the data files for the user to select the last uncorrupted file.
The saveChanges method builds the date/time-changetype-changedata format, seen previously, from the change_Array. This information is saved in $writeString and is used to replace the change log file with the updated version (minus the record that was deleted).
The delete_Process method then recalls the displayRecords method (described earlier) to display the updated change log (minus the record deleted) and the data file drop-down list.
The method calls the load_Array method to return the changes into $change_Array. The dog_data file is imported into the method to prepare for the changes to the data file selected by the user. An instance of the data_data class is created ($data_Changer).
The displaychangelog.php file
JSON Backup and Recovery
What changes are needed to provide backup and recovery for JSON data instead of XML data? Actually, no changes at all. As long as the changes from the first section of this chapter are implemented, the displaychangelog program and the changes to the dog_data class will handle JSON in the same manner as XML data.
MySQL Backup and Recovery
As you might be guessing, as long as the changes from the second section of this chapter are implemented, no additional changes will be required for backup and recovery of MySQL data. However, we can take a moment to look at an alternative way of handling MySQL data.
It is a common practice to create a SQL script file to execute against a database. A script file contains all the SQL code necessary to update the database. Using this type of file will allow you to do proper INSERT, UPDATE, and DELETE SQL commands instead of only an INSERT as previously shown. The previous example required creating an INSERT command for every record in the associate array. This includes records that were not changed. This would be inefficient for medium to large databases. You only need to update the record that changed.
You can develop the scripting file from records in the associate array that have changed. You can use the change log as the script file, as the SQL script lists all changes that have been requested. It can be rerun to fix any corrupted data.
If we review the changeRecords method, a SQL WHERE clause was built using a property named dog_id. In the XML and JSON examples, we did not have this field. However, SQL UPDATE requires a where clause to determine which record(s) to update. The property used needs to be unique to identify the exact record(s). The only place the code must generate this dog_id is when a new record is created in the database (in the insertRecords method). This can be done using the PHP rand method.
The PHP rand method produces random numbers. The first parameter is the starting number (0) and the second parameter is the last number (9999). The size of this field is set to char(4) in the database, which allows up to four characters. This would allow us up to 10,000 dogs. I am sure that will be more than enough!
The while loop in the insertRecords method uses the PHP in_array method to determine if the number is already in the dogs_array (which contains all the current records in the database). A third parameter, which determines if a strict search (comparing data types) should occur, must be set to produce reliable results with multidimensional associate arrays. If the number does exist, the logic continues to generate a new random number until a unique one is found. The value is then placed in $dog_id, which will be inserted into the database along with the other fields (dog_name, dog_weight, dog_color, and dog_breed). Note: This code assumes that the Dogs table in the database has been created with the fields in the order shown (dog_id, dog_name, dog_weight, dog_color, and dog_breed).
The code for the destructor becomes simpler than in the original MySQL example. The destructor does not need to format any SQL statements. It only needs to execute them. The method reads the change records from the change log, splitting each via the ; at the end of each SQL command line. Each line is placed in the array $sql. The logic then loops through the array and executes each statement via the query command. If any of the SQL statements has a problem, an exception is thrown (which will also send an email to support personnel via the dog_interface program).
As stated, the MySQL examples are shown to help the reader see that the overall logic of the dog_data class works well with all data types. Complete books are written on using PHP to interact with databases. It is not the intent of this book to train the user to have complete knowledge of database manipulation.
Do It
- 1.
The dog_data class creates a new log file every time it is run. This could cause a lot of log files to be created in a very short period of time. Your mission is to either update the readchangelog file (download it from the book’s web site) or to create your own maintenance program. The code will ask the users for the number of log files (and data files) to keep. The program will then keep the most recent number of files requested. The glob method, as shown previously, can be used to retrieve all the file names. The unlink method can be used to delete a file:
- 2.
The MySQL examples shown now produce different contents in the change log file. Download the readchangelog program from the book’s web site and make any adjustments needed to the code to properly view and delete the change log. Assuming that the database administrator has reversed the contents of the database to the last valid set of data, adjust the program to execute the change log selected against the database. Hint: Your completed program will have less code than the example from the book’s web site.
Connecting the Data Tier
The constructor of the dog class sets all the properties and throws an exception if there are problems. If no problems exist, the information is saved (via save_dog_data), and the program closes (exit).
In order to keep the data tier independent of the business rules tier, dependency injection will be used to discover the location and name of the dog_data class and to call the processRecords method from the class. We will borrow the logic from Chapter 5. Actually, we can use the dog_container from Example 5-10 without any changes. If you do not remember the details of this class, revisit Chapter 5.
The dog_container class includes the get_dog_application method, which uses the logic discussed several times to search the dog application XML file for the name of the file needed (dog_data.php). The set_app method allows us to pass the application type (dogdata) to search in get_dog_application. It also includes the create_object class that will determine the class name (dog_data), make an instance of the class, and pass the class (the address of the class in memory) back to the calling program. The class does require that a get_properties function exist in the calling program. We do not currently have one in the Dog class. However, we can create a shell (an empty function) in the class to meet this requirement.
The lines to accomplish this are the same as seen previously in the dog_interface; we create the dog_container, find the location of the dogdata file, and create an instance of the dog_data class. The only difference is that “dogdata” is passed in for the search. The PHP function get_class_methods is used to create a list of methods in the dog_data class. The last method in the class is processRecords. The name of this method is pulled and placed into $method_name. The record_Array is then built to be passed into processRecords. The method is called, passing "Insert" and the record_Array. Finally, the dog_data object is set to NULL, which causes the destructor to save the data.
The dog.php file using dog_data.php to save data
The interface tier contains the lab.html file and the dog_interface.php program. The business rules tier includes the dog.php class and the get_breeds class. The dog_data class is in the data tier. Any requests from the dog_interface program for communications with the business rules tier are handled by the dog_container class. Any requests for communications with the data tier (from the business rules tier) are also handled by the dog_container class. Access to the data tier is only available from or through the business rules tier. Access to the interface tier only occurs from or through the business rules tier.
The interface tier does not know the location/name of any class or method in the business rules tier. This information is discovered by using the dog_container. The business rules tier does not know the location/name of any class or method in the data tier. This information is also discovered by using the dog_container. This allows complete independence of each tier, which allows changes to occur in one tier without requiring changes in the other two tiers.
Do It
- 1.
Download all the files for the dog application from this chapter. Adjust file names in the dog_application XML file to discover how missing files are handled in the application. Does the application handle these problems properly? Adjust the dog_data XML file to include badly formed XML data. Run the application. Does it handle these problems properly? Empty the dog_data XML file (except for the dogs and dog tags). Run the application. Does it handle this situation properly? For any instance that causes the application to error instead of raising an exception, attempt to adjust the code to anticipate the problem and raise an exception.
Chapter Terms
Data Tier | file_get_contents |
---|---|
SimpleXML Data Model | simplexml:load_string |
Type Casting | JSON Data |
JSON Methods | Associative Array |
json_encode | json_decode |
Keywords | new line character |
file_put_contents | libxml:user_internal_errors(true) |
libxml:get_errors | Count |
$this | Unset |
Dynamic Arrays | Releasing an Object |
mysqli_connect | mysqli_connect_errno |
mysqli_fetch_assoc | mysqli_free_result |
mysqli_close | SQL SELECT |
SQL INSERT | Polymorphism |
Change Log File | Serialize |
Unserialize | Backup and Recovery |
preg_replace | Regular Expression |
glob | Embedded if then else |
SQL UPDATE | SQL Script File/Log |
SQL WHERE | Rand |
Strict Search | Unlink |
shell | Dependence Injection |
Chapter Questions and Projects
- 1.Which of the following describes type casting?
- a.
It is rarely needed in PHP.
- b.
It exists in most languages.
- c.
It is needed for serialized data.
- d.
All of the above.
- a.
- 2.Which of the following describes an associative array?
- a.
It has a key and value relationship (key->value).
- b.
It uses numerical subscripts.
- c.
It does not have an index.
- d.
A and B.
- a.
- 3.Which of the following is the newline character?
- a.
&
- b.
.
- c.
;
- d.
None of these
- a.
- 4.Which of the following describes JSON data?
- a.
It has a similar format to arrays.
- b.
It cannot only be used with JavaScript.
- c.
It requires much more coding than when using XML data.
- d.
It is more secure than XML data.
- a.
- 5.Which of the following describes unlink?
- a.
It can be used to release a parameter of an array.
- b.
It can be used to delete a file or directory.
- c.
It can be used to split apart an array.
- d.
None of these.
- a.
- 6.Which of the following describes polymorphism?
- a.
The container that holds and secures an application
- b.
The ability to pass multiple data types into the same signature of a method
- c.
The ability to use the methods and properties of a parent class
- d.
None of these
- a.
- 7.Which of the following describes rand?
- a.
It can be used to produce a random number.
- b.
The first parameter is the starting number.
- c.
The second parameter is the last number.
- d.
All of the above.
- a.
- 8.When using in_array, strict search does which of the following?
- a.
It compares data types.
- b.
It is the third parameter (set to true).
- c.
It should be used when searching associative arrays.
- d.
All of these.
- a.
- 9.Which of the following describes a shell method?
- a.
It contains no data.
- b.
It has no signature.
- c.
It includes JSON data.
- d.
All of these.
- a.
- 10.The data tier does which of the following?
- a.
Updates data
- b.
Returns data
- c.
Filters data
- d.
All of the above
- a.
- 1.
Log files are important for successful recovery of information.
- 2.
Data is serialized to convert the data type to string.
- 3.
After updates have been completed, all backup copies of data can be destroyed.
- 4.
Dependency injection is necessary to keep the tiers (interface, business rules, and data) independent of each other.
- 5.
SQL script files update all records including those that have not changed.
- 1.
Explain the process used to correct data files that have been corrupted.
- 2.
Why is data stored in a database usually more secure than data stored in a text file?
- 3.
Compare and contrast the methods used to update XML data to the methods used to update MySQL data. Which is more efficient? Why?
- 4.
When should an email be sent to the system administrator when data is being updated? What should this email contain? What should it not contain? Why?
- 5.
How can a system administrator determine which data file is the last noncorrupted version?
- 1.
Adjust the code from Chapter 4 project #1 or #2 to include backup and recovery ability.
- 2.
Create a complete storage (XML or JSON format) and a backup and recovery system for one of the previous projects you have completed. The system should include the ability for the users to limit the number of recovery files, the ability to adjust contents of a selected file (update, insert, and delete), and the ability to execute the file against the most recent valid data. When the process is complete, any corrupted files should automatically be removed. The system should also keep its own log file to indicate when changes have occurred.
- 1.
Update the ABC Computer Parts Inventory program to include storage of the data (XML or JSON format) and complete backup and recovery capabilities. The application should include a change log to indicate any data changes. Additional support programs should be included to allow for easy recovery of any corrupted data. Your complete application should use logic similar to the examples shown in this chapter.