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

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

10 230 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 869,28 KB

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

Nội dung

415 Pulling Data from Multiple Tables As I explained in Chapter 11, one of the major strengths of a relational database is the ability to link data in different tables by using the prim

Trang 1

411

Format character Description Examples

%R Display minus when negative, plus when positive -, +

%r Display minus when negative, no sign when positive -

* A bug verified in PHP 5.3.3 produces an incorrect result for the total number of days on Windows

Hopefully, this will be fixed in a subsequent release

The following example in date_interval_03.php shows how to get the difference between the current

date and the American Declaration of Independence using diff() and displaying the result with the

format() method:

<p><?php

$independence = new DateTime('7/4/1776');

$now = new DateTime();

$interval = $now->diff($independence);

echo $interval->format('%Y years %m months %d days'); ?>

since American independence.</p>

If you load date_interval_03.php into a browser, you should see something similar to the following

screenshot (of course, the actual period will be different)

Trang 2

CHAPTER 14

412

The format characters follow a logical pattern Uppercase characters always produce at least two digits with a leading zero if necessary Lowercase characters have no leading zero

What might not be immediately obvious is that, with the exception of %a, which represents the total number

of days, the format characters represent only specific parts of the overall interval For example, if you change the format string to $interval->format('%m months'), it shows only the number of whole months that have elapsed since last July 4 It does not show the total number of months since July 4,

1776

Calculating recurring dates with the DatePeriod class

Working out recurring dates, such as the second Tuesday of each month, is now remarkably easy thanks

to the DatePeriod class It works in conjunction with a DateInterval object and is available only in PHP 5.3 or later

The DatePeriod constructor is unusual in that it accepts arguments in three different ways The first way

of creating a DatePeriod object is to supply the following arguments:

• A DateTime object representing the start date

• A DateInterval object representing the recurring interval

• An integer representing the number of recurrences

• The DatePeriod::EXCLUDE_START_DATE constant (optional) The second way of creating a DatePeriod object is to replace the number of recurrences in the third argument with a DateTime object representing the end date

The third way uses a single argument: a string formatted according to the ISO 8601 recurring time interval standard (see http://en.wikipedia.org/wiki/ISO_8601#Repeating_intervals)

Once you have created a DatePeriod object, you can display the recurring dates in a foreach loop using the DateTime format() method

Lets take a quick look at the three ways of creating a DatePeriod object First, using an integer to represent the number of occurrences:

The code in date_interval_04.php uses the following code to display the date of the second Tuesday of each month in 2011:

$start = new DateTime('12/31/2010');

$interval = DateInterval::createFromDateString('second Tuesday of next month');

$period = new DatePeriod($start, $interval, 12, DatePeriod::EXCLUDE_START_DATE); foreach ($period as $date) {

echo $date->format('l, F jS, Y') '<br>';

}

Trang 3

413

It produces the output shown in Figure 14-10

Figure 14-10 Calculating a recurring date is remarkably easy with the DatePeriod class

The first line of PHP code sets the start date as December 31, 2010 The next line uses the DateInterval static method createFromDateString() to set the interval at the second Tuesday of next month Both values are passed to the DatePeriod constructor, together with 12 as the number of recurrences and the DatePeriod::EXCLUDE_START_DATE constant The constants name is self-explanatory Finally, a foreach loop displays the resulting dates using the DateTime format() method

The code in date_interval_05.php has been amended to create a DatePeriod object the second way, using a DateTime object as the third argument to indicate the end date It looks like this:

$start = new DateTime('12/31/2010');

$interval = DateInterval::createFromDateString('second Tuesday of next month');

$end = new DateTime('12/31/2011');

$period = new DatePeriod($start, $interval, $end, DatePeriod::EXCLUDE_START_DATE);

foreach ($period as $date) {

echo $date->format('l, F jS, Y') '<br>';

}

This produces exactly the same output as shown in Figure 14-10

The third way of creating a DatePeriod object using the ISO 8601 recurring time interval standard is perhaps not as user,friendly, mainly because of the need to construct a string in the correct format, which looks like this:

Rn/YYYY-MM-DDTHH:MM:SStz/Pinterval

Rn is the letter R followed by the number of recurrences; tz is the time zone offset from UTC (or Z for UTC,

as shown in the following example); and Pinterval uses the same format as the DateInterval class The code in date_interval_06.php shows an example of how to use DatePeriod with an ISO 8601 recurring interval It looks like this:

Trang 4

CHAPTER 14

414

$period = new DatePeriod('R5/2011-02-05T00:00:00Z/P10D');

foreach ($period as $date) {

echo $date->format('l, F j, Y') '<br>';

}

The ISO recurring interval sets five recurrences from midnight UTC on February 5, 2011 at an interval of 10 days The recurrences are subsequent to the original date, so the preceding example produces six dates,

as shown in the following output

Chapter review

A large part of this chapter has been devoted to the powerful date and time features introduced in PHP 5.2 and 5.3 You dont need them every day, but theyre extremely useful and represent a major improvement

on the original PHP date and time functions MySQLs date and time functions also make it easy to format dates and execute queries based on temporal criteria

Perhaps the biggest problem with dates is deciding whether to use MySQL or PHP to handle the formatting and/or calculations A useful feature of the PHP DateTime class is that the constructor accepts a date stored in the MySQL format, so you can use an unformatted MySQL date or timestamp to create DateTime objects However, unless you need to perform further calculations, its more efficient to use the MySQL DATE_FORMAT() function as part of a SELECT query

This chapter has also provided you with three utility functions for formatting text and dates In the next chapter, youll learn how to store and retrieve related information in multiple database tables

Trang 5

415

Pulling Data from Multiple Tables

As I explained in Chapter 11, one of the major strengths of a relational database is the ability to link data in different tables by using the primary key from one table as a foreign key in another table The phpsols database has two tables: images and blog Its time to add some more and join them, so you can assign categories to blog entries and associate images with individual articles

You dont join multiple tables physically, but through SQL Often, you can join tables by identifying a direct relationship between primary and foreign keys In some cases, though, the relationship is more complex and needs to go through a third table that acts as a cross reference between the other two

In this chapter, youll learn how to establish the relationship between tables and insert the primary key from one table as a foreign key in another table Although it sounds difficult conceptually, its actually quite easy—you use a database query to look up the primary key in the first table, save the result, and use it in another query to insert it in the second table

In particular, youll learn about the following:

• Understanding the different types of table relationships

• Using a cross-reference table for many-to-many relationships

• Altering a tables structure to add new columns or an index

• Storing a primary key as a foreign key in another table

• Linking tables with INNER JOIN and LEFT JOIN

Understanding table relationships

The simplest type of relationship is one-to-one (often represented as 1:1) This type of relationship is

often found in databases that contain information only certain people should see For example, companies often store details of employees salaries and other confidential information in a separate table from the more widely accessible staff list Storing the primary key of each staff members record as a foreign key in the salaries table establishes a direct relationship between the tables, allowing the accounts department

to see the full range of information, while restricting others to the public information

Trang 6

CHAPTER 15

416

Theres no confidential information in the phpsols database, but you might create a one-to-one relationship between a single photo in the images table with an article in the blog table, as illustrated by Figure 15-1

Figure 15-1 A one-to-one relationship links one record directly with another

This is the simplest way of creating a relationship between the two tables, but its not ideal As more articles are added, the nature of the relationship is likely to change The photo associated with the first article in Figure 15-1 shows maple leaves floating on the water, so it might be suitable to illustrate an article about the changing seasons or autumn hues The crystal-clear water, bamboo water scoop, and bamboo pipe also suggest other themes that the photo could be used to illustrate So you could easily end

up with the same photo being used for several articles, or a one-to-many (or 1:n) relationship, as

represented by Figure 15-2

Figure 15-2 A one-to-many relationship links one record with several others

As you have already learned, a primary key must be unique So, in a 1:n relationship, you store the primary key from the table on the 1 side of the relationship (the primary or parent table) as a foreign key in the table on the n side (the secondary or child table) In this case, the image_id from the images table needs to be stored as a foreign key in the blog table Whats important to understand about a 1:n relationship is that its also a collection of 1:1 relationships Reading Figure 15-2 from right to left, each article has a relationship with a single image Without this one-on-one relationship, you wouldnt be able to identify which image is associated with a particular article

What happens if you want to associate more than one image to each article? You could create several columns in the blog table to hold the foreign keys, but this rapidly becomes unwieldy You might start off with image1, image2, and image3, but if most articles have only one image, two columns are redundant for

Trang 7

417

much of the time And are you going add an extra column for that extra-special article that requires four images?

When faced with the need to accommodate many-to-many (or n:m) relationships, you need a different

approach The images and blog tables dont contain sufficient records to demonstrate n:m relationships, but you could add a categories table to tag individual articles Most articles are likely to belong to multiple categories, and each category will be related with several articles

The way to resolve complex relationships is through a cross-reference table (sometimes called a linking

table), which establishes a series of one-to-one relationships between related records This is a special

table containing just two columns, both of which are declared a joint primary key Figure 15-3 shows how this works Each record in the cross-reference table stores details of the relationship between individual articles in the blog and categories tables To find all articles that belong to the Kyoto category, you match cat_id 1 in the categories table with cat_id 1 in the cross-reference table This identifies the records in the blog table with the article_id 2, 3, and 4 as being associated with Kyoto

Figure 15-3 A cross-reference table resolves many-to-many relationships as 1:1

Establishing relationships between tables through foreign keys has important implications for how you update and delete records If youre not careful, you end up with broken links Ensuring that dependencies

arent broken is known as maintaining referential integrity Well tackle this important subject in the next

chapter First, lets concentrate on retrieving information stored in separate tables linked through a foreign key relationship

Linking an image to an article

To demonstrate how to work with multiple tables, lets begin with the straightforward scenarios outlined in Figures 15-1 and 15-2: relations that can be resolved as 1:1 through the storage of the primary key from one table (the parent table) as a foreign key in a second table (the child or dependent table) This involves adding an extra column in the child table to store the foreign key

Altering the structure of an existing table

Ideally, you should design your database structure before populating it with data However, relational databases, such as MySQL, are flexible enough to let you add, remove, or change columns in tables even when they already contain records To associate an image with individual articles in the phpsols database, you need to add an extra column to the blog table to store image_id as a foreign key

Trang 8

CHAPTER 15

418

PHP Solution 15-1: Adding an extra column to a table

This PHP solution shows how to add an extra column to an existing table using phpMyAdmin It assumes that you created the blog table in the phpsols database in Chapter 13

1 Launch phpMyAdmin, select the phpsols database, and click the link for the blog table in the

left-hand navigation frame

2 Below the blog table structure in the main frame is a form that allows you to add extra

columns You want to add only one column, so the default value in the Add field(s) text box is

fine Its normal practice to put foreign keys immediately after the tables primary key, so

select the After radio button, and make sure the drop-down menu is set to article_id, as shown in the following screenshot Then click Go

This opens the screen for you to define column attributes Use the following settings:

 Field: image_id

 Type: INT

 Attributes: UNSIGNED

 Null: Selected

 Index: INDEX

Do not select AUTO_INCREMENT The Null check box has been set to selected because not all

articles will necessarily be associated with an image Click Save

You will be returned to the blog table structure, which should now look like this:

Trang 9

419

3 If you click the Browse tab at the top left of the screen, you will see that the value of image_id

is NULL in each record The challenge now is to insert the correct foreign keys without the need

to look up the numbers manually Well tackle that next

Inserting a foreign key in a table

The basic principle behind inserting a foreign key in another table is quite simple: you query the database

to find the primary key of the record that you want to link to the other table You can then use an INSERT or UPDATE query to add the foreign key to the target record

To demonstrate the basic principle, youll adapt the update form from Chapter 13 to add a drop-down menu that lists images already registered in the images table (see Figure 15-4)

Figure 15-4 A dynamically generated drop-down menu inserts the appropriate foreign key

The menu is dynamically generated by a loop that displays the results of a SELECT query Each images primary key is stored in the value attribute of the <option> tag When the form is submitted, the selected value is incorporated into the UPDATE query as the foreign key

To focus on the structure and PHP logic, the instructions in this chapter and the next one cover only MySQLi The only difference in the PDO version lies in the commands used to submit the SQL queries to the database and to display the results Fully commented PDO files are in the ch15 and

ch16 folders

Trang 10

CHAPTER 15

420

PHP Solution 15-2: Adding the image foreign key

This PHP solution shows how to update records in the blog table by adding the primary key of a selected image as a foreign key It adapts admin/blog_update_mysqli.php from Chapter 13 Use the version that you created in Chapter 13 Alternatively, copy blog_update_mysqli_03.php from the ch13 folder to the admin folder, and remove _03 from the filename

1 The existing SELECT query that retrieves details of the article to be updated needs to be

amended so that it includes the foreign key, image_id, and the result needs to be bound to a new result variable, $image_id You then need to run a second SELECT query to get the details

of the images table, but before you can do so, you need to free the database resources by applying the free_result() method on the prepared statement ($stmt) Add the following code highlighted in bold to the existing script:

if (isset($_GET['article_id']) && !$_POST) {

// prepare SQL query

$sql = 'SELECT article_id, image_id, title, article

FROM blog WHERE article_id = ?';

$stmt->prepare($sql);

// bind the query parameter

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

// bind the results to variables

$stmt->bind_result($article_id, $image_id, $title, $article);

// execute the query, and fetch the result

$OK = $stmt->execute();

$stmt->fetch();

// free the database resources for the second query

$stmt->free_result();

}

Notice that the conditional statement wrapping the call to the prepare() method and

subsequent code has been removed You dont need it after verifying that the prepared statement doesnt contain any syntax errors

2 Inside the form, you need to display the filenames stored in the images table Since the

second SELECT statement doesnt rely on external data, its simpler to use the query() method instead of a prepared statement Add the following code after the article text area (its all new code, but the PHP sections are highlighted in bold for ease of reference):

<p>

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

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

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

<?php

// get the list images

$getImages = 'SELECT image_id, filename

FROM images ORDER BY filename';

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

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

?>

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

TỪ KHÓA LIÊN QUAN