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

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

10 273 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 614,16 KB

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

Nội dung

221 It doesnt matter which order your methods appear inside the class definition, but its common practice to keep all public methods together after the constructor and to put protected m

Trang 1

221

It doesnt matter which order your methods appear inside the class definition, but its common practice to keep all public methods together after the constructor and to put protected

methods at the bottom of the file This makes the code easier to maintain

Insert the following definition between the constructor and the checkType() definition:

public function test() {

echo 'File: ' $this->_original '<br>';

echo 'Original width: ' $this->_originalwidth '<br>';

echo 'Original height: ' $this->_originalheight '<br>';

echo 'Image type: ' $this->_imageType '<br>';

if ($this->_messages) {

print_r($this->_messages);

}

}

This uses echo and print_r() to display the value of the properties

6 To test the class definition so far, save Thumbnail.php, and add the following code block

above the DOCTYPE declaration in create_thumb.php (the code is in

create_thumb_win02.php and create_thumb_mac02.php in the ch08 folder):

<?php

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

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

try {

$thumb = new Ps2_Thumbnail($_POST['pix']);

$thumb->test();

} catch (Exception $e) {

echo $e->getMessage();

}

}

?>

The name of the submit button in create_thumb.php is create, so this code runs only when the form has been submitted It includes the Ps2_Thumbnail class definition, creates an

instance of the class, passing the selected value from the form as an argument, and calls the test() method

7 Save create_thumb.php, and load it into a browser Select an image, and click Create

Thumbnail This produces output similar to Figure 8-1

Trang 2

222

Figure 8-1 Displaying the details of the selected image confirms the code is working

If necessary, check your code against Thumbnail_01.php in the ch08 folder

Although some properties have default values, you need to provide the option to change them by creating public methods to set the maximum size of the thumbnail image, and the suffix applied to the base of the filename You also need to tell the class where to create the thumbnail The formal term for this type of

method is a mutator me thod However, because it sets a value, its commonly referred to as a se tter

method The next stage is to create the setter methods

PHP Solution 8-2: Creating the setter methods

In addition to setting the value of protected properties, setter methods play an important role in ensuring the validity of the value being assigned Continue working with the same class definition Alternatively, use Thumbnail_01.php in the ch08 folder

1 Begin by creating the setter method for the folder where the thumbnail is to be created Add the

following code to Thumbnail.php after the constructor definition

public function setDestination($destination) {

if (is_dir($destination) && is_writable($destination)) {

// get last character

$last = substr($destination, -1);

// add a trailing slash if missing

if ($last == '/') || $last == '\\') {

$this->_destination = $destination;

} else {

$this->_destination = $destination DIRECTORY_SEPARATOR;

}

} else {

$this->_messages[] = "Cannot write to $destination.";

}

}

Trang 3

223

This begins by checking that $destination is a folder (directory) and that its writable If it isnt, the error message in the else clause at the end of the method definition is added to the

$_messages property Otherwise, the rest of the code is executed

Before assigning the value of $destination to the $_destination property, the code

checks whether the value submitted ends in a forward slash or backslash It does this by extracting the final character in $destination, using the substr() function The second argument to substr() determines the position from which to start the extract A negative number counts from the end of the string If the third argument is omitted, the function returns the rest of the string So, $last = substr($destination, -1) has the effect of extracting the last character, and storing it in $last

The conditional statement checks whether $last is a forward slash or a backslash Two

backslashes are needed because PHP uses a backslash to escape quotes (see

“Understanding when to use quotes” and “Using escape sequences” in Chapter 3)

Its necessary to check for both forward slashes and backslashes in $destination because

a Windows user might use backslashes out of habit If the conditional statement confirms that the final character is a forward slash or a backslash, $destination is assigned to the

$_destination property Otherwise, the else clause concatenates the PHP constant

DIRECTORY_SEPARATOR to the end of $destination before assigning it to the

$_destination property The DIRECTORY_SEPARATOR constant automatically chooses the right type of slash depending on the operating system

PHP treats forward slashes or backslashes equally in a path Even if this results in adding the opposite type of slash, the path remains valid as far as PHP is concerned

2 The setter method for the maximum size of the thumbnail simply needs to check that the value

is a number Add the following code to the class definition:

public function setMaxSize($size) {

if (is_numeric($size)) {

$this->_maxSize = abs($size);

}

}

The is_numeric() function checks that the submitted value is a number If it is, its assigned

to the $_maxSize property As a precaution, the value is passed to the abs() function, which converts a number to its absolute value In other words, a negative number is converted into a positive one

If the submitted value isnt a number, nothing happens The propertys default value remains unchanged

3 The setter function for the suffix inserted in the filename needs to make sure the value doesnt

contain any special characters The code looks like this:

Trang 4

224

public function setSuffix($suffix) {

if (preg_match('/^\w+$/', $suffix)) {

if (strpos($suffix, '_') !== 0) {

$this->_suffix = '_' $suffix;

} else {

$this->_suffix = $suffix;

}

} else {

$this->_suffix = '';

}

}

This uses preg_match(), which takes a regular expression as its first argument and

searches for a match in the value passed as the second argument Regular expressions need

to be wrapped in a pair of matching delimiter characters—normally forward slashes, as used here Stripped of the delimiters, the regex looks like this:

^\w+$

In this context, the caret (^) tells the regex to start at the beginning of the string The \w matches any alphanumeric character or an underscore The + means match one or more of the preceding character, and the $ means match the end of the string In other words, the regex matches a string that contains only alphanumeric characters and underscores If the string contains spaces or special characters, it wont match

As mentioned before, regexes can be difficult to learn, but theyre extremely useful in PHP, JavaScript, and other web-related languages

If the match fails, the else clause at the end of the method definition sets the $_suffix property to an empty string Otherwise, this conditional statement is executed

if (strpos($suffix, '_') !== 0) {

The condition equates to true if the first character of $suffix is not an underscore It uses

the strpos() function to find the position of the first underscore If the first character is an underscore, the value returned by strpos() is 0 However, if $suffix doesnt contain an underscore, strpos() returns false As explained in Chapter 3, 0 is treated by PHP as false, so the condition needs to use the “not identical” operator (with two equal signs) So, if the suffix doesnt begin with an underscore, one is added Otherwise, the original value is preserved

Dont confuse strpos() and strrpos() The former finds the position of the first matching character The latter searches the string in reverse

Trang 5

225

4 Update the test() method to display the values of the properties for which you have just

created setter methods The revised code looks like this:

public function test() {

echo 'File: ' $this->_original '<br>';

echo 'Original width: ' $this->_originalwidth '<br>';

echo 'Original height: ' $this->_originalheight '<br>';

echo 'Image type: ' $this->_imageType '<br>';

echo 'Destination: ' $this->_destination '<br>';

echo 'Max size: ' $this->_maxSize '<br>';

echo 'Suffix: ' $this->_suffix '<br>';

if ($this->_messages) {

print_r($this->_messages);

}

}

5 Test the updated class by using the new setter methods in create_thumb.php like this:

$thumb = new Ps2_Thumbnail($_POST['pix']);

$thumb->setDestination('C:/upload_test/thumbs/');

$thumb->setMaxSize(100);

$thumb->setSuffix('small');

$thumb->test();

6 Save both pages, and select an image from the list in create_thumb.php You should see

results similar to Figure 8-2

Figure 8-2 Verifying that the setter methods work

7 Try a number of tests, omitting the trailing slash from the value passed to setDestination()

or selecting a nonexisting folder Also pass invalid values to the setters for the maximum size and suffix An invalid destination folder produces an error message, but the others fail silently, using the default value for the maximum size or an empty string for the suffix

Trang 6

226

If necessary, compare your code with Thumbnail_02.php in the ch08 folder

You might not agree with my decision to fail silently when the values passed as arguments are invalid By now, though, you should have sufficient experience of conditional statements to adapt the code to your own requirements For example, if you want the setter method for the thumbnails maximum size to return

an error message instead of failing silently, check that the value is greater than zero, and add an else clause to generate the error message The else clause should also set the $_canProcess property to false to prevent the class from attempting to create a thumbnail image This is how you would adapt the setMaxSize() method:

public function setMaxSize($size) {

if (is_numeric($size) && $size > 0) {

$this->_maxSize = $size;

} else {

$this->_messages[] = 'The value for setMaxSize() must be a positive number.'; $this->_canProcess = false;

}

}

Before you can create the thumbnail image, you need to calculate its size The value set in the $_maxSize property determines the width or height, depending which is larger To avoid distorting the thumbnail, you need to calculate the scaling ratio for the shorter dimension The ratio is calculated by dividing the maximum thumbnail size by the larger dimension of the original image

For example, the original image of the Golden Pavilion (kinkakuji.jpg) is 270  346 pixels If the maximum size is set at 120, dividing 120 by 346 produces a scaling ratio of 0.3468 Multiplying the width of the original image by this ratio fixes the thumbnails width at 94 pixels (rounded up to the nearest whole number), maintaining the correct proportions Figure 8-3 shows how the scaling ratio works

Figure 8-3 Working out the scaling ratio for a thumbnail image

Trang 7

227

The base filename also needs to be split from the filename extension in preparation for inserting the suffix indicating its a thumbnail

PHP Solution 8-3: Final preparations for generating the thumbnail

This PHP solution adds three new methods to the Ps2_Thumbnail class: a public method that initiates the generation of the thumbnail image, and two internal methods that calculate the thumbnails dimensions and split the images base name from its filename extension In PHP Solution 6-5, isolating the filename extension was done by searching for a dot or period in the filename This time, you know the file types in advance, so a regular expression is used

Continue working with your existing class definition Alternatively, use Thumbnail_02.php in the ch08 folder

1 Calculating the thumbnail dimensions doesnt require any further user input, so it can be

handled by an internal method Add the following code to the class definition Its a protected method, so put it at the end of the file, just inside the closing curly brace

protected function calculateSize($width, $height) {

if ($width <= $this->_maxSize && $height <= $this->_maxSize) {

$ratio = 1;

} elseif ($width > $height) {

$ratio = $this->_maxSize/$width;

} else {

$ratio = $this->_maxSize/$height;

}

$this->_thumbwidth = round($width * $ratio);

$this->_thumbheight = round($height * $ratio);

}

The dimensions of the original image are stored as properties of the Ps2_Thumbnail object,

so you could refer to them directly as $this->_originalWidth and

$this->_originalHeight However, the method needs to refer to these values often, so I decided to pass them as arguments to make the code easier to read and type

The conditional statement begins by checking if the width and height of the original image are less than or equal to the maximum size If they are, the image doesnt need to be resized, so the scaling ratio is set to 1

The elseif clause checks if the width is greater than the height If it is, the width is used to calculate the scaling ratio The else clause is invoked if the height is greater or both sides are equal In either case, the height is used to calculate the scaling ratio

The last two lines multiply the original width and height by the scaling ratio, and assign the results to the $_thumbwidth and $_thumbheight properties The calculation is wrapped in the round() function, which rounds the result to the nearest whole number

2 Next, add the method that gets the filename and strips off the filename extension The code

looks like this:

protected function getName() {

Trang 8

228

$extensions = array('/\.jpg$/i', '/\.jpeg$/i', '/\.png$/i', '/\.gif$/i'); $this->_name = preg_replace($extensions, '', basename($this->_original)); }

The code inside the method is only two lines, but theres a lot going on The first line creates

an array of regular expressions As mentioned earlier, regexes are wrapped in delimiter characters, normally forward slashes The i after the closing slash of each regex tells it to peform a case-insensitive search

A period normally represents any character, but escaping it with a backslash makes the regex look only for a period The $ matches the end of the string Everything else matches a literal character In other words, these regexes match jpg, jpeg, png, and gif in a case-insensitive manner

The second line uses the preg_replace() function, which performs a find and replace operation using a regex or array of regexes The first argument is the value(s) you want to replace The second argument is the replacement text—in this case, an empty string The third argument is the subject of the search and replace operation

Here, the third argument is the value of the $_original property, which has been passed to the basename() function You met basename() in PHP Solution 4-3 It extracts the filename from a path So, the code in the second line searches the filename for an image filename extension and replaces it with nothing In other words, it strips off the filename extension, and assigns the result to the $_name property

3 These two methods need to be called by the method that creates the thumbnail image Add the

following public method to the class definition above the protected methods:

public function create() {

if ($this->_canProcess && $this->_originalwidth != 0) {

$this->calculateSize($this->_originalwidth, $this->_originalheight); $this->getName();

} elseif ($this->_originalwidth == 0) {

$this->_messages[] = 'Cannot determine size of ' $this->_original; }

}

This checks that $_canProcess is true and that the width of the original image is not 0 The second test is necessary because getimagesize() sets the width and height to 0 if it cant determine the size This usually happens if the image format contains multiple images The method then calls the two internal methods you have just created If the $_originalwidth property is 0, an error message is added to the $_messages property

4 To test the new methods, amend the test() method like this:

public function test() {

echo 'File: ' $this->_original '<br>';

echo 'Original width: ' $this->_originalwidth '<br>';

echo 'Original height: ' $this->_originalheight '<br>';

echo 'Image type: ' $this->_imageType '<br>';

Trang 9

229

echo 'Destination: ' $this->_destination '<br>';

echo 'Max size: ' $this->_maxSize '<br>';

echo 'Suffix: ' $this->_suffix '<br>';

echo 'Thumb width: ' $this->_thumbwidth '<br>';

echo 'Thumb height: ' $this->_thumbheight '<br>';

echo 'Base name: ' $this->_name '<br>';

if ($this->_messages) {

print_r($this->_messages);

}

}

5 The call to create() needs to come before the test() method Otherwise, the new values

wont have been generated Amend the code in create_thumb.php like this:

$thumb = new Ps2_Thumbnail($_POST['pix']);

$thumb->setDestination('C:/upload_test/thumbs/');

$thumb->setMaxSize(100);

$thumb->setSuffix('small');

$thumb->create();

$thumb->test();

6 Test the updated class by selecting an image in create_thumb.php and clicking Create Thumbnail You should see the values displayed onscreen, as shown in Figure 8-4

Figure 8-4 The class is now generating all the values needed to create the thumbnail image

If necessary, check your code against Thumbnail_03.php in the ch08 folder

After you have gathered all the necessary information, you can generate a thumbnail image from a larger one This involves creating image resources for the original image and the thumbnail For the original image, you need to use one of these functions specific to the images MIME type:

Trang 10

230

• imagecreatefromjpeg()

• imagecreatefrompng()

• imagecreatefromgif()

The functions take a single argument: the path to the file Because the thumbnail doesnt yet exist, you use a different function, imagecreatetruecolor(), which takes two arguments—the width and height (in pixels)

The function that creates a resized copy of an image is imagecopyresampled(), which takes no fewer than ten arguments—all of them required The arguments fall into five pairs as follows:

• References to the two image resources—copy first, original second

• The x and y coordinates of where to position the top-left corner of the copied image

• The x and y coordinates of the top-left corner of the original

• The width and height of the copy

• The width and height of the area to copy from the original

Figure 8-5 shows how the last four pairs of arguments can be used to extract a specific area, rather than copy the whole image, using the following arguments to imagecopyresampled():

imagecopyresampled($thumb, $source, 0, 0, 170, 20, $thbwidth,$thbheight, 170, 102);

Figure 8-5 The imagecopyresampled() function allows you to copy part of an image

The x and y coordinates of the area to copy are measured in pixels from the top left of the image The x and y axes begin at 0 at the top left, and increase to the right and down By setting the width and height of the area to copy to 170 and 102, respectively, PHP extracts the area outlined in white

So, now you know how websites manage to crop uploaded images They calculate the coordinates dynamically using JavaScript or Flash, both of which are beyond the scope of this book For the Ps2_Thumbnail class, youll use the whole of the original image to generate the thumbnail

After creating the copy with imagecopyresampled(), you need to save it, again using a function specific

to the MIME type, namely:

• imagejpeg()

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