1. Trang chủ
  2. » Công Nghệ Thông Tin

Giải pháp thiết kế web động với PHP - p 47 ppsx

10 215 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 452,34 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

If the check box is subsequently unchecked, the drop-down menu is reenabled, and the file input field and caption field are hidden again.. The updated insert form now has input fields fo

Trang 1

Figure 16-8 The multiple-choice <select> list pulls the values from the categories table

7 View the pages source code to verify that the primary key of each category is correctly

embedded in the value attribute of each <option> tag You can compare your code with

blog_insert_mysqli_01.php in the ch16 folder

8 Next, create the <select> drop-down menu to display the images already registered in the

database Add this code immediately after the code you inserted in step 5:

<p>

<label for="image_id">Uploaded image:</label>

<select name="image_id" id="image_id">

<option value="">Select image</option>

<?php

// get the list of images

$getImages = 'SELECT image_id, filename

FROM images ORDER BY filename';

$images = $conn->query($getImages);

while ($row = $images->fetch_assoc()) {

?>

<option value="<?php echo $row['image_id']; ?>"

<?php

if (isset($_POST['image_id']) && $row['image_id'] == $_POST['image_id']) { echo 'selected';

}

?>><?php echo $row['filename']; ?></option>

<?php } ?>

</select>

</p>

Trang 2

442

This creates another SELECT query to get the primary key and filename of each image stored in the images table The code should be very familiar by now, so it needs no explanation

9 The check box, file input field, and text input field for the caption go between the code in the

previous step and the submit button The code looks like this:

<p id="allowUpload">

<input type="checkbox" name="upload_new" id="upload_new">

<label for="upload_new">Upload new image</label>

</p>

<p class="optional">

<label for="image">Select image:</label>

<input type="file" name="image" id="image">

</p>

<p class="optional">

<label for="caption">Caption:</label>

<input name="caption" type="text" class="widebox" id="caption">

</p>

The paragraph that contains the check box has been given the ID allowUpload, and the two other paragraphs have been assigned a class called optional The style rules in admin.css set the display property of these three paragraphs to none

10 Save blog_insert_mysqli.php, and load the page in a browser The images <select>

drop-down menu is displayed below the categories list, but the three form elements you inserted in step 9 are hidden This is what will be displayed if JavaScript is disabled in the browser Users will have the option to select categories and an existing image but not to upload a new image

If necessary, check your code against blog_insert_mysqli_02.php in the ch16 folder

11 Copy toggle_fields.js from the ch16 folder to the admin folder The file contains the following

JavaScript:

var cbox = document.getElementById('allowUpload');

cbox.style.display = 'block';

var uploadImage = document.getElementById('upload_new');

uploadImage.onclick = function () {

var image_id = document.getElementById('image_id');

var image = document.getElementById('image');

var caption = document.getElementById('caption');

var sel = uploadImage.checked;

image_id.disabled = sel;

image.parentNode.style.display = sel ? 'block' : 'none';

caption.parentNode.style.display = sel ? 'block' : 'none';

image.disabled = !sel;

caption.disabled = !sel;

}

This uses the IDs of the elements inserted in step 8 to control their display If JavaScript is enabled, the check box is automatically displayed when the page loads, but the file input field and text input field for the caption remain hidden If the check box is checked, the drop-down

Trang 3

menu of existing images is disabled, and the hidden elements are displayed If the check box is subsequently unchecked, the drop-down menu is reenabled, and the file input field and caption field are hidden again

JavaScript is beyond the scope of this book, but you can learn more from Getting StartED with

JavaScript by Terry McNavage (friends of ED, 2010, ISBN: 978-1-4302-7219-9) and DOM Scripting: Web Design with JavaScript and the Document Object Model, Second Edition by Jeremy Keith (friends of ED,

2010, ISBN: 978-1-4302-3389-3)

12 Link toggle_fields.js to blog_insert_mysqli.php with a <script> tag just before the

closing </body> tag like this:

</form>

<script src="toggle_fields.js"></script>

</body>

Although it has been common practice for many years to put <script> tags for external

JavaScript files in the <head> of a web page, more recent practice recommends adding most scripts as close to the bottom of the <body> as possible to speed up downloading and display The code in toggle_fields.js wont work correctly if you add it to the <head>

13 Save blog_insert_mysqli.php, and load the page in a browser In a JavaScript-enabled

browser, the check box should be displayed between the <select> drop-down menu and submit button Select the check box to disable the drop-down menu and display the hidden fields, as shown in Figure 16-9

Figure 16-9 The check box controls the display of the file and caption input fields

Trang 4

444

14 Deselect the check box The file and caption input fields are hidden, and the drop-down menu is

reenabled You can check your code, if necessary with blog_insert_mysqli_03.php and toggle_fields.js in the ch16 folder

If youre wondering why I used JavaScript, rather than PHP, to control the display of the file and caption input fields, its because PHP is a server-side language After the PHP engine has sent the output to the browser, it has no further interaction with the page unless you send another request to the web server JavaScript, on the other hand, works in the browser, so its able to manipulate the content of the page locally JavaScript can also be used in conjunction with PHP to send requests to the web server in the background and can use the result to refresh part of the page without reloading it—a technique known as Ajax, which is beyond the scope of this book

The updated insert form now has input fields for categories and images, but the processing script still handles only the text input field for the title and the text area for the blog entry

PHP Solution 16-4: Inserting data into multiple tables

This PHP solution adapts the existing script in blog_insert_mysqli.php to upload a new image (if required) and insert data into the images, blog, and article2cat tables following the decision chain outlined in Figure 16-6 It assumes you have set up the article2cat cross-reference table and have completed PHP Solutions 16-2 and 16-3

Dont attempt to rush through this section The code is quite long, but it brings together many of the techniques you have learned previously

1 In the conditional statement at the top of blog_insert_mysqli.php locate the following code

highlighted in bold:

if (isset($_POST['insert'])) {

// initialize flag

$OK = false;

// initialize prepared statement

$stmt = $conn->stmt_init();

2 Immediately after the highlighted code, insert some space to add the following conditional

statement to process the image, if one has been uploaded or selected

// initialize prepared statement

$stmt = $conn->stmt_init();

// if a file has been uploaded, process it

if(isset($_POST['upload_new']) && $_FILES['image']['error'] == 0) {

$imageOK = false;

require_once(' /classes/Ps2/Upload.php');

$upload = new Ps2_Upload(' /images/');

$upload->move();

$names = $upload->getFilenames();

// $names will be an empty array if the upload failed

if ($names) {

$sql = 'INSERT INTO images (filename, caption)

VALUES (?, ?)';

Trang 5

$stmt->prepare($sql);

$stmt->bind_param('ss', $names[0], $_POST['caption']);

$stmt->execute();

$imageOK = $stmt->affected_rows;

}

// get the image's primary key or find out what went wrong

if ($imageOK) {

$image_id = $stmt->insert_id;

} else {

$imageError = implode(' ', $upload->getMessages());

}

} elseif (isset($_POST['image_id']) && !empty($_POST['image_id'])) {

// get the primary key of a previously uploaded image

$image_id = $_POST['image_id'];

}

// create SQL

$sql = 'INSERT INTO blog (title, article, created)

VALUES(?, ?, NOW())';

This begins by checking if $_POST['upload_new'] has been set As explained in Chapter 5, a check box is included in the $_POST array only if it has been selected So, if the check box

hasnt been selected, the condition fails, and the elseif clause at the bottom is tested instead The elseif clause checks for the existence of $_POST['image_id'] If it exists and is not empty, an existing image has been selected from the drop-down menu, and the value is stored in

$image_id

If both tests fail, an image has neither been uploaded nor selected from the drop-down menu The script later takes this into account when preparing the INSERT query for the blog table, allowing you to create a blog entry without an image

However, if $_POST['upload_new'] exists, the check box has been selected, and an image has probably been uploaded To make sure, the conditional statement also checks the value of

$_FILES['image']['error'] As you learned in Chapter 6, the error code 0 indicates a

successful upload Any other error code means the upload failed or that no file was selected Assuming a file has been successfully uploaded from the form, the conditional statement

includes the Ps2_Upload class and creates an upload object, setting the destination folder to images It then calls the move() method to move the file to the images folder To avoid

complicating the code, Im using the default maximum size and MIME types

The changes you made to the Ps2_Upload class in PHP Solution 16-2 add the name of an

uploaded file to the $_filenames property only if the file was moved successfully to the

destination folder The getFilenames() method retrieves the contents of the $_filenames property, and assigns the result to $names If the file was moved successfully, its filename is stored as the first element of the $names array So if $names contains a value, you can safely proceed with the INSERT query, which binds the values of $names[0] and $_POST['caption']

as strings to the prepared statement

Trang 6

446

After the statement has been executed, the affected_rows property resets the value of

$imageOK If the INSERT query succeeded, $imageOK is 1, which is treated as true

If the image details were inserted in the images table, the insert_id property retrieves the primary key of the new record and stores it in $image_id The insert_id property must be accessed before running any other SQL queries, because it contains the primary key of the most recent query

However, if $imageOK is still false, the getMessages() method of the upload object is called, and the result is stored in $imageError The getMessages() method returns an array, so the implode() function is used to join the array elements as a single string The most likely causes

of failure are a file thats too big or of the wrong MIME type

3 As long as the image upload didnt fail, the next stage in the process is to insert the blog entry

into the blog table The form of the INSERT query depends on whether an image is associated with the blog entry If it is, $image_id exists and needs to be inserted in the blog table as a foreign key Otherwise, the original query can be used

Amend the original query like this:

// don't insert blog details if the image failed to upload

if (!isset($imageError)) {

// if $image_id has been set, insert it as a foreign key

if (isset($image_id)) {

$sql = 'INSERT INTO blog (image_id, title, article, created)

VALUES(?, ?, ?, NOW())';

$stmt->prepare($sql);

$stmt->bind_param('iss', $image_id, $_POST['title'], $_POST['article']); } else {

// create SQL

$sql = 'INSERT INTO blog (title, article, created)

VALUES(?, ?, NOW())';

$stmt->prepare($sql);

$stmt->bind_param('ss', $_POST['title'], $_POST['article']);

}

// execute and get number of affected rows

$stmt->execute();

$OK = $stmt->affected_rows;

}

This whole section of code is wrapped in a conditional statement that checks whether

$imageError exists If it does, theres no point in inserting the new blog entry, so the entire code block is ignored

However, if $imageError doesnt exist, the nested conditional statement prepares different INSERT queries depending on whether $image_id exists and then executes whichever one has been prepared

4 The next stage of the process inserts values into the article2cat cross-reference table The

code follows immediately after the code in the previous step and looks like this:

Trang 7

// if the blog entry was inserted successfully, check for categories

if ($OK && isset($_POST['category'])) {

// get the article's primary key

$article_id = $stmt->insert_id;

foreach ($_POST['category'] as $cat_id) {

if (is_numeric($cat_id)) {

$values[] = "($article_id, " (int) $cat_id ')';

}

}

if ($values) {

$sql = 'INSERT INTO article2cat (article_id, cat_id)

VALUES ' implode(',', $values);

// execute the query and get error message if it fails

if (!$conn->query($sql)) {

$catError = $conn->error;

}

}

}

The value of $OK is determined by the affected_rows property from the query that inserted the data in the blog table, and the multiple-choice <select> list is included in the $_POST array only

if any categories are selected So, this code block is run only if the data was successfully

inserted in the blog table and at least one category was selected in the form It begins by

obtaining the primary key of the insert operation from the prepared statements insert_id

property and assigning it to $article_id

The form submits the category values as an array The foreach loop checks each value in

$_POST['category'] If the value is numeric, the following line is executed:

$values[] = "($article_id, " (int) $cat_id ')';

This creates a string with the two primary keys, $article_id and $cat_id, separated by a comma and wrapped in a pair of parentheses The (int) casting operator makes sure that

$cat_id is an integer The result is assigned to an array called $values For example, if

$article_id is 10 and $cat_id is 4, the resulting string assigned to the array is (10, 4)

If $values contains any elements, implode() converts it to a comma-separated string and appends it to the SQL query For example, if categories 2, 4, and 5 are selected, the resulting query looks like this:

INSERT INTO article2cat (article_id, cat_id)

VALUES (10, 2),(10, 4),(10,5)

As explained in “Reviewing the four essential SQL commands” in Chapter 13, this is how you insert multiple rows with a single INSERT query

Because $article_id comes from a reliable source and the data type of $cat_id has been checked, its safe to use these variables directly in a SQL query without using a prepared

statement The query is executed with the query() method If it fails, the connection objects error property is stored in $catError

Trang 8

448

5 The final section of code handles the redirect on success and error messages The amended

code looks like this:

// redirect if successful or display error

if ($OK && !isset($imageError) && !isset($catError)) {

header('Location: http://localhost/phpsols/admin/blog_list_mysqli.php'); exit;

} else {

$error = $stmt->error;

if (isset($imageError)) {

$error = ' ' $imageError;

}

if (isset($catError)) {

$error = ' ' $catError;

}

}

}

The condition controlling the redirect now makes sure that $imageError and $catError dont exist If either does, the value is concatenated to the original $error, which contains any error message from the prepared statement object

6 Save blog_insert_mysqli.php, and test it in a browser Try uploading an image thats too big

or a file of the wrong MIME type The form should be redisplayed with an error message and the blog details preserved Also try inserting blog entries with and without images and/or categories You now have a versatile insert form

If you dont have suitable images to upload, use the images in the phpsols images folder The Ps2_Upload class renames them to avoid overwriting the existing files

You can check your code against blog_insert_mysqli_04.php in the ch16 folder

The PDO version is in blog_insert_pdo.php in the ch16 folder PDO uses the lastInsertId() method on the connection object to get the primary key of the most recent insert operation For example, the following line gets the primary key of the blog entry:

$article_id = $conn->lastInsertId();

Like the MySQLi insert_id property, you need to access it immediately after the INSERT query has been executed

Updating and deleting records in multiple tables

The addition of the categories and article2cat tables means that the changes you made to blog_update_mysqli.php in PHP Solution 15-2 in the previous chapter no longer adequately cover the foreign key relationships in the phpsols database In addition to amending the update form, you also need to create scripts to delete records without destroying the databases referential integrity

Trang 9

Updating records in a cross-reference table

Each record in a cross-reference table contains only a composite primary key Normally, primary keys should never be altered Moreover, they must be unique This poses a problem for updating the article2cat table If you make no changes to the selected categories when updating a blog entry, the cross-reference table doesnt need to be updated However, if the categories are changed, you need to work out which cross references to delete and which new ones to insert

Rather than getting tied up in knots working out whether any changes have been made, a simple solution is

to delete all existing cross references and insert the selected categories again If no changes have been made, you simply insert the same ones again

PHP Solution 16-5: Adding categories to the update form

This PHP solution amends blog_update_mysqli.php from PHP Solution 15-2 in the previous chapter to allow you to update the categories associated with a blog entry To keep the structure simple, the only change that can be made to the image associated with the entry is to select a different existing image or no image at all

1 Continue working with blog_update_mysqli.php from PHP Solution 15-2 Alternatively, copy

blog_update_mysqli_04.php from the ch16 folder, and save it in the admin folder as

blog_update_mysqli.php

2 When the page first loads, you need to run a second query to get the categories associated with

the blog entry Add the following highlighted code to conditional statement that gets details of the selected record:

$stmt->free_result();

// get categories associated with the article

$sql = 'SELECT cat_id FROM article2cat

WHERE article_id = ?';

$stmt->prepare($sql);

$stmt->bind_param('i', $_GET['article_id']);

$stmt->bind_result($cat_id);

$OK = $stmt->execute();

// loop through the results to store them in an array

$selected_categories = array();

while ($stmt->fetch()) {

$selected_categories[] = $cat_id;

}

}

The query selects cat_id from all records in the cross-reference table that match the primary key of the selected blog entry The results are bound to $cat_id, and a while loop extracts the values into an array called $selected_categories

3 In the body of the HTML page, add a multiple-choice <select> list between the text area and the

<select> drop-down menu that displays the list of images Use another SQL query to populate it like this:

Trang 10

450

<p>

<label for="category">Categories:</label>

<select name="category[]" size="5" multiple id="category">

<?php

// get categories

$getCats = 'SELECT cat_id, category FROM categories

ORDER BY category';

$categories = $conn->query($getCats);

while ($row = $categories->fetch_assoc()) {

?>

<option value="<?php echo $row['cat_id']; ?>" <?php

if (in_array($row['cat_id'], $selected_categories)) {

echo 'selected';

} ?>><?php echo $row['category']; ?></option>

<?php } ?>

</select>

</p>

The while loop builds each <option> tag, inserting cat_id in the value attribute and displaying the category between the opening and closing tags If cat_id is in the $selected_categories array, selected is inserted in the <option> tag This selects the categories already associated with the blog entry

4 Save blog_update_mysqli.php, and select one of the EDIT links in blog_list_mysqli.php to

make sure the multiple-choice list is populated with the categories If you inserted a new entry in PHP Solution 16-4, the categories you associated with the item should be selected, as shown in the following screenshot

You can check your code, if necessary, against blog_update_mysqli_05.php in the ch16 folder The PDO version is in blog_update_pdo_05.php

5 Next, you need to edit the section of code that updates the record when the form is submitted

The code currently looks like this:

// if form has been submitted, update record

if (isset($_POST ['update'])) {

// prepare update query

if (!empty($_POST['image_id'])) {

$sql = 'UPDATE blog SET image_id = ?, title = ?, article = ?

WHERE article_id = ?';

$stmt->prepare($sql);

$stmt->bind_param('issi', $_POST['image_id'], $_POST['title'], 

$_POST['article'], $_POST['article_id']);

Ngày đăng: 06/07/2014, 19:20

TỪ KHÓA LIÊN QUAN