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

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

10 180 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 537,37 KB

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

Nội dung

In this chapter, youll learn about the following: • Extracting the first section of a longer text item • Using an alias in a SQL query • Displaying text retrieved from a database as para

Trang 1

MANAGING CONTENT

381

You can rewrite it like this:

$result = @ $conn->query($sql);

if (!$result) {

// redirect to custom error page

}

You should also remove the conditional statements surrounding MySQLi prepared statements once you have verified that they dont generate SQL syntax errors For example, your development code might look like this:

if ($stmt->prepare($sql)) {

$stmt->bind_param('s', $searchterm);

$stmt->bind_result($image_id, $filename, $caption);

$stmt->execute();

$stmt->store_result();

$numRows = $stmt->num_rows;

} else {

echo $stmt->error;

}

To deploy it on a live website, change it to this:

$stmt->prepare($sql);

$stmt->bind_param('s', $searchterm);

$stmt->bind_result($image_id, $filename, $caption);

$stmt->execute();

$stmt->store_result();

$numRows = $stmt->num_rows;

Chapter review

Content management with a database involves inserting, selecting, updating, and deleting records Each records primary key plays a vital role in the update and delete processes Most of the time, generating the primary key is handled automatically by MySQL when a record is first created Thereafter, finding a records primary key is simply a matter of using a SELECT query, either by displaying a list of all records, or

by searching for something you know about the record, such as a title or words in an article

MySQLi and PDO prepared statements make database queries more secure by removing the need to ensure that quotes and control characters are properly escaped They also speed up your application if the same query needs to be repeated during a script using different variables Instead of validating the SQL every time, the script needs do it only once with the placeholders

Although this chapter has concentrated on content management, the same basic techniques apply to most interaction with a database Of course, theres a lot more to SQL—and to PHP In the next chapter, Ill address some of the most common problems, such as displaying only the first sentence or so of a long text field and handling dates Then, in Chapter 15 and 16, well explore working with more than one table in

a database

Trang 2

CHAPTER 13

382

Trang 3

383

Chapter 14

Formatting Text and Dates

We have some unfinished business left over from the previous chapter Figure 13-1 in Chapter 13 shows content from the blog table with just the first two sentences of each article displayed and a link to the rest

of the article However, I didnt show you how it was done There are several ways to extract a shorter piece of text from the beginning of a longer one Some are rather crude and usually leave you with a broken word at the end In this chapter, youll learn how to extract complete sentences

The other piece of unfinished business is that full list of articles in blog_list_mysqli.php and blog_list_pdo.php displays the MySQL timestamp in its raw state, which isnt very elegant You need to reformat the date to look user friendlier Handling dates can be a major headache because MySQL and PHP use completely different methods of storing them This chapter guides you through the minefield of storing and displaying dates in a PHP/MySQL context Youll also learn about the powerful new date and time features introduced in PHP 5.2 and 5.3, which make complex date calculations, such as finding the second Tuesday of each month, childs play

In this chapter, youll learn about the following:

• Extracting the first section of a longer text item

• Using an alias in a SQL query

• Displaying text retrieved from a database as paragraphs

• Formatting dates with MySQL

• Selecting records based on temporal criteria

• Using the PHP DateTime, DateTimeZone, DateInterval, and DatePeriod classes

Displaying a text extract

There are many ways to extract the first few lines or characters from a longer piece of text Sometimes, you need just the first 20 or 30 characters to identify an item At other times, its preferable to show complete sentences or paragraphs

Trang 4

CHAPTER 14

384

Extracting a fixed number of characters

You can extract a fixed number of characters from the beginning of a text item either with the PHP substr() function or with the LEFT() function in a SQL query

Using the PHP substr() function

The substr() function extracts a substring from a longer string It takes three arguments: the string you want to extract the substring from, the starting point (counted from 0), and the number of characters to extract The following code displays the first 100 characters of $row['article']:

echo substr($row['article'], 0, 100);

The original string remains intact If you omit the third argument, substr() extracts everything to the end

of the string This makes sense only if you choose a starting point other than 0

Using the MySQL LEFT() function

The MySQL LEFT() function extracts characters from the beginning of a column It takes two arguments: the column name and the number of characters to extract The following retrieves article_id, title, and the first 100 characters from the article column of the blog table:

SELECT article_id, title, LEFT(article, 100)

FROM blog ORDER BY created DESC

Whenever you use a function in a SQL query like this, the column name no longer appears in the result set

as article, but as LEFT(article, 100) instead So its a good idea to assign an alias to the affected column using the AS keyword You can either reassign the columns original name as the alias or use a descriptive name as in the following example (the code is in blog_left_mysqli.php and blog_left_pdo.php in the ch14 folder):

SELECT article_id, title, LEFT(article, 100) AS first100

FROM blog ORDER BY created DESC

If you process each record as $row, the extract is in $row['first100'] To retrieve both the first 100 characters and the full article, simply include both in the query like this:

SELECT article_id, title, LEFT(article, 100) AS first100, article

FROM blog ORDER BY created DESC

Taking a fixed number of characters produces a very crude result, as Figure 14-1 shows

Figure 14-1 Selecting the first 100 characters from an article chops words in half

Trang 5

FORMATTING TEXT AND DATES

385

Ending an extract on a complete word

To end an extract on a complete word, you need to find the final space and use that to determine the length of the substring So, if you want the extract to be a maximum of 100 characters, use either of the preceding methods to start with, and store the result in $extract Then you can use the PHP string functions strrpos() and substr() to find the last space and end the extract like this (the code is in blog_word_mysqli.php and blog_word_pdo.php):

$extract = $row['first100'];

// find position of last space in extract

$lastSpace = strrpos($extract, ' ');

// use $lastSpace to set length of new extract and add

echo substr($extract, 0, $lastSpace) ' ';

This produces the more elegant result shown in Figure 14-2 It uses strrpos(), which finds the last position of a character within another string Since youre looking for a space, the second argument is a pair of quotes with a single space between them The result is stored in $lastSpace, which is passed as the third argument to substr(), finishing the extract on a complete word Finally, add a string containing three dots and a space, and join the two with the concatenation operator (a period or dot)

Figure 14-2 Ending the extract on a complete word produces a more elegant result

Extracting the first paragraph

Assuming that you have entered your text in the database using the Enter or Return key to indicate new paragraphs, this is very easy Simply retrieve the full text, use strpos() to find the first new line character, and use substr() to extract the first section of text up to that point

The following SQL query is used in blog_para_mysqli.php, and blog_para_pdo.php:

SELECT article_id, title, article

FROM blog ORDER BY created DESC

The following code is used to display the first paragraph of article:

echo substr($row['article'], 0, strpos($row['article'], PHP_EOL));

If that makes your head spin, then lets break it up and take a look at the third argument on its own:

strpos($row['article'], PHP_EOL)

This locates the first end of line character in $row['article'] in a cross-platform way using the PHP_EOL constant (see Chapter 7) You could rewrite the code like this:

$newLine = strpos($row['article'], PHP_EOL);

echo substr($row['article'], 0, $newLine);

Trang 6

CHAPTER 14

386

Both sets of code do exactly the same thing, but PHP lets you nest a function as an argument passed to another function As long as the nested function returns a valid result, you can frequently use shortcuts like this

Using the PHP_EOL constant eliminates the problem of dealing with the different characters used by Linux, Mac OS X, and Windows to insert a new line

Displaying paragraphs

Since were on the subject of paragraphs, many beginners are confused by the fact that all the text retrieved from a database is displayed as a continuous block, with no separation between paragraphs HTML ignores whitespace, including new lines To get text stored in a database displayed as paragraphs, you have the following options:

• Store your text as HTML

• Convert new lines to <br /> tags

• Create a custom function to replace new lines with paragraph tags

The first option involves installing an HTML editor, such as CK Editor (http://ckeditor.com/) or TinyMCE (http://tinymce.moxiecode.com/) in your content management forms Mark up your text as you insert or update it The HTML is stored in the database, and the text displays as intended Installing one of these editors is beyond the scope of this book

The simplest option is to pass your text to the nl2br() function before displaying it like this:

echo nl2br($row['article']);

Voilà!—paragraphs Well, not really The nl2br() function converts new line characters to <br /> tags

As a result, you get fake paragraphs Its a quick and dirty solution, but not ideal

The nl2br() function inserts the slash before the closing angle bracket for compatibility with XHTML The trailing slash is optional in HTML5, so your code remains valid even if youre not using XHTML-style markup

To display text retrieved from a database as genuine paragraphs, wrap the database result in a pair of paragraph tags, and then use the preg_replace() function to convert consecutive new line characters

to a closing </p> tag immediately followed by an opening <p> tag like this:

<p><?php echo preg_replace('/[\r\n]+/', '</p><p>', $row['article']); ?></p>

The regular expression used as the first argument matches one or more carriage returns and/or newline characters You cant use the PHP_EOL constant here because you need to match all consecutive newline characters and replace them with a single pair of paragraph tags Remembering the pattern for a regex can

be difficult, so you can easily convert this into a custom function like this:

function convertToParas($text) {

$text = trim($text);

return '<p>' preg_replace('/[\r\n]+/', '</p><p>', $text) '</p>';

}

Trang 7

FORMATTING TEXT AND DATES

387

This trims whitespace, including newline characters from the beginning and end of the text, adds a <p> tag

at the beginning, replaces internal sequences of newline characters with closing and opening tags, and appends a closing </p> tag at the end

You can then use the function like this:

<?php echo convertToParas($row['article']); ?>

The code for the function definition is in utility_funcs.inc.php in the ch14 folder You can see it being used in blog_ptags_mysqli.php and blog_ptags_pdo.php

Extracting complete sentences

PHP has no concept of what constitutes a sentence Counting periods means you ignore all sentences that end with an exclamation point or question mark You also run the risk of breaking a sentence on a decimal point or cutting off a closing quote after a period To overcome these problems, I have devised a PHP function called getFirst() that identifies the punctuation at the end of a normal sentence:

• A period, question mark, or exclamation point

• Optionally followed by a single or double quote

• Followed by one or more spaces

The getFirst() function takes two arguments: the text from which you want to extract the first section and the number of sentences you want to extract The second argument is optional; if its not supplied, the function extracts the first two sentences The code looks like this (its in utility_funcs.inc.php):

function getFirst($text, $number=2) {

// use regex to split into sentences

$sentences = preg_split('/([.?!]["\']?\s)/', $text, $number+1, 

PREG_SPLIT_DELIM_CAPTURE);

if (count($sentences) > $number * 2) {

$remainder = array_pop($sentences);

} else {

$remainder = '';

}

$result = array();

$result[0] = implode('', $sentences);

$result[1] = $remainder;

return $result;

}

All you really need to know about this function is that it returns an array containing two elements: the extracted sentences and any text thats left over You can use the second element to create a link to a page containing the full text

If youre interested in how the function works, read on The line highlighted in bold uses a regex to identify the end of each sentence—a period, question mark, or exclamation point, optionally followed by a double

or single quotation mark and a space This is passed as the first argument to preg_split(), which uses the regex to split the text into an array The second argument is the target text The third argument determines the maximum number of chunks to split the text into You want one more than the number of sentences to be extracted Normally, preg_split() discards the characters matched by the regex, but using PREG_SPLIT_DELIM_CAPTURE as the fourth argument together with a pair of capturing parentheses

Trang 8

CHAPTER 14

388

in the regex preserves them as separate array elements In other words, the elements of the $sentences array consist alternately of the text of a sentence followed by the punctuation and space like this:

$sentences[0] = '"Hello, world';

$sentences[1] = '!" ';

Its impossible to know in advance how many sentences there are in the target text, so you need to find out if theres anything remaining after extracting the desired number of sentences The conditional statement uses count() to ascertain the number of elements in the $sentences array and compares the result with $number multiplied by 2 (because the array contains two elements for each sentence) If theres more text, array_pop() removes the last element of the $sentences array and assigns it to

$remainder If theres no further text, $remainder is an empty string

The final stage of the function uses implode() with an empty string as its first argument to stitch the extracted sentences back together and then returns a two-element array containing the extracted text and anything thats left over

Dont worry if you found that explanation hard to follow The code is quite advanced It took a lot of experimentation to build the function, and I have improved it gradually over the years

PHP Solution 14-1: Displaying the first two sentences of an article

This PHP solution shows how to display an extract from each article in the blog table using the getFirst() function described in the preceding section If you created the Japan Journey site earlier in the book, use blog.php Alternatively, use blog_01.php from the ch14 folder, and save it as blog.php in the phpsols site root You also need footer.inc.php, menu.inc.php, title.inc.php, and connection.inc.php in the includes folder

1 Copy utility_funcs.inc.php from the ch14 folder to the includes folder, and include it in

the PHP code block above the DOCTYPE declaration Also include the MySQL connection file, and create a connection to the database This page needs read-only privileges, so use read

as the argument passed to dbConnect() like this:

require_once('./includes/connection.inc.php');

require_once('./includes/utility_funcs.inc.php');

// create database connection

$conn = dbConnect('read');

2 Prepare a SQL query to retrieve all records from the blog table like this:

$sql = 'SELECT * FROM blog ORDER BY created DESC';

3 For MySQLi, use this:

$result = $conn->query($sql);

Theres no need to submit the query at this stage for PDO

4 Create a loop inside the maincontent <div> to display the results

For MySQLi, use this:

<div id="maincontent">

<?php

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

Trang 9

FORMATTING TEXT AND DATES

389

?>

<h2><?php echo $row['title']; ?></h2>

<p><?php $extract = getFirst($row['article']);

echo $extract[0];

if ($extract[1]) {

echo '<a href="details.php?article_id=' $row['article_id'] '">  More</a>';

} ?></p>

<?php } ?>

</div>

The code is the same for PDO, except for this line:

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

Replace it with this:

foreach ($conn->query($sql) as $row) {

The main part of the code is inside the <p> tags The getFirst() function processes

$row['article'] and stores the result in $extract The first two sentences of article in

$extract[0] are immediately displayed If $extract[1] contains anything, it means there is more to display So the code inside the if statement displays a link to details.php with the articles primary key in a query string

5 Save the page, and test it in a browser You should see the first two sentences of each article

displayed as shown in Figure 14-3

Figure 14-3 The first two sentences have been extracted cleanly from the longer text

6 Test the function by adding a number as a second argument to getFirst() like this:

$extract = getFirst($row['article'], 3);

This displays the first three sentences If you increase the number so that it equals or

exceeds the number of sentences in an article, the More link wont be displayed

You can compare your code with blog_mysqli.php and blog_pdo.php in the ch14 folder Well look at details.php in Chapter 15 Before that, lets tackle the minefield presented by using dates

in a dynamic website

Trang 10

CHAPTER 14

390

Lets make a date

Dates and time are so fundamental to modern life that we rarely pause to think how complex they are There are 60 seconds to a minute and 60 minutes to an hour, but 24 hours to a day Months range between

28 and 31 days, and a year can be either 365 or 366 days The confusion doesnt stop there, because 7/4 means July 4 to an American or Japanese, but 7 April to a European To add to the confusion, PHP and MySQL handle dates differently Time to bring order to chaos

How MySQL handles dates

In MySQL, dates and time are always expressed in descending order from the largest unit to the smallest: year, month, date, hour, minutes, seconds Hours are always measured using the 24-hour clock with midnight expressed as 00:00:00 Even if this seems unfamiliar to you, its the recommendation laid down

by the International Organization for Standardization (ISO)

If you attempt to store a date in any other format than year, month, date, MySQL inserts 0000-00-00 in the database MySQL allows considerable flexibility about the separator between the units (any punctuation symbol is OK), but there is no argument about the order—its fixed

Ill come back later to the way you insert dates into MySQL, because its best to validate them and format them with PHP First, lets take a look at some of the things you can do with dates once theyre stored in MySQL MySQL has many date and time functions, which are listed with examples at http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

One of the most useful functions is DATE_FORMAT(), which does exactly what its name suggests

Formatting dates in a SELECT query with DATE_FORMAT()

The syntax for DATE_FORMAT() is as follows:

DATE_FORMAT(date, format)

Normally, date is the table column to be formatted, and format is a string composed of formatting

specifiers and any other text you want to include Table 14-1 lists the most common specifiers, all of which are case-sensitive

Table 14-1 Frequently used MySQL date format specifiers

Year

%b Abbreviated name, three letters Jan, Sep Month

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