JETZT ONLINE BESTELLEN
Second Edition Mai 2006
ISBN 978-0-596-00681-5
540 Seiten
EUR32.00
Weitere Informationen zu diesem Buch
Inhaltsverzeichnis |
Rezensionen |
Inhaltsverzeichnis
- Chapter 1: Introduction to PHP
- InhaltsvorschauPHP is a simple yet powerful language designed for creating HTML content. This chapter covers essential background on the PHP language. It describes the nature and history of PHP; which platforms it runs on; and how to download, install, and configure it. This chapter ends by showing you PHP in action, with a quick walkthrough of several PHP programs that illustrate common tasks, such as processing form data, interacting with a database, and creating graphics.PHP can be used in three primary ways:
- Server-side scripting
-
PHP was originally designed to create dynamic web content, and it is still best suited for that task. To generate HTML, you need the PHP parser and a web server to send the documents. PHP has also become popular for generating XML documents, graphics, Flash animations, PDF files, and more.
- Command-line scripting
-
PHP can run scripts from the command line, much like Perl, awk, or the Unix shell. You might use the command-line scripts for system administration tasks, such as backup and log parsing.
- Client-side GUI applications
-
Using PHP-GTK (
http://gtk.php.net), you can write full-blown, cross-platform GUI applications in PHP.
In this book, we'll concentrate on the first item, using PHP to develop dynamic web content.PHP runs on all major operating systems, from Unix variants including Linux, FreeBSD, and Solaris to Windows and Mac OS X. It can be used with all leading web servers, including Apache, Microsoft IIS, and the Netscape/iPlanet servers.The language is very flexible. For example, you aren't limited to outputting just HTML or other text files—any document format can be generated. PHP has built-in support for generating PDF files, GIF, JPG, and PNG images, and Flash movies.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - What Does PHP Do?
- InhaltsvorschauPHP can be used in three primary ways:
- Server-side scripting
-
PHP was originally designed to create dynamic web content, and it is still best suited for that task. To generate HTML, you need the PHP parser and a web server to send the documents. PHP has also become popular for generating XML documents, graphics, Flash animations, PDF files, and more.
- Command-line scripting
-
PHP can run scripts from the command line, much like Perl, awk, or the Unix shell. You might use the command-line scripts for system administration tasks, such as backup and log parsing.
- Client-side GUI applications
-
Using PHP-GTK (
http://gtk.php.net), you can write full-blown, cross-platform GUI applications in PHP.
In this book, we'll concentrate on the first item, using PHP to develop dynamic web content.PHP runs on all major operating systems, from Unix variants including Linux, FreeBSD, and Solaris to Windows and Mac OS X. It can be used with all leading web servers, including Apache, Microsoft IIS, and the Netscape/iPlanet servers.The language is very flexible. For example, you aren't limited to outputting just HTML or other text files—any document format can be generated. PHP has built-in support for generating PDF files, GIF, JPG, and PNG images, and Flash movies.One of PHP's most significant features is its wide-ranging support for databases. PHP supports all major databases (including MySQL, PostgreSQL, Oracle, Sybase, and ODBC-compliant databases), and even many obscure ones. With PHP, creating web pages with dynamic content from a database is remarkably simple.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - A Brief History of PHP
- InhaltsvorschauRasmus Lerdorf first conceived of PHP in 1994, but the PHP that people use today is quite different from the initial version. To understand how PHP got where it is today, it is useful to know the historical evolution of the language. Here's that story, as told by Rasmus.Here is the PHP 1.0 announcement that I posted to the Usenet newsgroup
comp.infosystems.www.authoring.cgiin June 1995:From: rasmus@io.org (Rasmus Lerdorf) Subject: Announce: Personal Home Page Tools (PHP Tools) Date: 1995/06/08 Message-ID: <3r7pgp$aa1@ionews.io.org>#1/1 organization: none newsgroups: comp.infosystems.www.authoring.cgi Announcing the Personal Home Page Tools (PHP Tools) version 1.0. These tools are a set of small tight cgi binaries written in C. They perform a number of functions including: . Logging accesses to your pages in your own private log files . Real-time viewing of log information . Providing a nice interface to this log information . Displaying last access information right on your pages . Full daily and total access counters . Banning access to users based on their domain . Password protecting pages based on users' domains . Tracking accesses ** based on users' e-mail addresses ** . Tracking referring URL's - HTTP_REFERER support . Performing server-side includes without needing server support for it . Ability to not log accesses from certain domains (ie. your own) . Easily create and display forms . Ability to use form information in following documents Here is what you don't need to use these tools: . You do not need root access - install in your ~/public_html dir . You do not need server-side includes enabled in your server . You do not need access to Perl or Tcl or any other script interpreter . You do not need access to the httpd log files The only requirement for these tools to work is that you have the ability to execute your own cgi programs. Ask your system administrator if you are not sure what this means. The tools also allow you to implement a guestbook or any other form that needs to write information and display it to users later in about 2 minutes. The tools are in the public domain distributed under the GNU Public License. Yes, that means they are free! For a complete demonstration of these tools, point your browser at: http://www.io.org/~rasmus -- Rasmus Lerdorf rasmus@io.org http://www.io.org/~rasmusEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Installing PHP
- InhaltsvorschauPHP is available for many operating systems and platforms. The most common setup, however, is to use PHP as a module for the Apache web server on a Unix machine. This section briefly describes how to install Apache with PHP. If you're interested in running PHP on Windows, see Chapter 15, which explains many of your options for that operating system.To install Apache with PHP, you'll need a Unix machine with an ANSI-compliant C compiler, and around 10 MB of available disk space for source and object files. You'll also need Internet access to fetch the source code for PHP and Apache.Start by downloading the source distributions of PHP and Apache. The latest files are always available from the web sites for the respective tools. Since there are so many options on installation , we are showing here the generic installation instructions for a Linux server as shown on the PHP web site at
http://ca3.php.net/manual/en/install.unix.php. You will have to replace the xxx signifier in the following steps with the version of the software that you choose to install.Although Apache has a Version 2.x you may find that it is more adept at serving PHP with Version 1.3.xx, so generally we will be using the 1.3.xx version throughout this book.-
gunzip apache_xxx.tar.gz -
tar -xvf apache_xxx.tar -
gunzip php-xxx.tar.gz -
tar -xvf php-xxx.tar -
cd apache_xxx -
.
/configure --prefix=/www --enable-module=so
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- A Walk Through PHP
- InhaltsvorschauPHP pages are HTML pages with PHP commands embedded in them. This is in contrast to many other dynamic web-page solutions which are scripts that generate HTML. The web server processes the PHP commands and sends their output (and any HTML from the file) to the browser. Example 1-1 shows a complete PHP page.Example 1-1. Hello_world.php
<html> <head> <title>Look Out World</title> </head> <body> <?php echo 'Hello, world!' ?> </body> </html>Save the contents of Example 1-1 to a file, hello_world.php, and point your browser to it. The results appear in Figure 1-2.
Figure 1-2: Output of hello_world.phpThe PHPechocommand produces output (the string "Hello, world!" in this case), which is inserted into the HTML file. In this example, the PHP code is placed between the<?phpand?>tags. There are other ways to tag your PHP code—see Chapter 2 for a full description.The PHP functionphpinfo( )creates an HTML page full of information on how PHP was installed. You can use it to see whether you have particular extensions installed, or whether the php.ini file has been customized. Example 1-2 is a complete page that displays thephpinfo( )page.Example 1-2. Using phpinfo( )<?php phpinfo( ); ?>
Figure 1-3 shows the first part of the output of Example 1-2.Example 1-3 creates and processes a form. When the user submits the form, the information typed into the name field is sent back to this page. The PHP code tests for a name field and displays a greeting if it finds one.
Figure 1-3: Partial output of phpinfo( )Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 2: Language Basics
- InhaltsvorschauThis chapter provides a whirlwind tour of the core PHP language, covering such basic topics as data types, variables, operators, and flow control statements. PHP is strongly influenced by other programming languages, such as Perl and C, so if you've had experience with those languages, PHP should be easy to pick up. If PHP is one of your first programming languages, don't panic. We start with the basic units of a PHP program and build up your knowledge from there.The lexical structure of a programming language is the set of basic rules that governs how you write programs in that language. It is the lowest-level syntax of the language and specifies such things as what variable names look like, what characters are used for comments, and how program statements are separated from each other.The names of user-defined classes and functions, as well as built-in constructs and keywords such as
echo,while,class, etc., are case-insensitive. Thus, these three lines are equivalent:echo("hello, world"); ECHO("hello, world"); EcHo("hello, world");Variables, on the other hand, are case-sensitive. That is,$name,$NAME, and$NaMEare three different variables.A statement is a collection of PHP code that does something. It can be as simple as a variable assignment or as complicated as a loop with multiple exit points. Here is a small sample of PHP statements, including function calls, assignment, and aniftest:echo "Hello, world"; myfunc(42, "O'Reilly"); $a = 1; $name = "Elphaba"; $b = $a / 25.0; if ($a == $b) { echo "Rhyme? And Reason?"; }PHP uses semicolons to separate simple statements. A compound statement that uses curly braces to mark a block of code, such as a conditional test or loop, does not need a semicolon after a closing brace. Unlike in other languages, in PHP the semicolon before the closing brace is not optional:if ($needed) { echo "We must have it!"; // semicolon required here } // no semicolon required here after the braceEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Lexical Structure
- InhaltsvorschauThe lexical structure of a programming language is the set of basic rules that governs how you write programs in that language. It is the lowest-level syntax of the language and specifies such things as what variable names look like, what characters are used for comments, and how program statements are separated from each other.The names of user-defined classes and functions, as well as built-in constructs and keywords such as
echo,while,class, etc., are case-insensitive. Thus, these three lines are equivalent:echo("hello, world"); ECHO("hello, world"); EcHo("hello, world");Variables, on the other hand, are case-sensitive. That is,$name,$NAME, and$NaMEare three different variables.A statement is a collection of PHP code that does something. It can be as simple as a variable assignment or as complicated as a loop with multiple exit points. Here is a small sample of PHP statements, including function calls, assignment, and aniftest:echo "Hello, world"; myfunc(42, "O'Reilly"); $a = 1; $name = "Elphaba"; $b = $a / 25.0; if ($a == $b) { echo "Rhyme? And Reason?"; }PHP uses semicolons to separate simple statements. A compound statement that uses curly braces to mark a block of code, such as a conditional test or loop, does not need a semicolon after a closing brace. Unlike in other languages, in PHP the semicolon before the closing brace is not optional:if ($needed) { echo "We must have it!"; // semicolon required here } // no semicolon required here after the braceThe semicolon is optional before a closing PHP tag:<?php if ($a == $b) { echo "Rhyme? And Reason?"; } echo "Hello, world" // no semicolon required before closing tag ?>It's good programming practice to include optional semicolons, as they make it easier to add code later.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Data Types
- InhaltsvorschauPHP provides eight types of values, or data types. Four are scalar (single-value) types: integers , floating-point numbers, strings, and Booleans. Two are compound (collection) types: arrays and objects. The remaining two are special types: resource and NULL. Numbers, Booleans, resources, and NULL are discussed in full here, while strings, arrays, and objects are big enough topics that they get their own chapters (Chapters 4, 5, and 6).Integers are whole numbers, such as 1, 12, and 256. The range of acceptable values varies according to the details of your platform but typically extends from -2,147,483,648 to +2,147,483,647. Specifically, the range is equivalent to the range of the long data type of your C compiler. Unfortunately, the C standard doesn't specify what range that long type should have, so on some systems you might see a different integer range.Integer literals can be written in decimal, octal, or hexadecimal. Decimal values are represented by a sequence of digits, without leading zeros. The sequence may begin with a plus (
+)or minus (−)sign. If there is no sign, positive is assumed. Examples of decimal integers include the following:1998 -641 +33Octal numbers consist of a leading 0 and a sequence of digits from 0 to 7. Like decimal numbers, octal numbers can be prefixed with a plus or minus. Here are some example octal values and their equivalent decimal values:0755 // decimal 493 +010 // decimal 8Hexadecimal values begin with 0x, followed by a sequence of digits (0-9) or letters (A-F). The letters can be upper- or lowercase but are usually written in capitals. Like decimal and octal values, you can include a sign in hexadecimal numbers :0xFF // decimal 255 0x10 // decimal 16 -0xDAD1 // decimal -56017If you try to store a variable that is too large to be stored as an integer, or is not a whole number, it will automatically be turned into a floating-point number.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Variables
- InhaltsvorschauVariables in PHP are identifiers prefixed with a dollar sign (
$). For example:$name $Age $_debugging $MAXIMUM_IMPACTA variable may hold a value of any type. There is no compile-time or runtime type checking on variables . You can replace a variable's value with another of a different type:$what = "Fred"; $what = 35; $what = array('Fred', '35', 'Wilma');There is no explicit syntax for declaring variables in PHP. The first time the value of a variable is set, the variable is created. In other words, setting a value to a variable also functions as a declaration. For example, this is a valid complete PHP program:$day = 60 * 60 * 24; echo "There are $day seconds in a day.\n"; There are 86400 seconds in a day.A variable whose value has not been set behaves like theNULLvalue:if ($uninitialized_variable === NULL) { echo "Yes!"; } Yes!You can reference the value of a variable whose name is stored in another variable. For example:$foo = 'bar'; $$foo = 'baz';After the second statement executes, the variable$barhas the value"baz".In PHP, references are how you create variable aliases. To make$blackan alias for the variable$white, use:$black =& $white;The old value of$blackis lost. Instead,$blackis now another name for the value that is stored in$white:$big_long_variable_name = "PHP"; $short =& $big_long_variable_name; $big_long_variable_name .= " rocks!"; print "\$short is $short\n"; print "Long is $big_long_variable_name\n"; $short is PHP rocks! Long is PHP rocks! $short = "Programming $short"; print "\$short is $short\n"; print "Long is $big_long_variable_name\n"; $short is Programming PHP rocks! Long is Programming PHP rocks!After the assignment, the two variables are alternate names for the same value. Unsetting a variable that is aliased does not affect other names for that variable's value, however:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Expressions and Operators
- InhaltsvorschauAn expression is a bit of PHP that can be evaluated to produce a value. The simplest expressions are literal values and variables. A literal value evaluates to itself, while a variable evaluates to the value stored in the variable. More complex expressions can be formed using simple expressions and operators .An operator takes some values (the operands) and does something (for instance, adds them together). Operators are written as punctuation symbols—for instance, the
+and - familiar to us from math. Some operators modify their operands, while most do not.Table 2-3 summarizes the operators in PHP, many of which were borrowed from C and Perl. The column labeled "P" gives the operator's precedence; the operators are listed in precedence order, from highest to lowest. The column labeled "A" gives the operator's associativity, which can be L (left-to-right), R (right-to-left), or N (non-associative).Table 2-3: PHP operators PAOperatorOperation19NnewCreate new object18[Array subscript17R!Logical NOTEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Flow-Control Statements
- InhaltsvorschauPHP supports a number of traditional programming constructs for controlling the flow of execution of a program.Conditional statements, such as
if/elseandswitch, allow a program to execute different pieces of code, or none at all, depending on some condition. Loops, such aswhileandfor, support the repeated execution of particular segments of code.Theifstatement checks the truthfulness of an expression and, if the expression is true, evaluates a statement. Anifstatement looks like:if (expression) statementTo specify an alternative statement to execute when the expression is false, use theelsekeyword:if (expression) statement else statementFor example:if ($user_validated) echo "Welcome!"; else echo "Access Forbidden!";To include more than one statement in anifstatement, use a block—a curly brace-enclosed set of statements:if ($user_validated) { echo 'Welcome!"; $greeted = 1; } else { echo "Access Forbidden!"; exit; }PHP provides another syntax for blocks in tests and loops. Instead of enclosing the block of statements in curly braces, end theifline with a colon (:) and use a specific keyword to end the block (endif, in this case). For example:if ($user_validated) : echo "Welcome!"; $greeted = 1; else : echo "Access Forbidden!"; exit; endif;Other statements described in this chapter also have similar alternate style syntax (and ending keywords); they can be useful if you have large blocks of HTML inside your statements. For example:<?if($user_validated):?> <table> <tr> <td>First Name:</td><td>Sophia</td> </tr> <tr> <td>Last Name:</td><td>Lee</td> </tr> </table> <?else:?> Please log in. <?endif?>Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Including Code
- InhaltsvorschauPHP provides two constructs to load code and HTML from another module:
requireandinclude. They both load a file as the PHP script runs, work in conditionals and loops, and complain if the file being loaded cannot be found. The main difference is that attempting torequirea nonexistent file is a fatal error, while attempting toincludesuch a file produces a warning but does not stop script execution.A common use ofincludeis to separate page-specific content from general site design. Common elements such as headers and footers go in separate HTML files, and each page then looks like:<? include 'header.html'; ?> content <? include 'footer.html'; ?>We useincludebecause it allows PHP to continue to process the page even if there's an error in the site design file(s). Therequireconstruct is less forgiving and is more suited to loading code libraries, where the page cannot be displayed if the libraries do not load. For example:require 'codelib.inc'; mysub( ); // defined in codelib.incA marginally more efficient way to handle headers and footers is to load a single file and then call functions to generate the standardized site elements:<? require 'design.inc'; header( ); ?> content <? footer( ); ?>If PHP cannot parse some part of a file included byincludeorrequire, a warning is printed and execution continues. You can silence the warning by prepending the call with the silence operator (@) — for example,@include.If theallow_url_fopenoption is enabled through PHP's configuration file, php.ini, you can include files from a remote site by providing a URL instead of a simple local path:include 'http://www.example.com/codelib.inc';If the filename begins with "http://" or "ftp://", the file is retrieved from a remote site and then loaded.Files included withincludeandrequirecan be arbitrarily named. Common extensions areEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Embedding PHP in Web Pages
- InhaltsvorschauAlthough it is possible to write and run standalone PHP programs, most PHP code is embedded in HTML or XML files. This is, after all, why it was created in the first place. Processing such documents involves replacing each chunk of PHP source code with the output it produces when executed.Because a single file contains PHP and non-PHP source code, we need a way to identify the regions of PHP code to be executed. PHP provides four different ways to do this.As you'll see, the first, and preferred, method looks like XML. The second method looks like SGML. The third method is based on ASP tags. The fourth method uses the standard HTML
<script>tag; this makes it easy to edit pages with enabled PHP using a regular HTML editor.Because of the advent of the eXtensible Markup Language (XML) and the migration of HTML to an XML language (XHTML), the currently preferred technique for embedding PHP uses XML-compliant tags to denote PHP instructions.Coming up with tags to demark PHP commands in XML was easy, because XML allows the definition of new tags. To use this style, surround your PHP code with<?phpand?>. Everything between these markers is interpreted as PHP, and everything outside the markers is not. Although it is not necessary to include spaces between the markers and the enclosed text, doing so improves readability. For example, to get PHP to print "Hello, world", you can insert the following line in a web page:<?php echo "Hello, world"; ?>The trailing semicolon on the statement is optional, because the end of the block also forces the end of the expression. Embedded in a complete HTML file, this looks like:<!doctype html public "-//w3c//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>This is my first PHP program!</title> </head> <body> <p> Look, ma! It's my first PHP program:<br /> <?php echo "Hello, world"; ?><br /> How cool is that? </p> </body> </html>Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 3: Functions
- InhaltsvorschauA function is a named block of code that performs a specific task, possibly acting upon a set of values given to it, or parameters , and possibly returning a single value. Functions save on compile time—no matter how many times you call them, functions are compiled only once for the page. They also improve reliability by allowing you to fix any bugs in one place, rather than everywhere you perform a task, and they improve readability by isolating code that performs specific tasks.This chapter introduces the syntax of function calls and function definitions and discusses how to manage variables in functions and pass values to functions (including pass-by-value and pass-by-reference). It also covers variable functions and anonymous functions.Functions in a PHP program can be built-in (or, by being in an extension, effectively built-in) or user-defined. Regardless of their source, all functions are evaluated in the same way:
$some_value = function_name( [ parameter, ... ] );The number of parameters a function requires differs from function to function (and, as we'll see later, may even vary for the same function). The parameters supplied to the function may be any valid expression and should be in the specific order expected by the function. A function's documentation will tell you what parameters the function expects and what values you can expect to be returned.Here are some examples of functions:// strlen( ) is a built-in function that returns the length of a string $length = strlen("PHP"); // $length is now 3 // sin( ) and asin( ) are the sine and arcsine math functions $result = sin(asin(1)); // $result is the sine of arcsin(1), or 1.0 // unlink( ) deletes a file $result = unlink("functions.txt"); // false if unsuccessfulIn the first example, we give an argument,"PHP", to the functionstrlen( ), which gives us the number of characters in the string it's given. In this case, it returnsEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Calling a Function
- InhaltsvorschauFunctions in a PHP program can be built-in (or, by being in an extension, effectively built-in) or user-defined. Regardless of their source, all functions are evaluated in the same way:
$some_value = function_name( [ parameter, ... ] );The number of parameters a function requires differs from function to function (and, as we'll see later, may even vary for the same function). The parameters supplied to the function may be any valid expression and should be in the specific order expected by the function. A function's documentation will tell you what parameters the function expects and what values you can expect to be returned.Here are some examples of functions:// strlen( ) is a built-in function that returns the length of a string $length = strlen("PHP"); // $length is now 3 // sin( ) and asin( ) are the sine and arcsine math functions $result = sin(asin(1)); // $result is the sine of arcsin(1), or 1.0 // unlink( ) deletes a file $result = unlink("functions.txt"); // false if unsuccessfulIn the first example, we give an argument,"PHP", to the functionstrlen( ), which gives us the number of characters in the string it's given. In this case, it returns3, which is assigned to the variable$length. This is the simplest and most common way to use a function.The second example passes the result ofasin(1)to thesin( )function. Since the sine and arcsine functions are reflexive, taking the sine of the arcsine of any value will always return that same value. Here we see that a function can be called within another function and the returned value of the inner call is subsequently sent to the outer function before the overall result is returned and stored in the $result variable.In the final example, we give a filename to theunlink( )function, which attempts to delete the file. Like many functions, it returnsfalsewhen it fails. This allows you to use another built-in function,die( ), and the short-circuiting property of the logic operators. Thus, this example might be rewritten as:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Defining a Function
- InhaltsvorschauTo define a function, use the following syntax:
function [&] function_name ( [ parameter [, ... ] ] ) { statement list }The statement list can include HTML. You can declare a PHP function that doesn't contain any PHP code. For instance, thecolumn( )function simply gives a convenient short name to HTML code that may be needed many times throughout the page:<? function column( ) { ?> </td><td> <? } ?>The function name can be any string that starts with a letter or underscore followed by zero or more letters, underscores, and digits. Function names are case-insensitive; that is, you can call thesin( )function assin(1),SIN(1),SiN(1), and so on, because all these names refer to the same function.Typically, functions return some value. To return a value from a function, use thereturnstatement: putreturnexpr inside your function. When areturnstatement is encountered during execution, control reverts to the calling statement, and the evaluated results of expr will be returned as the value of the function. Although it can make for messy code, you can actually include multiplereturnstatements in a function if it makes sense (for example, if you have aswitchstatement to determine which of several values to return).If you define your function with the optional ampersand before the name, the function returns a reference to the returned data rather than a copy of the data.Let's take a look at a simple function. Example 3-1 takes two strings, concatenates them, and then returns the result (in this case, we've created a slightly slower equivalent to the concatenation operator, but bear with us for the sake of example).Example 3-1. String concatenationfunction strcat($left, $right) { $combined_string = $left . $right; return $combined_string; }The function takes two arguments,$leftand$right. Using the concatenation operator, the function creates a combined string in the variableEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Variable Scope
- InhaltsvorschauUp to this point, if you don't use functions, any variable you create can be used anywhere in a page. With functions, this is not always true. Functions keep their own sets of variables that are distinct from those of the page and of other functions.The variables defined in a function, including its parameters, are not accessible outside the function, and, by default, variables defined outside a function are not accessible inside the function. The following example illustrates this:
$a = 3; function foo( ) { $a += 2; } foo( ); echo $a;The variable$ainside the functionfoo( )is a different variable than the variable$aoutside the variable; even thoughfoo( )uses the add-and-assign operator, the value of the outer$aremains3throughout the life of the page. Inside the function,$ahas the value2.As we discussed in Chapter 2, the extent to which a variable can be seen in a program is called the scope of the variable. Variables created within a function are inside the scope of the function (i.e., have function-level scope). Variables created outside of functions and objects have global scope and exist anywhere outside of those functions and objects. A few variables provided by PHP have both function-level and global scope.At first glance, even an experienced programmer may think that in the previous example$awill be5by the time theechostatement is reached, so keep that in mind when choosing names for your variables.If you want a variable in the global scope to be accessible from within a function, you can use theglobalkeyword. Its syntax is:global var1, var2, ...Changing the previous example to include aglobalkeyword, we get:$a = 3; function foo( ) { global $a; $a += 2; } foo( ); echo $a;Instead of creating a new variable called$awith function-level scope, PHP uses the globalEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Function Parameters
- InhaltsvorschauFunctions can expect, by declaring them in the function definition, an arbitrary number of arguments. There are two different ways to pass parameters to a function. The first, and more common, is by value . The other is by reference .In most cases, you pass parameters by value. The argument is any valid expression. That expression is evaluated, and the resulting value is assigned to the appropriate variable in the function. In all of the examples so far, we've been passing arguments by value.Passing by reference allows you to override the normal scoping rules and give a function direct access to a variable. To be passed by reference, the argument must be a variable; you indicate that a particular argument of a function will be passed by reference by preceding the variable name in the parameter list with an ampersand (
&). Example 3-5 revisits ourdoubler( )function with a slight change.Example 3-5. Doubler reduxfunction doubler(&$value) { $value = $value << 1; } $a = 3; doubler($a); echo $a;Because the function's$valueparameter is passed by reference, the actual value of$a, rather than a copy of that value, is modified by the function. Before, we had toreturnthe doubled value, but now we change the caller's variable to be the doubled value.Here's another place where a function contains side effects: since we passed the variable$aintodoubler( )by reference, the value of$ais at the mercy of the function. In this case,doubler( )assigns a new value to it.A parameter that is declared as being passed by reference can only be a variable. Thus, if we included the statement<?= doubler(7); ?>in the previous example, it would issue an error. However, you may assign a default value to parameters passed by reference (in the same manner as you provide default values for parameters passed by value).Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Return Values
- InhaltsvorschauPHP functions can return only a single value with the return keyword:
function return_one( ) { return 42; }To return multiple values, return an array:function return_two ( ) { return array("Fred", 35); }By default, values are copied out of the function. A function declared with an&before its name returns a reference (alias) to its return value:$names = array("Fred", "Barney", "Wilma", "Betty"); function & find_one($n) { global $names; return $names[$n]; } $person =& find_one(1); // Barney $person = "Barnetta"; // changes $names[1]In this code, thefind_one( )function returns an alias for$names[1], instead of a copy of its value. Because we assign by reference,$personis an alias for$names[1], and the second assignment changes the value in$names[1].This technique is sometimes used to return large string or array values efficiently from a function. However, PHP's copy-on-write/shallow-copy mechanism usually means that returning a reference from a function is not necessary. There is no point in returning a reference to some large piece of data unless you know you are likely to change that data. The drawback of returning the reference is that it is slower than returning the value and relying on the shallow-copy mechanism to ensure that a copy of that data is not made unless it is changed.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Variable Functions
- InhaltsvorschauAs with variable variables, you can call a function based on the value of a variable. For example, consider this situation, where a variable is used to determine which of three functions to call:
switch($which) { case 'first': first( ); break; case 'second': second( ); break; case 'third': third( ); break; }In this case, we could use a variable function call to call the appropriate function. To make a variable function call, include the parameters for a function in parentheses after the variable. To rewrite the previous example:$which( ); // if $which is "first," the function first( ) is called, etc...If no function exists for the variable, a runtime error occurs when the code is evaluated. To prevent this, you can use the built-in functionfunction_exists( )to determine whether a function exists for the value of the variable before calling the function:$yes_or_no = function_exists(function_name);For example:if(function_exists($which)) { $which( ); // if $which is "first," the function first( ) is called, etc... }Language constructs such asecho( )andisset( )cannot be called through variable functions:$f = 'echo'; $f('hello, world'); // does not workEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Anonymous Functions
- InhaltsvorschauSome PHP functions use a function you provide them with to do part of their work. For example, the
usort( )function uses a function you create and pass to it as a parameter to determine the sort order of the items in an array.Although you can define a function for such purposes, as shown previously, these functions tend to be localized and temporary. To reflect the transient nature of the callback, create and use an anonymous function (or lambda function).You can create an anonymous function usingcreate_function( ). This function takes two parameters—the first describes the parameters the anonymous function takes in, and the second is the actual code. A randomly generated name for the function is returned:$func_name = create_function(args_string, code_string);Example 3-7 shows an example usingusort( ).Example 3-7. Anonymous functions$lambda = create_function('$a,$b', 'return(strlen($a) - strlen($b));'); $array = array('really long string here, boy', 'this', 'middling length', 'larger'); usort($array, $lambda); print_r($array);The array is sorted byusort( ), using the anonymous function, in order of string length.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 4: Strings
- InhaltsvorschauMost data you encounter as you program will be sequences of characters, or strings. Strings hold people's names, passwords, addresses, credit card numbers, photographs, purchase histories, and more. For that reason, PHP has an extensive selection of functions for working with strings.This chapter shows the many ways to write strings in your programs, including the sometimes-tricky subject of interpolation (placing a variable's value into a string), then covers functions for changing, quoting, and searching strings. By the end of this chapter, you'll be a string-handling expert.There are three ways to write a literal string in your program: using single quotes, double quotes, and the here document (heredoc) format derived from the Unix shell. These methods differ in whether they recognize special escape sequences that let you encode other characters or interpolate variables.The general rule is to use the least powerful quoting mechanism necessary. In practice, this means that you should use single-quoted strings unless you need to include escape sequences or interpolate variables, in which case you should use double-quoted strings. If you want a string that spans many lines, use a heredoc.When you define a string literal using double quotes or a heredoc, the string is subject to variable interpolation . Interpolation is the process of replacing variable names in the string with the values of those variables. There are two ways to interpolate variables into strings—the simple way and the complex way.The simple way is to put the variable name in a double-quoted string or heredoc:
$who = 'Kilroy'; $where = 'here'; echo "$who was $where"; Kilroy was hereThe complex way is to surround the variable being interpolated with curly braces. This method can be used either to disambiguate or to interpolate array lookups. The classic use of curly braces is to separate the variable name from surrounding text:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Quoting String Constants
- InhaltsvorschauThere are three ways to write a literal string in your program: using single quotes, double quotes, and the here document (heredoc) format derived from the Unix shell. These methods differ in whether they recognize special escape sequences that let you encode other characters or interpolate variables.The general rule is to use the least powerful quoting mechanism necessary. In practice, this means that you should use single-quoted strings unless you need to include escape sequences or interpolate variables, in which case you should use double-quoted strings. If you want a string that spans many lines, use a heredoc.When you define a string literal using double quotes or a heredoc, the string is subject to variable interpolation . Interpolation is the process of replacing variable names in the string with the values of those variables. There are two ways to interpolate variables into strings—the simple way and the complex way.The simple way is to put the variable name in a double-quoted string or heredoc:
$who = 'Kilroy'; $where = 'here'; echo "$who was $where"; Kilroy was hereThe complex way is to surround the variable being interpolated with curly braces. This method can be used either to disambiguate or to interpolate array lookups. The classic use of curly braces is to separate the variable name from surrounding text:$n = 12; echo "You are the {$n}th person"; You are the 12th personWithout the curly braces, PHP would try to print the value of the$nthvariable.Unlike in some shell environments, in PHP strings are not repeatedly processed for interpolation. Instead, any interpolations in a double-quoted string are processed, then the result is used as the value of the string:$bar = 'this is not printed'; $foo = '$bar'; // single quotes print("$foo"); $barSingle-quoted strings do not interpolate variables. Thus, the variable name in the following string is not expanded because the string literal in which it occurs is single-quoted :Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Printing Strings
- InhaltsvorschauThere are four ways to send output to the browser. The
echoconstruct lets you print many values at once, whileprint( )prints only one value. Theprintf( )function builds a formatted string by inserting values into a template. Theprint_r( )function is useful for debugging—it prints the contents of arrays, objects, and other things, in a more-or-less human-readable form.To put a string into the HTML of a PHP-generated page, useecho. While it looks—and for the most part behaves—like a function,echois a language construct. This means that you can omit the parentheses, so the following are equivalent:echo "Printy"; echo("Printy"); // also validYou can specify multiple items to print by separating them with commas:echo "First", "second", "third"; FirstsecondthirdIt is a parse error to use parentheses when trying to echo multiple values:// this is a parse error echo("Hello", "world");Becauseechois not a true function, you can't use it as part of a larger expression:// parse error if (echo("test")) { echo("it worked!"); }Such errors are easily remedied, by using theprint( )orprintf( )functions.Theprint( )function sends one value (its argument) to the browser. It returnstrueif the string was successfully displayed andfalseotherwise (e.g., if the user pressed the Stop button on her browser before this part of the page was rendered):if (! print("Hello, world")) { die("you're not listening to me!"); } Hello, worldTheprintf( )function outputs a string built by substituting values into a template (the format string). It is derived from the function of the same name in the standard C library. The first argument toprintf( )is the format string. The remaining arguments are the values to be substituted. A % character in the format string indicates a substitution.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Accessing Individual Characters
- InhaltsvorschauThe
strlen( )function returns the number of characters in a string:$string = 'Hello, world'; $length = strlen($string); // $length is 12You can use the string offset syntax on a string to address individual characters:$string = 'Hello'; for ($i=0; $i < strlen($string); $i++) { printf("The %dth character is %s\n", $i, $string{$i}); } The 0th character is H The 1th character is e The 2th character is l The 3th character is l The 4th character is oEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Cleaning Strings
- InhaltsvorschauOften, the strings we get from files or users need to be cleaned up before we can use them. Two common problems with raw data are the presence of extraneous whitespace, and incorrect capitalization (uppercase versus lowercase).You can remove leading or trailing whitespace with the
trim( ),ltrim( ), andrtrim( )functions:$trimmed = trim(string [, charlist ]); $trimmed = ltrim(string [, charlist ]); $trimmed = rtrim(string [, charlist ]);trim( )returns a copy of string with whitespace removed from the beginning and the end.ltrim( )(the l is for left) does the same, but removes whitespace only from the start of the string.rtrim( )(the r is for right) removes whitespace only from the end of the string. The optional charlist argument is a string that specifies all the characters to strip. The default characters to strip are given in Table 4-3.Table 4-3: Default characters removed by trim( ), ltrim( ), and rtrim( ) CharacterASCII valueMeaning" "0x20Space"\t"0x09Tab"\n"Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Encoding and Escaping
- InhaltsvorschauBecause PHP programs often interact with HTML pages, web addresses (URLs), and databases, there are functions to help you work with those types of data. HTML, web page addresses, and database commands are all strings, but they each require different characters to be escaped in different ways. For instance, a space in a web address must be written as
%20, while a literal less-than sign (<) in an HTML document must be written as<. PHP has a number of built-in functions to convert to and from these encodings.Special characters in HTML are represented by entities such as&and<. There are two PHP functions that turn special characters in a string into their entities, one for removing HTML tags, and one for extracting onlymetatags.Section 4.5.1.1: Entity-quoting all special characters
Thehtmlentities( )function changes all characters with HTML entity equivalents into those equivalents (with the exception of the space character). This includes the less-than sign (<), the greater-than sign (>), the ampersand (&), and accented characters.For example:$string = htmlentities("Einstürzende Neubauten"); echo $string; Einstürzende NeubautenThe entity-escaped version (ü— seen by viewing the source) correctly displays as ü in the rendered web page. As you can see, the space has not been turned into .Thehtmlentities( )function actually takes up to three arguments:$output = htmlentities(input, quote_style, charset);The charset parameter, if given, identifies the character set. The default is "ISO-8859-1." The quote_style parameter controls whether single and double quotes are turned into their entity forms.ENT_COMPAT(the default) converts only double quotes,ENT_QUOTESconverts both types of quotes, andENT_NOQUOTESEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Comparing Strings
- InhaltsvorschauPHP has two operators and six functions for comparing strings to each other.You can compare two strings for equality with the
==and===operators. These operators differ in how they deal with non-string operands. The==operator casts non-string operands to strings, so it reports that3and"3"are equal. The===operator does not cast, and returnsfalseif the data types of the arguments differ.$o1 = 3; $o2 = "3"; if ($o1 == $o2) { echo("== returns true<br>"); } if ($o1 === $o2) { echo("=== returns true<br>"); } == returns trueThe comparison operators (<,<=,>,>=) also work on strings:$him = "Fred"; $her = "Wilma"; if ($him < $her) { print "$him comes before $her in the alphabet.\n"; } Fred comes before Wilma in the alphabetHowever, the comparison operators give unexpected results when comparing strings and numbers:$string = "PHP Rocks"; $number = 5; if ($string < $number) { echo("$string < $number"); } PHP Rocks < 5When one argument to a comparison operator is a number, the other argument is cast to a number. This means that"PHP Rocks"is cast to a number, giving0(since the string does not start with a number). Because 0 is less than 5, PHP prints"PHP Rocks < 5".To explicitly compare two strings as strings, casting numbers to strings if necessary, use thestrcmp( )function:$relationship = strcmp(string_1, string_2);The function returns a number less than 0 if string_1 sorts before string_2, greater than 0 if string_2 sorts before string_1, or 0 if they are the same:$n = strcmp("PHP Rocks", 5); echo($n); 1A variation onstrcmp( )isstrcasecmp( ), which converts strings to lowercase before comparing them. Its arguments and return values are the same as those forstrcmp( ):$n = strcasecmp("Fred", "frED"); // $n is 0Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Manipulating and Searching Strings
- InhaltsvorschauPHP has many functions to work with strings. The most commonly used functions for searching and modifying strings are those that use regular expressions to describe the string in question. The functions described in this section do not use regular expressions—they are faster than regular expressions, but they work only when you're looking for a fixed string (for instance, if you're looking for
"12/11/01"rather than "any numbers separated by slashes").If you know where the data that you are interested in lies in a larger string, you can copy it out with thesubstr( )function:$piece = substr(string, start [, length ]);The start argument is the position in string at which to begin copying, with0meaning the start of the string. The length argument is the number of characters to copy (the default is to copy until the end of the string). For example:$name = "Fred Flintstone"; $fluff = substr($name, 6, 4); // $fluff is "lint" $sound = substr($name, 11); // $sound is "tone"To learn how many times a smaller string occurs in a larger one, usesubstr_count( ):$number = substr_count(big_string, small_string);For example:$sketch = <<< End_of_Sketch Well, there's egg and bacon; egg sausage and bacon; egg and spam; egg bacon and spam; egg bacon sausage and spam; spam bacon sausage and spam; spam egg spam spam bacon and spam; spam sausage spam spam bacon spam tomato and spam; End_of_Sketch; $count = substr_count($sketch, "spam"); print("The word spam occurs $count times."); The word spam occurs 14 times.Thesubstr_replace( )function permits many kinds of string modifications:$string = substr_replace(original, new, start [, length ]);The function replaces the part of original indicated by the start (0means the start of the string) and length values with the stringEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Regular Expressions
- InhaltsvorschauIf you need more complex searching functionality than the previous methods provide, you can use regular expressions . A regular expression is a string that represents a pattern. The regular expression functions compare that pattern to another string and see if any of the string matches the pattern. Some functions tell you whether there was a match, while others make changes to the string.PHP provides support for two different types of regular expressions: POSIX and Perl-compatible . POSIX regular expressions are less powerful, and sometimes slower, than the Perl-compatible functions, but can be easier to read. There are three uses for regular expressions: matching, which can also be used to extract information from a string; substituting new text for matching text; and splitting a string into an array of smaller chunks. PHP has functions for all three behaviors for both Perl and POSIX regular expressions. For instance,
ereg( )does a POSIX match, whilepreg_match( )does a Perl match. Fortunately, there are a number of similarities between basic POSIX and Perl regular expressions, so we'll cover those before delving into the details of each library.Most characters in a regular expression are literal characters, meaning that they match only themselves. For instance, if you search for the regular expression"cow"in the string"Dave was a cowhand,"you get a match because"cow"occurs in that string.Some characters have special meanings in regular expressions. For instance, a caret (^) at the beginning of a regular expression indicates that it must match the beginning of the string (or, more precisely, anchors the regular expression to the beginning of the string):ereg('^cow', 'Dave was a cowhand'); // returns false ereg('^cow', 'cowabunga!'); // returns trueSimilarly, a dollar sign ($) at the end of a regular expression means that it must match the end of the string (i.e., anchors the regular expression to the end of the string):Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - POSIX-Style Regular Expressions
- InhaltsvorschauNow that you understand the basics of regular expressions, we can explore the details. POSIX-style regular expressions use the Unix locale system. The locale system provides functions for sorting and identifying characters that let you intelligently work with text from languages other than English. In particular, what constitutes a "letter" varies from language to language (think of
àandç), and there are character classes in POSIX regular expressions that take this into account.However, POSIX regular expressions are designed for use with only textual data. If your data has a NUL-byte (\x00) in it, the regular expression functions will interpret it as the end of the string, and matching will not take place beyond that point. To do matches against arbitrary binary data, you'll need to use Perl-compatible regular expressions, which are discussed later in this chapter. Also, as we already mentioned, the Perl-style regular expression functions are often faster than the equivalent POSIX-style ones.As shown in Table 4-7, POSIX defines a number of named sets of characters that you can use in character classes . The expansions given in Table 4-7 are for English. The actual letters vary from locale to locale.Table 4-7: POSIX character classes ClassDescriptionExpansion[:alnum:]Alphanumeric characters[0-9a-zA-Z][:alpha:]Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Perl-Compatible Regular Expressions
- InhaltsvorschauPerl has long been considered the benchmark for powerful regular expressions. PHP uses a C library called
pcreto provide almost complete support for Perl's arsenal of regular expression features. Perl regular expressions include the POSIX classes and anchors described earlier. A POSIX-style character class in a Perl regular expression works and understands non-English characters using the Unix locale system. Perl regular expressions act on arbitrary binary data, so you can safely match with patterns or strings that contain the NUL-byte (\x00).Perl-style regular expressions emulate the Perl syntax for patterns, which means that each pattern must be enclosed in a pair of delimiters . Traditionally, the slash (/) character is used; for example,/pattern/. However, any non-alphanumeric character other than the backslash character (\) can be used to delimit a Perl-style pattern. This is useful when matching strings containing slashes, such as filenames. For example, the following are equivalent:preg_match('/\/usr\/local\//', '/usr/local/bin/perl'); // returns true preg_match('#/usr/local/#', '/usr/local/bin/perl'); // returns trueParentheses (( )), curly braces ({}), square brackets ([]), and angle brackets (<>) can be used as pattern delimiters:preg_match('{/usr/local/}', '/usr/local/bin/perl'); // returns trueThe section "Trailing Options" discusses the single-character modifiers you can put after the closing delimiter to modify the behavior of the regular expression engine. A very useful one isx, which makes the regular expression engine strip whitespace and#-marked comments from the regular expression before matching. These two patterns are the same, but one is much easier to read:'/([[:alpha:]]+)\s+\1/' '/( # start capture [[:alpha:]]+ # a word \s+ # whitespace \1 # the same word again ) # end capture /x'Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 5: Arrays
- InhaltsvorschauAs we discussed in Chapter 2, PHP supports both scalar and compound data types. In this chapter, we'll discuss one of the compound types: arrays. An array is a collection of data values organized as an ordered collection of key-value pairs.This chapter talks about creating an array, adding and removing elements from an array, and looping over the contents of an array. Because arrays are very common and useful, there are many built-in functions that work with them in PHP. For example, if you want to send email to more than one email address, you'll store the email addresses in an array and then loop through the array, sending the message to the current email address. Also, if you have a form that permits multiple selections, the items the user selected are returned in an array.There are two kinds of arrays in PHP: indexed and associative . The keys of an indexed array are integers, beginning at 0. Indexed arrays are used when you identify things by their position. Associative arrays have strings as keys and behave more like two-column tables. The first column is the key, which is used to access the value.PHP internally stores all arrays as associative arrays , so the only difference between associative and indexed arrays is what the keys happen to be. Some array features are provided mainly for use with indexed arrays because they assume that you have or want keys that are consecutive integers beginning at 0. In both cases, the keys are unique. In other words, you can't have two elements with the same key, regardless of whether the key is a string or an integer.PHP arrays have an internal order to their elements that is independent of the keys and values, and there are functions that you can use to traverse the arrays based on this internal order. The order is normally that in which values were inserted into the array, but the sorting functions described later let you change the order to one based on keys, values, or anything else you choose.Before we look at creating an array, let's look at the structure of an existing array. You can access specific values from an array using the array variable's name, followed by the element's key (sometimes called theEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Indexed Versus Associative Arrays
- InhaltsvorschauThere are two kinds of arrays in PHP: indexed and associative . The keys of an indexed array are integers, beginning at 0. Indexed arrays are used when you identify things by their position. Associative arrays have strings as keys and behave more like two-column tables. The first column is the key, which is used to access the value.PHP internally stores all arrays as associative arrays , so the only difference between associative and indexed arrays is what the keys happen to be. Some array features are provided mainly for use with indexed arrays because they assume that you have or want keys that are consecutive integers beginning at 0. In both cases, the keys are unique. In other words, you can't have two elements with the same key, regardless of whether the key is a string or an integer.PHP arrays have an internal order to their elements that is independent of the keys and values, and there are functions that you can use to traverse the arrays based on this internal order. The order is normally that in which values were inserted into the array, but the sorting functions described later let you change the order to one based on keys, values, or anything else you choose.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Identifying Elements of an Array
- InhaltsvorschauBefore we look at creating an array, let's look at the structure of an existing array. You can access specific values from an array using the array variable's name, followed by the element's key (sometimes called the index) within square brackets:
$age['Fred'] $shows[2]The key can be either a string or an integer. String values that are equivalent to integer numbers (without leading zeros) are treated as integers. Thus,$array[3]and$array['3']reference the same element, but$array['03']references a different element. Negative numbers are valid keys, and they don't specify positions from the end of the array as they do in Perl.You don't have to quote single-word strings. For instance,$age['Fred']is the same as$age[Fred]. However, it's considered good PHP style to always use quotes, because quoteless keys are indistinguishable from constants. When you use a constant as an unquoted index, PHP uses the value of the constant as the index:define('index',5); echo $array[index]; // retrieves $array[5], not $array['index'];You must use quotes if you're using interpolation to build the array index:$age["Clone$number"]However, don't quote the key if you're interpolating an array lookup:// these are wrong print "Hello, $person['name']"; print "Hello, $person["name"]"; // this is right print "Hello, $person[name]";Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Storing Data in Arrays
- InhaltsvorschauStoring a value in an array will create the array if it didn't already exist, but trying to retrieve a value from an array that hasn't been defined yet won't create the array. For example:
// $addresses not defined before this point echo $addresses[0]; // prints nothing echo $addresses; // prints nothing $addresses[0] = 'spam@cyberpromo.net'; echo $addresses; // prints "Array"Using simple assignment to initialize an array in your program leads to code like this:$addresses[0] = 'spam@cyberpromo.net'; $addresses[1] = 'abuse@example.com'; $addresses[2] = 'root@example.com'; // ...That's an indexed array, with integer indexes beginning at 0. Here's an associative array:$price['Gasket'] = 15.29; $price['Wheel'] = 75.25; $price['Tire'] = 50.00; // ...An easier way to initialize an array is to use thearray( )construct, which builds an array from its arguments. This builds an indexed array, and the index values (starting at 0) are created automatically:$addresses = array('spam@cyberpromo.net', 'abuse@example.com', 'root@example.com');To create an associative array witharray( ), use the=>symbol to separate indexes from values:$price = array('Gasket' => 15.29, 'Wheel' => 75.25, 'Tire' => 50.00);Notice the use of whitespace and alignment. We could have bunched up the code, but it wouldn't have been as easy to read:$price = array('Gasket'=>15.29,'Wheel'=>75.25,'Tire'=>50.00);To construct an empty array, pass no arguments toarray( ):$addresses = array( );You can specify an initial key with=>and then a list of values. The values are inserted into the array starting with that key, with subsequent values having sequential keys:$days = array(1 => 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'); // 2 is Tuesday, 3 is Wednesday, etc.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Multidimensional Arrays
- InhaltsvorschauThe values in an array can themselves be arrays. This lets you easily create multidimensional arrays:
$row_0 = array(1, 2, 3); $row_1 = array(4, 5, 6); $row_2 = array(7, 8, 9); $multi = array($row_0, $row_1, $row_2);You can refer to elements of multidimensional arrays by appending more[]s:$value = $multi[2][0]; // row 2, column 0. $value = 7To interpolate a lookup of a multidimensional array, you must enclose the entire array lookup in curly braces:echo("The value at row 2, column 0 is {$multi[2][0]}\n");Failing to use the curly braces results in output like this:The value at row 2, column 0 is Array[0]Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Extracting Multiple Values
- InhaltsvorschauTo copy all of an array's values into variables, use the
list( )construct:list($variable, ...) = $array;The array's values are copied into the listed variables in the array's internal order. By default that's the order in which they were inserted, but the sort functions described later let you change that. Here's an example:$person = array('Fred', 35, 'Betty'); list($name, $age, $wife) = $person; // $name is 'Fred', $age is 35, $wife is 'Betty'If you have more values in the array than in thelist( ), the extra values are ignored:$person = array('Fred', 35, 'Betty'); list($name, $age) = $person; // $name is 'Fred', $age is 35If you have more values in thelist( )than in the array, the extra values are set toNULL:$values = array('hello', 'world'); list($a, $b, $c) = $values; // $a is 'hello', $b is 'world', $c is NULLTwo or more consecutive commas in thelist( )skip values in the array:$values = range('a', 'e'); // use range to populate the array list($m,,$n,,$o) = $values; // $m is 'a', $n is 'c', $o is 'e'To extract only a subset of the array, use thearray_slice( )function:$subset = array_slice(array, offset, length);Thearray_slice( )function returns a new array consisting of a consecutive series of values from the original array. The offset parameter identifies the initial element to copy (0represents the first element in the array), and the length parameter identifies the number of values to copy. The new array has consecutive numeric keys starting at 0. For example:$people = array('Tom', 'Dick', 'Harriet', 'Brenda', 'Jo'); $middle = array_slice($people, 2, 2); // $middle is array('Harriet', 'Brenda')It is generally only meaningful to usearray_slice( )on indexed arrays (i.e., those with consecutive integer indices starting at 0):Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Converting Between Arrays and Variables
- InhaltsvorschauPHP provides two functions,
extract( )andcompact( ), that convert between arrays and variables. The names of the variables correspond to keys in the array, and the values of the variables become the values in the array. For instance, this array:$person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Betty');can be converted to, or built from, these variables:$name = 'Fred'; $age = 35; $wife = 'Betty';Theextract( )function automatically creates local variables from an array. The indices of the array elements are the variable names:extract($person); // $name, $age, and $wife are now setIf a variable created by the extraction has the same name as an existing one, the extracted variable overwrites the existing variable.You can modifyextract( )'s behavior by passing a second argument. Appendix A describes the possible values for this second argument. The most useful value isEXTR_PREFIX_ALL, which indicates that the third argument toextract( )is a prefix for the variable names that are created. This helps ensure that you create unique variable names when you useextract( ). It is good PHP style to always useEXTR_PREFIX_ALL, as shown here:$shape = "round"; $array = array("cover" => "bird", "shape" => "rectangular"); extract($array, EXTR_PREFIX_ALL, "book"); echo "Cover: $book_cover, Book Shape: $book_shape, Shape: $shape"; Cover: bird, Book Shape: rectangular, Shape: roundThecompact( )function is the complement ofextract( ). Pass it the variable names to compact either as separate parameters or in an array. Thecompact( )function creates an associative array whose keys are the variable names and whose values are the variable's values. Any names in the array that do not correspond to actual variables are skipped. Here's an example ofEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Traversing Arrays
- InhaltsvorschauThe most common task with arrays is to do something with every element—for instance, sending mail to each element of an array of addresses, updating each file in an array of filenames, or adding up each element of an array of prices. There are several ways to traverse arrays in PHP, and the one you choose will depend on your data and the task you're performing.The most common way to loop over elements of an array is to use the
foreachconstruct:$addresses = array('spam@cyberpromo.net', 'abuse@example.com'); foreach ($addresses as $value) { echo "Processing $value\n"; } Processing spam@cyberpromo.net Processing abuse@example.comPHP executes the body of the loop (theechostatement) once for each element of$addressesin turn, with$valueset to the current element. Elements are processed by their internal order.An alternative form offoreachgives you access to the current key:$person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Wilma'); foreach ($person as $key => $value) { echo "Fred's $key is $value\n"; } Fred's name is Fred Fred's age is 35 Fred's wife is WilmaIn this case, the key for each element is placed in$keyand the corresponding value is placed in$value.Theforeachconstruct does not operate on the array itself, but rather on a copy of it. You can insert or delete elements in the body of aforeachloop, safe in the knowledge that the loop won't attempt to process the deleted or inserted elements.Every PHP array keeps track of the current element you're working with; the pointer to the current element is known as the iterator. PHP has functions to set, move, and reset this iterator. The iterator functions are:-
current( ) -
Returns the element currently pointed at by the iterator
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Sorting
- InhaltsvorschauSorting changes the internal order of elements in an array and optionally rewrites the keys to reflect this new order. For example, you might use sorting to arrange a list of scores from biggest to smallest, to alphabetise a list of names or to order a set of users based on how many messages they posted.PHP provides three ways to sort arrays—sorting by keys, sorting by values without changing the keys, or sorting by values and then changing the keys. Each kind of sort can be done in ascending order, descending order, or an order defined by a user-defined function.The functions provided by PHP to sort an array are shown in Table 5-1.
Table 5-1: PHP functions for sorting an array EffectAscendingDescendingUser-defined orderSort array by values, then reassign indices starting with 0sort( )rsort( )usort( )Sort array by valuesasort( )arsort( )Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Acting on Entire Arrays
- InhaltsvorschauPHP has several useful functions for modifying or applying an operation to all elements of an array. You can merge arrays, find the difference, calculate the total, and more; this can all be accomplished by using built-in functions.The
array_sum( )function adds up the values in an indexed or associative array:$sum = array_sum(array);For example:$scores = array(98, 76, 56, 80); $total = array_sum($scores); // $total = 310Thearray_merge( )function intelligently merges two or more arrays:$merged = array_merge(array1, array2 [, array ... ])If a numeric key from an earlier array is repeated, the value from the later array is assigned a new numeric key:$first = array('hello', 'world'); // 0 => 'hello', 1 => 'world' $second = array('exit', 'here'); // 0 => 'exit', 1 => 'here' $merged = array_merge($first, $second); // $merged = array('hello', 'world', 'exit', 'here')If a string key from an earlier array is repeated, the earlier value is replaced by the later value:$first = array('bill' => 'clinton', 'tony' => 'danza'); $second = array('bill' => 'gates', 'adam' => 'west'); $merged = array_merge($first, $second); // $merged = array('bill' => 'gates', 'tony' => 'danza', 'adam' => 'west')Thearray_diff( )function identifies values from one array that are not present in others:$diff = array_diff(array1, array2 [, array ... ]);For example:$a1 = array('bill', 'claire', 'elle', 'simon', 'judy'); $a2 = array('jack', 'claire', 'toni'); $a3 = array('elle', 'simon', 'garfunkel'); // find values of $a1 not in $a2 or $a3 $diff = array_diff($a1, $a2, $a3); // $diff is array('bill', 'judy');Values are compared using===, so1and"1"are considered different. The keys of the first array are preserved, so inEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Using Arrays
- InhaltsvorschauArrays crop up in almost every PHP program. In addition to their obvious use for storing collections of values, they're also used to implement various abstract data types. In this section, we show how to use arrays to implement sets and stacks.Arrays let you implement the basic operations of set theory: union , intersection, and difference. Each set is represented by an array, and various PHP functions implement the set operations. The values in the set are the values in the array—the keys are not used, but they are generally preserved by the operations.The union of two sets is all the elements from both sets, with duplicates removed. The
array_merge( )andarray_unique( )functions let you calculate the union. Here's how to find the union of two arrays:function array_union($a, $b) { $union = array_merge($a, $b); // duplicates may still exist $union = array_unique($union); return $union; } $first = array(1, 'two', 3); $second = array('two', 'three', 'four'); $union = array_union($first, $second); print_r($union); Array ( [0] => 1 [1] => two [2] => 3 [4] => three [5] => four )The intersection of two sets is the set of elements they have in common. PHP's built-inarray_intersect( )function takes any number of arrays as arguments and returns an array of those values that exist in each. If multiple keys have the same value, the first key with that value is preserved.Another common function to perform on a set of arrays is to get the difference; that is, the values in one array that are not present in another array. Thearray_diff( )function calculates this, returning an array with values from the first array that are not present in the second.The following code takes the difference of two arrays:$first = array(1, 'two', 3); $second = array('two', 'three', 'four'); $difference = array_diff($first, $second); print_r($difference); Array ( [0] => 1 [2] => 3 )Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 6: Objects
- InhaltsvorschauObject-oriented programming (OOP) opens the door to cleaner designs, easier maintenance, and greater code reuseability. The proven value of OOP is such that few today would dare to introduce a language that wasn't object-oriented. PHP supports many useful features of OOP, and this chapter shows you how to use them.OOP acknowledges the fundamental connection between data and the code that works on that data, and it lets you design and implement programs around that connection. For example, a bulletin-board system usually keeps track of many users. In a procedural programming language, each user would be a data structure, and there would probably be a set of functions that work with users' data structures (create the new users, get their information, etc.). In an object-oriented programming language, each user would be an object—a data structure with attached code. The data and the code are still there, but they're treated as an inseparable unit.In this hypothetical bulletin-board design, objects can represent not just users, but also messages and threads. A user object has a username and password for that user, and code to identify all the messages by that author. A message object knows which thread it belongs to and has code to post a new message, reply to an existing message, and display messages. A thread object is a collection of message objects, and it has code to display a thread index. This is only one way of dividing the necessary functionality into objects, though. For instance, in an alternate design, the code to post a new message lives in the user object, not the message object. Designing object-oriented systems is a complex topic, and many books have been written on it. The good news is that however you design your system, you can implement it in PHP.The object, as union of code and data, is the modular unit for application development and code reuse. This chapter shows you how to define, create, and use objects in PHP. It covers basic OO concepts as well as advanced topics such as introspection and serialization.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Terminology
- InhaltsvorschauEvery object-oriented language seems to have a different set of terms for the same old concepts. This section describes the terms that PHP uses, but be warned that in other languages these terms may have different meanings.Let's return to the example of the users of a bulletin board. You need to keep track of the same information for each user, and the same functions can be called on each user's data structure. When you design the program, you decide the fields for each user and come up with the functions. In OOP terms, you're designing the user class. A class is a template for building objects .An object is an instance (or occurrence) of a class. In this case, it's an actual user data structure with attached code. Objects and classes are a bit like values and data types. There's only one integer data type, but there are many possible integers. Similarly, your program defines only one user class but can create many different (or identical) users from it.The data associated with an object are called its properties . The functions associated with an object are called its methods . When you define a class, you define the names of its properties and give the code for its methods.Debugging and maintenance of programs is much easier if you use encapsulation . This is the idea that a class provides certain methods (the interface) to the code that uses its objects, so the outside code does not directly access the data structures of those objects. Debugging is thus easier because you know where to look for bugs—the only code that changes an object's data structures is within the class—and maintenance is easier because you can swap out implementations of a class without changing the code that uses the class, as long as you maintain the same interface.Any nontrivial object-oriented design probably involves inheritance . This is a way of defining a new class by saying that it's like an existing class, but with certain new or changed properties and methods. The old class is called theEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Creating an Object
- InhaltsvorschauIt's much easier to create objects and use them than it is to define object classes, so before we discuss how to define classes, let's look at creating objects. To create an object of a given class, use the
newkeyword:$object = new Class;Assuming that aPersonclass has been defined, here's how to create aPersonobject:$rasmus = new Person;Do not quote the class name, or you'll get a compilation error:$rasmus = new 'Person'; // does not workSome classes permit you to pass arguments to thenewcall. The class's documentation should say whether it accepts arguments. If it does, you'll create objects like this:$object = new Person('Fred', 35);The class name does not have to be hardcoded into your program. You can supply the class name through a variable:$class = 'Person'; $object = new $class; // is equivalent to $object = new Person;Specifying a class that doesn't exist causes a runtime error.Variables containing object references are just normal variables—they can be used in the same ways as other variables. Note that variable variables work with objects, as shown here:$account = new Account; $object = 'account' ${$object}->init(50000, 1.10); // same as $account->initEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Accessing Properties and Methods
- InhaltsvorschauOnce you have an object, you can use the
->notation to access methods and properties of the object:$object->propertyname $object->methodname([arg, ... ])For example:printf("Rasmus is %d years old.\n", $rasmus->age); // property access $rasmus->birthday( ); // method call $rasmus->set_age(21); // method call with argumentsMethods act the same as functions (only specifically to the object in question), so they can take arguments and return a value:$clan = $rasmus->family('extended');Within a class's definition, you can specify which methods and properties are publicly accessible and which are accessible only from within the class itself using the public and private access modifiers. You can use these to provide encapsulation.You can use variable variables with property names:$prop = 'age'; echo $rasmus->$prop;A static method is one that is called on a class, not on an object. Such methods cannot access properties. The name of a static method is the class name followed by two colons and the function name. For instance, this calls thep( )static method in the HTML class:HTML::p("Hello, world");When declaring a class, you define which properties and methods are static using the static access property.Once created, objects are passed by reference—that is, instead of copying around the entire object itself (a time- and memory-consuming endeavor), a reference to the object is passed around instead. For example:$f = new Person('Fred', 35); $b = $f; // $b and $f point at same object $b->set_name('Barney'); printf("%s and %s are best friends.\n", $b->get_name( ), $f->get_name( )); // outputs: Barney and Barney are best friends.If you want to create a true copy of an object, you use the clone operator:$f = new Person('Fred', 35); $b = clone $f; // make a copy $b->set_name('Barney'); // change the copy printf("%s and %s are best friends.\n", $b->get_name( ), $f->get_name( )); // outputs: Fred and Barney are best friends.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Declaring a Class
- InhaltsvorschauTo design your program or code library in an object-oriented fashion, you'll need to define your own classes, using the
classkeyword. A class definition includes the class name and the properties and methods of the class. Class names are case-insensitive and must conform to the rules for PHP identifiers. The class namestdClassis reserved. Here's the syntax for a class definition:class classname [ extends baseclass ] { [ var $property [ = value ]; ... ] [ function functionname (args) { // code } ... ] }A method is a function defined inside a class. Although PHP imposes no special restrictions, most methods act only on data within the object in which the method resides. Method names beginning with two underscores (_ _) may be used in the future by PHP (and are currently used for the object serialization methods_ _sleep( )and_ _wakeup( ), described later in this chapter, among others), so it's recommended that you do not begin your method names with this sequence.Within a method, the$thisvariable contains a reference to the object on which the method was called. For instance, if you call$rasmus->birthday( )inside thebirthday( )method,$thisholds the same value as$rasmus. Methods use the$thisvariable to access the properties of the current object and to call other methods on that object.Here's a simple class definition of thePersonclass that shows the$thisvariable in action:class Person { var $name; function get_name ( ) { return $this->name; } function set_name ($new_name) { $this->name = $new_name; } }As you can see, theget_name( )andset_name( )methods use$thisto access and set the$nameproperty of the current object.To declare a method as a static method, use the static keyword. Inside of static methods the variable$thisis not defined. For example:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Introspection
- InhaltsvorschauIntrospection is the ability of a program to examine an object's characteristics, such as its name, parent class (if any), properties, and methods. With introspection , you can write code that operates on any class or object. You don't need to know which methods or properties are defined when you write your code; instead, you can discover that information at runtime, which makes it possible for you to write generic debuggers, serializers, profilers, etc. In this section, we look at the introspective functions provided by PHP.To determine whether a class exists, use the
class_exists( )function, which takes in a string and returns a Boolean value. Alternately, you can use theget_declared_classes( )function, which returns an array of defined classes and checks if the class name is in the returned array:$yes_no = class_exists(classname); $classes = get_declared_classes( );You can get the methods and properties that exist in a class (including those that are inherited from superclasses) using theget_class_methods( )andget_class_vars( )functions. These functions take a class name and return an array:$methods = get_class_methods(classname); $properties = get_class_vars(classname);The class name can be a bare word, a quoted string, or a variable containing the class name:$class = 'Person'; $methods = get_class_methods($class); $methods = get_class_methods(Person); // same $methods = get_class_methods('Person'); // sameThe array returned byget_class_methods( )is a simple list of method names. The associative array returned byget_class_vars( )maps property names to values and also includes inherited properties.One quirk ofget_class_vars( )is that it returns only properties that have default values; there's no way to discover uninitiailized properties.Useget_parent_class( )to find a class's parent class:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Serialization
- InhaltsvorschauSerializing an object means converting it to a bytestream representation that can be stored in a file. This is useful for persistent data; for example, PHP sessions automatically save and restore objects. Serialization in PHP is mostly automatic—it requires little extra work from you, beyond calling the
serialize( )andunserialize( )functions:$encoded = serialize(something); $something = unserialize(encoded);Serialization is most commonly used with PHP's sessions, which handle the serialization for you. All you need to do is tell PHP which variables to keep track of, and they're automatically preserved between visits to pages on your site. However, sessions are not the only use of serialization—if you want to implement your own form of persistent objects, theserialize( )andunserialize( )functions are a natural choice.An object's class must be defined before unserialization can occur. Attempting to unserialize an object whose class is not yet defined puts the object intostdClass, which renders it almost useless. One practical consequence of this is that if you use PHP sessions to automatically serialize and unserialize objects, you must include the file containing the object's class definition in every page on your site. For example, your pages might start like this:<?php include('object_definitions.inc'); // load object definitions session_start( ); // load persistent variables ?> <html>...PHP has two hooks for objects during the serialization and unserialization process:_ _sleep( )and_ _wakeup( ). These methods are used to notify objects that they're being serialized or unserialized. Objects can be serialized if they do not have these methods; however, they won't be notified about the process.The_ _sleep( )method is called on an object just before serialization; it can perform any cleanup necessary to preserve the object's state, such as closing database connections, writing out unsaved persistent data, and so on. It should return an array containing the names of the data members that need be written into the bytestream. If you return an empty array, no data is written.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 7: Web Techniques
- InhaltsvorschauPHP was designed as a web-scripting language and, although it is possible to use it in purely command-line and GUI scripts, the Web accounts for the vast majority of PHP uses. A dynamic web site may have forms, sessions, and sometimes redirection, and this chapter explains how to implement those things in PHP. You'll learn how PHP provides access to form parameters and uploaded files, how to send cookies and redirect the browser, how to use PHP sessions, and more.The Web runs on HTTP, or HyperText Transfer Protocol. This protocol governs how web browsers request files from web servers and how the servers send the files back. To understand the various techniques we'll show you in this chapter, you need to have a basic understanding of HTTP. For a more thorough discussion of HTTP, see the HTTP Pocket Reference by Clinton Wong (O'Reilly).When a web browser requests a web page, it sends an HTTP request message to a web server. The request message always includes some header information, and it sometimes also includes a body. The web server responds with a reply message, which always includes header information and usually contains a body. The first line of an HTTP request looks like this:
GET /index.html HTTP/1.1This line specifies an HTTP command, called a method, followed by the address of a document and the version of the HTTP protocol being used. In this case, the request is using the GET method to ask for the index.html document using HTTP 1.1. After this initial line, the request can contain optional header information that gives the server additional data about the request. For example:User-Agent: Mozilla/5.0 (Windows 2000; U) Opera 6.0 [en] Accept: image/gif, image/jpeg, text/*, */*The User-Agent header provides information about the web browser, while the Accept header specifies the MIME types that the browser accepts. After any headers, the request contains a blank line to indicate the end of the header section. The request can also contain additional data, if that is appropriate for the method being used (e.g., with the POST method, as we'll discuss shortly). If the request doesn't contain any data, it ends with a blank line.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - HTTP Basics
- InhaltsvorschauThe Web runs on HTTP, or HyperText Transfer Protocol. This protocol governs how web browsers request files from web servers and how the servers send the files back. To understand the various techniques we'll show you in this chapter, you need to have a basic understanding of HTTP. For a more thorough discussion of HTTP, see the HTTP Pocket Reference by Clinton Wong (O'Reilly).When a web browser requests a web page, it sends an HTTP request message to a web server. The request message always includes some header information, and it sometimes also includes a body. The web server responds with a reply message, which always includes header information and usually contains a body. The first line of an HTTP request looks like this:
GET /index.html HTTP/1.1This line specifies an HTTP command, called a method, followed by the address of a document and the version of the HTTP protocol being used. In this case, the request is using the GET method to ask for the index.html document using HTTP 1.1. After this initial line, the request can contain optional header information that gives the server additional data about the request. For example:User-Agent: Mozilla/5.0 (Windows 2000; U) Opera 6.0 [en] Accept: image/gif, image/jpeg, text/*, */*The User-Agent header provides information about the web browser, while the Accept header specifies the MIME types that the browser accepts. After any headers, the request contains a blank line to indicate the end of the header section. The request can also contain additional data, if that is appropriate for the method being used (e.g., with the POST method, as we'll discuss shortly). If the request doesn't contain any data, it ends with a blank line.The web server receives the request, processes it, and sends a response. The first line of an HTTP response looks like this:HTTP/1.1 200 OKThis line specifies the protocol version, a status code, and a description of that code. In this case, the status code is "200," meaning that the request was successful (hence the description "OK"). After the status line, the response contains headers that give the client additional information about the response. For example:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Variables
- InhaltsvorschauServer configuration and request information—including form parameters and cookies—are accessible in three different ways from your PHP scripts, as described in this section. Collectively, this information is referred to as EGPCS (environment, GET, POST, cookies, and server).If the
register_globalsoption in php.ini is enabled (it is disabled by default), PHP creates a separate global variable for every form parameter, every piece of request information, and every server configuration value. This functionality is convenient but dangerous, as it lets the browser provide initial values for any of the variables in your program. The (negative) effects this can have on your program's security are explained in Chapter 12.Regardless of the setting ofregister_globals, PHP creates six global arrays that contain the EGPCS information.The global arrays are:-
$_COOKIE -
Contains any cookie values passed as part of the request, where the keys of the array are the names of the cookies
-
$_GET -
Contains any parameters that are part of a GET request, where the keys of the array are the names of the form parameters
-
$_POST -
Contains any parameters that are part of a POST request, where the keys of the array are the names of the form parameters
-
$_FILES -
Contains information about any uploaded files
-
$_SERVER -
Contains useful information about the web server, as described in the next section
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Server Information
- InhaltsvorschauThe
$_SERVERarray contains a lot of useful information from the web server. Much of this information comes from the environment variables required in the CGI specification (http://hoohoo.ncsa.uiuc.edu/cgi/env.html).Here is a complete list of the entries in$_SERVERthat come from CGI:-
SERVER_SOFTWARE -
A string that identifies the server (e.g., "Apache/1.3.33 (Unix) mod_perl/1.26 PHP/5.0.4").
-
SERVER_NAME -
The hostname, DNS alias, or IP address for self-referencing URLs (e.g., "
www.example.com"). -
GATEWAY_INTERFACE -
The version of the CGI standard being followed (e.g., "CGI/1.1").
-
SERVER_PROTOCOL -
The name and revision of the request protocol (e.g., "HTTP/1.1").
-
SERVER_PORT -
The server port number to which the request was sent (e.g., "80").
-
REQUEST_METHOD -
The method the client used to fetch the document (e.g., "GET").
-
PATH_INFO -
Extra path elements given by the client (e.g., "/list/users").
-
PATH_TRANSLATED -
The value of
PATH_INFO, translated by the server into a filename (e.g., "/home/httpd/htdocs/list/users").
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Processing Forms
- InhaltsvorschauIt's easy to process forms with PHP, as the form parameters are available in the
$_GETand$_POSTarrays. There are many tricks and techniques for working with forms, though, which are described in this section.As we already discussed, there are two HTTP methods that a client can use to pass form data to the server: GET and POST. The method that a particular form uses is specified with themethodattribute to theformtag. In theory methods are case-insensitive in the HTML, but in practice some broken browsers require the method name to be in all uppercase.A GET request encodes the form parameters in the URL in what is called a query string:/path/to/chunkify.php?word=despicable&length=3A POST request passes the form parameters in the body of the HTTP request, leaving the URL untouched.The most visible difference between GET and POST is the URL line. Because all of a form's parameters are encoded in the URL with a GET request, users can bookmark GET queries. They cannot do this with POST requests , however.The biggest difference between GET and POST requests, however, is far more subtle. The HTTP specification says that GET requests are idempotent—that is, one GET request for a particular URL, including form parameters, is the same as two or more requests for that URL. Thus, web browsers can cache the response pages for GET requests, because the response page doesn't change regardless of how many times the page is loaded. Because of idempotence , GET requests should be used only for queries such as splitting a word into smaller chunks or multiplying numbers, where the response page is never going to change.POST requests are not idempotent. This means that they cannot be cached, and the server is recontacted every time the page is displayed. You've probably seen your web browser prompt you with "Repost form data?" before displaying or reloading certain pages. This makes POST requests the appropriate choice for queries whose response pages may change over time—for example, displaying the contents of a shopping cart or the current messages in a bulletin board.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Setting Response Headers
- InhaltsvorschauAs we've already discussed, the HTTP response that a server sends back to a client contains headers that identify the type of content in the body of the response, the server that sent the response, how many bytes are in the body, when the response was sent, etc. PHP and Apache normally take care of the headers for you, identifying the document as HTML, calculating the length of the HTML page, and so on. Most web applications never need to set headers themselves. However, if you want to send back something that's not HTML, set the expiration time for a page, redirect the client's browser, or generate a specific HTTP error, you'll need to use the
header( )function.The only catch to setting headers is that you must do so before any of the body is generated. This means that all calls toheader( )(orsetcookie( ), if you're setting cookies) must happen at the very top of your file, even before the<html>tag. For example:<?php header('Content-Type: text/plain'); ?> Date: today From: fred To: barney Subject: hands off! My lunchbox is mine and mine alone. Get your own, you filthy scrounger!Attempting to set headers after the document has started results in this warning:Warning: Cannot add header information - headers already sentThe Content-Type header identifies the type of document being returned. Ordinarily this is"text/html", indicating an HTML document, but there are other useful document types. For example,"text/plain"forces the browser to treat the page as plain text. This type is like an automatic "view source," and it is useful when debugging.In Chapter 9 and Chapter 10, we'll make heavy use of the Content-Type header as we generate documents that are really graphic images and Adobe PDF files.To send the browser to a new URL, known as a redirection, you set the Location header:<?php header('Location: http://www.example.com/elsewhere.html'); exit( ); ?>Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Maintaining State
- InhaltsvorschauHTTP is a stateless protocol, which means that once a web server completes a client's request for a web page, the connection between the two goes away. In other words, there is no way for a server to recognize that a sequence of requests all originate from the same client.State is useful, though. You can't build a shopping-cart application, for example, if you can't keep track of a sequence of requests from a single user. You need to know when a user puts an item in his cart, when he adds items, when he removes them, and what's in the cart when he decides to check out.To get around the Web's lack of state, programmers have come up with many tricks to keep track of state information between requests (also known as session tracking). One such technique is to use hidden form fields to pass around information. PHP treats hidden form fields just like normal form fields, so the values are available in the
$_GETand$_POSTarrays. Using hidden form fields, you can pass around the entire contents of a shopping cart. However, a more common technique is to assign each user a unique identifier and pass the ID around using a single hidden form field. While hidden form fields work in all browsers, they work only for a sequence of dynamically generated forms, so they aren't as generally useful as some other techniques.Another technique is URL rewriting, where every local URL on which the user might click is dynamically modified to include extra information. This extra information is often specified as a parameter in the URL. For example, if you assign every user a unique ID, you might include that ID in all URLs, as follows:http://www.example.com/catalog.php?userid=123If you make sure to dynamically modify all local links to include a user ID, you can now keep track of individual users in your application. URL rewriting works for all dynamically generated documents, not just forms, but actually performing the rewriting can be tedious.A third technique for maintaining state is to use cookies . AEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - SSL
- InhaltsvorschauThe Secure Sockets Layer (SSL) provides a secure channel over which regular HTTP requests and responses can flow. PHP doesn't specifically concern itself with SSL, so you cannot control the encryption in any way from PHP. An https:// URL indicates a secure connection for that document, unlike an http:// URL.The
HTTPSentry in the$_SERVERarray is set to'on'if the PHP page was generated in response to a request over an SSL connection. To prevent a page from being generated over a nonencrypted connection, simply use:if ($_SERVER['HTTPS'] !== 'on') { die("Must be a secure connection."); }A common mistake is to send a form over a secure connection (e.g.,https://www.example.com/form.html), but have theactionof theformsubmit to an http:// URL. Any form parameters entered by the user are sent over an insecure connection—a trivial packet sniffer can reveal them.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 8: Databases
- InhaltsvorschauPHP has support for over 20 databases, including the most popular commercial and open source varieties. Relational database systems such as MySQL, PostgreSQL, and Oracle are the backbone of most modern dynamic web sites. In these are stored shopping-cart information, purchase histories, product reviews, user information, credit-card numbers, and sometimes even web pages themselves.This chapter covers how to access databases from PHP. We focus on the PEAR DB system, which lets you use the same functions to access any database, rather than on the myriad database-specific extensions. In this chapter, you'll learn how to fetch data from the database, how to store data in the database, and how to handle errors. We finish with a sample application that shows how to put various database techniques into action.This book cannot go into all the details of creating web database applications with PHP. For a more in-depth look at the PHP/MySQL combination, see Web Database Applications with PHP and MySQL by Hugh Williams and David Lane (O'Reilly).There are two ways to access databases from PHP. One is to use a database-specific extension; the other is to use the database-independent PEAR DB library. There are advantages and disadvantages to each approach.If you use a database-specific extension, your code is intimately tied to the database you're using. The MySQL extension's function names, parameters, error handling, and so on are completely different from those of the other database extensions. If you want to move your database from MySQL to PostgreSQL, it will involve significant changes to your code. The PEAR DB, on the other hand, hides the database-specific functions from you; moving between database systems can be as simple as changing one line of your program.The portability of an abstraction layer like PEAR's DB library comes at a price however. Features that are specific to a particular database (for example, finding the value of an automatically assigned unique row identifier) are unavailable. Code that uses the PEAR DB is also typically a little slower than code that uses a database-specific extension.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Using PHP to Access a Database
- InhaltsvorschauThere are two ways to access databases from PHP. One is to use a database-specific extension; the other is to use the database-independent PEAR DB library. There are advantages and disadvantages to each approach.If you use a database-specific extension, your code is intimately tied to the database you're using. The MySQL extension's function names, parameters, error handling, and so on are completely different from those of the other database extensions. If you want to move your database from MySQL to PostgreSQL, it will involve significant changes to your code. The PEAR DB, on the other hand, hides the database-specific functions from you; moving between database systems can be as simple as changing one line of your program.The portability of an abstraction layer like PEAR's DB library comes at a price however. Features that are specific to a particular database (for example, finding the value of an automatically assigned unique row identifier) are unavailable. Code that uses the PEAR DB is also typically a little slower than code that uses a database-specific extension.Keep in mind that an abstraction layer like PEAR DB does absolutely nothing when it comes to making sure your actual SQL queries are portable. If your application uses any sort of nongeneric SQL, you'll have to do significant work to convert your queries from one database to another. For large applications, you should consider writing a functional abstraction layer; that is, for each database your application needs to support, write a set of functions that perform various database actions, such as
get_user_record( ),insert_user_record( ), and whatever else you need, then have a configuration option that sets the type of database to which your application is connected. This approach lets you use all the intricacies of each database you choose to support without the performance penalty and limitations of an abstraction layer. This would, however, take quite some time to build from scratch.For simple applications, we prefer the PEAR DB to the database-specific extensions, not just for portability but also for ease of use. The speed and feature costs are rarely significant enough to force us into using the database-specific extensions. For the most part, the rest of this chapter gives sample code using the PEAR DB abstraction objects.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Relational Databases and SQL
- InhaltsvorschauA Relational Database Management System (RDBMS) is a server that manages data for you. The data is structured into tables, where each table has a number of columns, each of which has a name and a type. For example, to keep track of science fiction books, we might have a "books" table that records the title (a string), year of release (a number), and the author.Tables are grouped together into databases, so a science fiction book database might have tables for time periods, authors, and villains. An RDBMS usually has its own user system, which controls access rights for databases (e.g., "user Fred can update database authors").PHP communicates with relational databases such as MySQL and Oracle using the Structured Query Language (SQL). You can use SQL to create, modify, and query relational databases.The syntax for SQL is divided into two parts. The first, Data Manipulation Language, or DML, is used to retrieve and modify data in an existing database. DML is remarkably compact, consisting of only four verbs:
SELECT,INSERT,UPDATE, andDELETE. The set of SQL commands used to create and modify the database structures that hold the data is known as Data Definition Language, or DDL. The syntax for DDL is not as standardized as that for DML, but as PHP just sends any SQL commands you give it to the database, you can use any SQL commands your database supports.The SQL Command file for creating this sample library database is available in a file called library.sql.Assuming you have a table calledbooks, this SQL statement would insert a new row (check web site companion for source files):INSERT INTO books VALUES (4, 'I, Robot', '0-553-29438-5', 1950)
This SQL statement inserts a new row but specifies the columns for which there are values:INSERT INTO books (authorid, title, ISBN, pub_year) VALUES (4, 'I, Robot, '0-553-29438-5', 1950)
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - PEAR DB Basics
- InhaltsvorschauExample 8-1 is a program to build an HTML table of information about science fiction books. It demonstrates how to use the PEAR DB library (which comes with PHP) to connect to a database, issue queries, check for errors, and transform the results of queries into HTML. Be sure to verify how to turn on PEAR with your setup of PHP, as the Unix/Linux flavor is slightly different to that of Windows. Go to
http://www.pear.php.net/manual/en/installation.getting.phpfor a starting point on installation. The library is object-oriented, with a mixture of class methods (DB::connect( ),DB::iserror( )) and object methods ($db->query( ),$q->fetchInto( )).Example 8-1. Display book information<html><head><title>Library Books</title></head> <body> <table border=1> <tr><th>Book</th><th>Year Published</th><th>Author</th></tr> <?php // connect require_once('DB.php'); $db = DB::connect("mysql://librarian:passw0rd@localhost/library"); if (DB::iserror($db)) { die($db->getMessage( )); } // issue the query $sql = "SELECT books.title,books.pub_year,authors.name FROM books, authors WHERE books.authorid=authors.authorid ORDER BY books.pub_year ASC"; $q = $db->query($sql); if (DB::iserror($q)) { die($q->getMessage( )); } // generate the table while ($q->fetchInto($row)) { ?> <tr><td><?= $row[0] ?></td> <td><?= $row[1] ?></td> <td><?= $row[2] ?></td> </tr> <?php } ?>The output of Example 8-1 is shown in Figure 8-1.
Figure 8-1: The Library pageA data source name (DSN ) is a string that specifies where the database is located, what kind of database it is, the username and password to use when connecting to the database, and more. The components of a DSN in PEAR are assembled into a URL-like string:type(dbsyntax)Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Advanced Database Techniques
- InhaltsvorschauPEAR DB goes beyond the database primitives shown earlier; it provides several shortcut functions for fetching result rows, as well as a unique row ID system and separate prepare/execute steps that can improve the performance of repeated queries.Just as
printf( )builds a string by inserting values into a template, the PEAR DB can build a query by inserting values into a template. Pass thequery( )function SQL with?in place of specific values, and add a second parameter consisting of the array of values to insert into the SQL:$result = $db->query(SQL, values);
For example, this code inserts three entries into thebookstable:$movies = array(array('Foundation', 1951), array('Second Foundation', 1953), array('Foundation and Empire', 1952)); foreach ($books as $book) { $db->query('INSERT INTO books (title,pub_year) VALUES (?,?)', $book); }There are three characters that you can use as placeholder values in an SQL query:-
? -
A string or number, which will be quoted if necessary (recommended)
-
| -
A string or number, which will never be quoted
-
& -
A filename, the contents of which will be included in the statement (e.g., for storing an image file in a BLOB field)
When issuing the same query repeatedly, it can be more efficient to compile the query once and then execute it multiple times using theprepare( ),execute( ), andexecuteMultiple( )methods.The first step is to callprepare( )Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Sample Application
- InhaltsvorschauBecause web database applications are such a mainstay of web development, we've decided to show you a complete sample application in this chapter. This section develops a self-maintaining business listing service. Companies add their own records to the database and pick the category or categories by which they want to be indexed.Two HTML forms are needed to populate the database tables. One form provides the site administrator with the means to add category IDs, titles, and descriptions. The second form, used by the self-registering businesses, collects the business contact information and permits the registrant to associate the listing with one or more categories. A separate page displays the listings by category on the web page.There are three tables:
businessesto collect the address data for each business,categoriesto name and describe each category, and an associative table calledbiz_categoriesto relate entries in the other two tables to each other. These tables and their relationships are shown in Figure 8-3.
Figure 8-3: Database design for business listing serviceExample 8-2 contains a dump of the table schema in MySQL format. Depending on your database's features, the schema may have to be altered slightly.Example 8-2. Database schema# -------------------------------------------------------- # # Table structure for table 'biz_categories' # CREATE TABLE biz_categories ( business_id int(11) NOT NULL, category_id char(10) NOT NULL, PRIMARY KEY (business_id, category_id), KEY business_id (business_id, category_id) ); # -------------------------------------------------------- # # Table structure for table 'businesses' # CREATE TABLE businesses ( business_id int(11) NOT NULL auto_increment, name varchar(255) NOT NULL, address varchar(255) NOT NULL, city varchar(128) NOT NULL, telephone varchar(64) NOT NULL, url varchar(255), PRIMARY KEY (business_id), UNIQUE business_id (business_id), KEY business_id_2 (business_id) ); # -------------------------------------------------------- # # Table structure for table 'categories' # CREATE TABLE categories ( category_id varchar(10) NOT NULL, title varchar(128) NOT NULL, description varchar(255) NOT NULL, PRIMARY KEY (category_id), UNIQUE category_id (category_id), KEY category_id_2 (category_id) );
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 9: Graphics
- InhaltsvorschauThe Web is more than just text. Images appear in the form of logos, buttons, photographs, charts, advertisements, and icons. Many of these images are static, built with tools such as PhotoShop and never change. But many are dynamically created—from advertisements for Amazon's referral program that include your name to Yahoo! Finance's graphs of stock performance.PHP supports graphics creation with the GD and Imlib2 extensions. In this chapter we'll show you how to generate images dynamically with PHP, using the GD extension.A common misconception is that there is a mixture of text and graphics flowing across a single HTTP request. After all, when you view a page you see a single page containing such a mixture. It is important to understand that a standard web page containing text and graphics is created through a series of HTTP requests from the web browser, each answered by a response from the web server. Each response can contain one and only one type of data, and each image requires a separate HTTP request and web server response. Thus, if you see a page that contains some text and two images, you know that it has taken three HTTP requests and corresponding responses to construct this page.Take this HTML page, for example:
<html> <head> <title>Example Page</title> </head> <body> This page contains two images. <img src="image1.jpg" alt="Image 1"> <img src="image2.jpg" alt="Image 2"> </body> </html>The series of requests sent by the web browser for this page looks something like this:GET /page.html HTTP/1.0 GET /image1.jpg HTTP/1.0 GET /image2.jpg HTTP/1.0
The web server sends back a response to each of these requests. The Content-Type headers in these responses look like this:Content-Type: text/html Content-Type: image/jpeg Content-Type: image/jpeg
To embed a PHP-generated image in an HTML page, pretend that the PHP script that generates the image is actually the image. Thus, if we haveEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Embedding an Image in a Page
- InhaltsvorschauA common misconception is that there is a mixture of text and graphics flowing across a single HTTP request. After all, when you view a page you see a single page containing such a mixture. It is important to understand that a standard web page containing text and graphics is created through a series of HTTP requests from the web browser, each answered by a response from the web server. Each response can contain one and only one type of data, and each image requires a separate HTTP request and web server response. Thus, if you see a page that contains some text and two images, you know that it has taken three HTTP requests and corresponding responses to construct this page.Take this HTML page, for example:
<html> <head> <title>Example Page</title> </head> <body> This page contains two images. <img src="image1.jpg" alt="Image 1"> <img src="image2.jpg" alt="Image 2"> </body> </html>The series of requests sent by the web browser for this page looks something like this:GET /page.html HTTP/1.0 GET /image1.jpg HTTP/1.0 GET /image2.jpg HTTP/1.0
The web server sends back a response to each of these requests. The Content-Type headers in these responses look like this:Content-Type: text/html Content-Type: image/jpeg Content-Type: image/jpeg
To embed a PHP-generated image in an HTML page, pretend that the PHP script that generates the image is actually the image. Thus, if we have image1.php and image2.php scripts that create images, we can modify the previous HTML to look like this (the image names are PHP extensions now):<html> <head> <title>Example Page</title> </head> <body> This page contains two images. <img src="image1.php" alt="Image 1"> <img src="image2.php" alt="Image 2"> </body> </html>Instead of referring to real images on your web server, theimgtags now refer to the PHP scripts that generate the images.Furthermore, you can pass variables to these scripts, so instead of having separate scripts to generate the two images, you could write yourEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - The GD Extension
- InhaltsvorschauBefore you can start generating images with PHP, you need to check that you actually have image-generation capabilities in your PHP installation. In this chapter we'll discuss using the GD extension, which allows PHP to use the open source GD graphics library available from
http://www.boutell.com/gd/. Starting with PHP 4.3, a version of GD (equivalent to GD 2.0 or higher) is bundled into PHP by default.Load the familiarphpinfo( )page and look for a section entitled "GD." You should see something similar to the following:gd GD Support enabled GD Version 2.0 or higher FreeType Support enabled FreeType Linkage with freetype JPG Support enabled PNG Support enabled WBMP Support enabled
Pay close attention to the image types listed. These are the types of images you will be able to generate.There have been three major revisions of GD and its API. Versions of GD before 1.6 support only the GIF format. Versions 1.6 and later support JPEG, PNG, and WBMP, but do not support GIF (the GIF file format uses patented algorithms that require royalties). Version 2.x of GD added several new drawing primitives.All GD 1.x versions are limited to 8-bit color. That is, the images you generate or manipulate with GD 1.x can contain only 256 different colors. For simple charts or graphs this is more than sufficient, but if you are dealing with photos or other images with more than 256 colors you will find the results less than satisfactory. Upgrade to GD 2.x to get true-color support, or use the Imlib2 library and corresponding PHP extension instead. The API for the Imlib2 extension is somewhat different from the GD extension API and is not covered in this chapter.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Basic Graphics Concepts
- InhaltsvorschauAn image is a rectangle of pixels of various colors. Colors are identified by their position in the palette , an array of colors. Each entry in the palette has three separate color values—one for red, one for green, and one for blue. Each value ranges from 0 (this color not present) to 255 (this color at full intensity).Image files are rarely a straightforward dump of the pixels and the palette. Instead, various file formats (GIF, JPEG, PNG, etc.) have been created that attempt to compress the data somewhat to make smaller files.Different file formats handle image transparency , which controls whether and how the background shows through the image, in different ways. Some support an alpha channel, an extra value for every pixel reflecting the transparency at that point. Others simply designate one entry in the palette as indicating transparency.Antialiasing is where pixels at the edge of a shape are moved or recolored to make a gradual transition between the shape and its background. This prevents the rough and jagged edges that can make for unappealing images. Some functions that draw on an image implement antialiasing .With 256 possible values for each of red, green, and blue, there are 16,777,216 possible colors for each pixel. Some file formats limit the number of colors you can have in a palette (e.g., GIF supports no more than 256 colors); others let you have as many colors as you need. The latter are known as true color formats, because 24-bit color (8 bits for each of red, green, and blue) gives more hues than the human eye can distinguish.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Creating and Drawing Images
- InhaltsvorschauFor now, let's start with the simplest possible GD example. Example 9-1 is a script that generates a black filled square. The code works with any version of GD that supports the PNG image format.Example 9-1. A black square on a white background (black.php)
<?php $im = ImageCreate(200,200); $white = ImageColorAllocate($im,0xFF,0xFF,0xFF); $black = ImageColorAllocate($im,0x00,0x00,0x00); ImageFilledRectangle($im,50,50,150,150,$black); header('Content-Type: image/png'); ImagePNG($im); ?>Example 9-1 illustrates the basic steps in generating any image: creating the image, allocating colors, drawing the image, and then saving or sending the image. Figure 9-1 shows the output of Example 9-1.
Figure 9-1: A black square on a white backgroundTo see the result, simply point your browser at the black.php PHP page. To embed this image in a web page, use:<img src="black.php">
Most dynamic image-generation programs follow the same basic steps outlined in Example 9-1.You can create a 256-color image with theImageCreate( )function , which returns an image handle:$image = ImageCreate(width, height);
All colors used in an image must be allocated with theImageColorAllocate( )function . The first color allocated becomes the background color for the image.$color = ImageColorAllocate(image, red, green, blue);
The arguments are the numeric RGB (red, green, blue) components of the color. In Example 9-1, we wrote the color values in hexadecimal, to bring the function call closer to the HTML color representation"#FFFFFF"and"#000000".There are many drawing primitives in GD. Example 9-1 usesImageFilledRectangle( ), in which you specify the dimensions of the rectangle by passing the coordinates of the top-left and bottom-right corners:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Images with Text
- InhaltsvorschauOften it is necessary to add text to images. GD has built-in fonts for this purpose. Example 9-5 adds some text to our black square image.Example 9-5. Adding text to an image
<?php $im = ImageCreate(200,200); $white = ImageColorAllocate($im,0xFF,0xFF,0xFF); $black = ImageColorAllocate($im,0x00,0x00,0x00); ImageFilledRectangle($im,50,50,150,150,$black); ImageString($im,5,50,160,"A Black Box",$black); Header('Content-Type: image/png'); ImagePNG($im); ?>Figure 9-3 shows the output of Example 9-5.
Figure 9-3: The black box image with added textTheImageString( )function adds text to an image. Specify the top-left point of the text, as well as the color and the font to use:ImageString(image, font, x, y, text, color);
Fonts in GD are identified by numbers. The five built-in fonts are shown in Figure 9-4.
Figure 9-4: Native GD fontsThe code used to show you these fonts follows:<?php $im = ImageCreate(200,200); $black = ImageColorAllocate($im,0x00,0x00,0x00); ImageString($im,1,10,10,"Font 1: ABCDEfghij",$black); ImageString($im,2,10,30,"Font 2: ABCDEfghij",$black); ImageString($im,3,10,50,"Font 3: ABCDEfghij",$black); ImageString($im,4,10,70,"Font 4: ABCDEfghij",$black); ImageString($im,5,10,90,"Font 5: ABCDEfghij",$black); Header('Content-Type: image/png'); ImagePNG($im); ?>You can create your own fonts and load them into GD using theImageLoadFont( )function. However, these fonts are binary and architecture-dependent. Using TrueType fonts with the TrueType functions in GD provides much more flexibility.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Dynamically Generated Buttons
- InhaltsvorschauA popular use for dynamically generated images is to create images for buttons on the fly (this was introduced to you in Chapter 1 as well). Normally, a blank button background image is used and text is overlaid on top of it, as shown in Example 9-8.Example 9-8. Creating a dynamic button
<?php $font = 'times'; if (!$size) $size = 12; $im = ImageCreateFromPNG('button.png'); // calculate position of text $tsize = ImageTTFBBox($size,0,$font,$text); $dx = abs($tsize[2]-$tsize[0]); $dy = abs($tsize[5]-$tsize[3]); $x = ( ImageSx($im) - $dx ) / 2; $y = ( ImageSy($im) - $dy ) / 2 + $dy; // draw text $black = ImageColorAllocate($im,0,0,0); ImageTTFText($im, $size, 0, $x, $y, $black, $font, $text); header('Content-Type: image/png'); ImagePNG($im); ?>In this case, the blank button (button.png) looks as shown in Figure 9-7.
Figure 9-7: Blank ButtonThe script in Example 9-8 can be called from a page like this:<img src="button.php?text=PHP+Button">
This HTML generates the button shown in Figure 9-8.
Figure 9-8: Button with generated text labelThe + character in the URL is the encoded form of a space. Spaces are illegal in URLs and must be encoded. Use PHP'surlencode( )function to encode your button strings. For example:<img src="button.php?text=<?php echo urlencode('PHP Button')?>">It is somewhat slower to generate an image than to send a static image. For buttons that will always look the same when called with the same text argument, a simple cache mechanism can be implemented.Example 9-9 generates the button only when no cache file for that button is found. The$pathvariable holds a directory, writable by the web server user, where buttons can be cached. TheEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Scaling Images
- InhaltsvorschauThere are two ways to change the size of an image. The
ImageCopyResized( )function is available in all versions of GD, but its resizing algorithm is crude and may lead to jagged edges in your new images. TheImageCopyResampled( )function is new in GD 2.x and features pixel interpolation to give smooth edges and clarity to resized images (it is, however, slower thanImageCopyResized( )). Both functions take the same arguments:ImageCopyResized(dest, src, dx, dy, sx, sy, dw, dh, sw, sh); ImageCopyResampled(dest, src, dx, dy, sx, sy, dw, dh, sw, sh);
The dest and src parameters are image handles. The point(dx,dy)is the point in the destination image where the region will be copied. The point(sx,sy)is the upper-left corner of the source image. The sw, sh, dw, and dh parameters give the width and height of the copy regions in the source and destination.Example 9-11 takes the php.jpg image shown in Figure 9-9 and smoothly scales it down to one-quarter of its size, yielding the image in Figure 9-10.Example 9-11. Resizing with ImageCopyResampled( )<?php $src = ImageCreateFromJPEG('php.jpg'); $width = ImageSx($src); $height = ImageSy($src); $x = $width/2; $y = $height/2; $dst = ImageCreateTrueColor($x,$y); ImageCopyResampled($dst,$src,0,0,0,0,$x,$y,$width,$height); header('Content-Type: image/png'); ImagePNG($dst); ?>
Figure 9-9: Original php.jpg imageThe output of Example 9-11 is shown in Figure 9-10.
Figure 9-10: Resulting 1/4-sized imageDividing the height and the width by 4 instead of 2 produces the output shown in Figure 9-11.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Color Handling
- InhaltsvorschauColor support improved markedly between GD 1.x and GD 2.x. In GD 1.x there was no notion of the alpha channel, color handling was rather simple, and the library supported only 8-bit palette images (256 colors). When creating GD 1.x 8-bit palette images, you use the
ImageCreate( )function, and the first color you allocate using theImageColorAllocate( )function becomes the background color.In GD 2.x there is support for true color images complete with an alpha channel. GD 2.x has a 7-bit (0-127) alpha channel.To create a true color image, use theImageCreateTrueColor( )function:$image = ImageCreateTrueColor(width, height);
UseImageColorResolveAlpha( )to create a color index that includes transparency:$color = ImageColorResolveAlpha(image, red, green, blue, alpha);
The alpha value is between 0 (opaque) and 127 (transparent).While most people are used to an 8-bit (0-255) alpha channel, it is actually quite handy that GD's is 7-bit (0-127). Each pixel is represented by a 32-bit signed integer, with the four 8-bit bytes arranged like this:High Byte Low Byte {Alpha Channel} {Red} {Green} {Blue}For a signed integer, the leftmost bit, or the highest bit, is used to indicate whether the value is negative, thus leaving only 31 bits of actual information. PHP's default integer value is a signed long into which we can store a single GD palette entry. Whether that integer is positive or negative tells us whether antialiasing is enabled for that palette entry.Unlike with palette images, with GD 2.x true color images the first color you allocate does not automatically become your background color. CallImageFilledRectangle( )to fill the image with any background color you want.Example 9-12 creates a true color image and draws a semitransparent orange ellipse on a white background.Example 9-12. A simple orange ellipse on a white backgroundEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 10: PDF
- InhaltsvorschauAdobe's Portable Document Format (PDF) provides a popular way to get a consistent look, both on screen and when printed, for documents . This chapter shows how to dynamically create PDF files with text, graphics, links, and more.Dynamic construction of PDF files opens the door to many applications. You can create almost any kind of business document, including form letters, invoices, and receipts. Most paperwork that involves filling out a paper form can be automated by overlaying text onto a scan of the paper form and saving the result as a PDF file.PHP has several libraries for generating PDF documents. This chapter shows how to use the popular fpdf library. The FPDF library is a set of PHP code you include in your scripts with the require function, so it doesn't require any server-side configuration or support, meaning you can use it even without support from your host.The basic concepts of the structure and features of a PDF file should be common to all the pdf libraries, however. This library (FPDF) is available at
http://www.fpdf.org.A PDF document is made up of a number of pages. Each page contains text and/or images. This section shows you how to make a document, create pages in that document, put text onto the pages, and send the pages back to the browser when you're done.The examples in this chapter assume that you have at least the Adobe PDF document viewer installed as an add-on to your web browser. These examples will not work otherwise. You can get the add-on from the Adobe web page athttp://www.adobe.com.Let's start with a simple PDF document. Example 10-1 simply places "Hello Out There!" on a page and then displays the resulting PDF document.Example 10-1. Hello out there in PDF<?php require("../fpdf/fpdf.php"); // path to fpdf.php $pdf = new FPDF( ); $pdf->AddPage( ); $pdf->SetFont('Arial','B',16); $pdf->Cell(40,10,'Hello Out There!'); $pdf->Output( ); ?>Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - PDF Extensions
- InhaltsvorschauPHP has several libraries for generating PDF documents. This chapter shows how to use the popular fpdf library. The FPDF library is a set of PHP code you include in your scripts with the require function, so it doesn't require any server-side configuration or support, meaning you can use it even without support from your host.The basic concepts of the structure and features of a PDF file should be common to all the pdf libraries, however. This library (FPDF) is available at
http://www.fpdf.org.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Documents and Pages
- InhaltsvorschauA PDF document is made up of a number of pages. Each page contains text and/or images. This section shows you how to make a document, create pages in that document, put text onto the pages, and send the pages back to the browser when you're done.The examples in this chapter assume that you have at least the Adobe PDF document viewer installed as an add-on to your web browser. These examples will not work otherwise. You can get the add-on from the Adobe web page at
http://www.adobe.com.Let's start with a simple PDF document. Example 10-1 simply places "Hello Out There!" on a page and then displays the resulting PDF document.Example 10-1. Hello out there in PDF<?php require("../fpdf/fpdf.php"); // path to fpdf.php $pdf = new FPDF( ); $pdf->AddPage( ); $pdf->SetFont('Arial','B',16); $pdf->Cell(40,10,'Hello Out There!'); $pdf->Output( ); ?>Example 10-1 follows the basic steps involved in creating a PDF document: creating a new pdf object instance, creating a page, setting a valid font for the pdf text, and writing the text to a "cell" on the page. Figure 10-1 shows the output of Example 10-1.
Figure 10-1: Hello out there PDF exampleIn Example 10-1, we started by making reference to the FPDF library with the require function. Then the code created a new instance of the FPDF object with the 'new' keyword. You will note that all the calls to the new fpdf instance are object-oriented calls to methods in that object. Be sure to refer to Chapter 6 if you have trouble with the samples in this chapter. After you have created the new instance of the FPDF object, you will need to add at least one page to the object—so theAddPagemethod is called. Next, you need to set the font for the output you are about to generate with theEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Text
- InhaltsvorschauText is the heart of a PDF file. As such, there are many options for changing the appearance and layout of text. In this section, we'll discuss the coordinate system used in PDF documents, functions for inserting text and changing text attributes, and font usage.The origin (
(0,0)) in a PDF document with the FPDF library is in the top-left corner of the defined page. All of the measurements are specified in points, millimeters, inches, or centimeters. A point (the default) is equal to 1/72 of an inch, or 0.35 mm. In the following code (Example 10-2) we change the defaults of the page dimensions to inches with theFPDF( )class instantiation-constructor method. The other options with this call are the orientation of the page (Portrait or Landscape), and the page size (typically Legal or Letter). The full options of this instantiation are shown in the following table:FPDF ( ) constructor parametersParameter optionsOrientation-
P -
Portrait; default
-
L -
Landscape
Units of MeasurementEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Chapter 11: XML
- InhaltsvorschauXML, the Extensible Markup Language, is a standardized data format. It looks a little like HTML, with tags (
<example>like this</example>) and entities (&). Unlike HTML, however, XML is designed to be easy to parse, and there are rules for what you can and cannot do in an XML document. XML is now the standard data format in fields as diverse as publishing, engineering, and medicine. It's used for remote procedure calls, databases, purchase orders, and much more.There are many scenarios where you might want to use XML. Because it is a common format for data transfer, other programs can emit XML files for you to either extract information from (parse) or display in HTML (transform). This chapter shows how to use the XML parser bundled with PHP, as well as how to use the optional XSLT extension to transform XML. We also briefly cover generating XML.Recently, XML has been used in remote procedure calls. A client encodes a function name and parameter values in XML and sends them via HTTP to a server. The server decodes the function name and values, decides what to do, and returns a response value encoded in XML. XML-RPC has proved a useful way to integrate application components written in different languages. In this chapter, we'll show you how to write XML-RPC servers and clients.Most XML consists of elements (like HTML tags), entities, and regular data. For example:<book isbn="1-56592-610-2"> <title>Programming PHP</title> <authors> <author>Rasmus Lerdorf</author> <author>Kevin Tatroe</author> <author>Peter MacIntyre</author> </authors> </book>In HTML, you often have an open tag without a close tag. The most common example of this is:<br>
In XML, that is illegal. XML requires that every open tag be closed. For tags that don't enclose anything, such as the line break<br>, XML adds this syntax:<br />
Tags can be nested but cannot overlap. For example, this is valid:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Lightning Guide to XML
- InhaltsvorschauMost XML consists of elements (like HTML tags), entities, and regular data. For example:
<book isbn="1-56592-610-2"> <title>Programming PHP</title> <authors> <author>Rasmus Lerdorf</author> <author>Kevin Tatroe</author> <author>Peter MacIntyre</author> </authors> </book>In HTML, you often have an open tag without a close tag. The most common example of this is:<br>
In XML, that is illegal. XML requires that every open tag be closed. For tags that don't enclose anything, such as the line break<br>, XML adds this syntax:<br />
Tags can be nested but cannot overlap. For example, this is valid:<book><title>Programming PHP</title></book>
but this is not valid, because thebookandtitletags overlap:<book><title>Programming PHP</book></title>
XML also requires that the document begin with a processing instruction that identifies the version of XML being used (and possibly other things, such as the text encoding used). For example:<?xml version="1.0" ?>
The final requirement of a well-formed XML document is that there be only one element at the top level of the file. For example, this is well formed:<?xml version="1.0" ?> <library> <title>Programming PHP</title> <title>Programming Perl</title> <title>Programming C#</title> </library>
but this is not well formed, as there are three elements at the top level of the file:<?xml version="1.0" ?> <title>Programming PHP</title> <title>Programming Perl</title> <title>Programming C#</title>
XML documents generally are not completely ad hoc . The specific tags, attributes, and entities in an XML document, and the rules governing how they nest, comprise the structure of the document. There are two ways to write down this structure: the Document Type Definition (DTD ) and the Schema . DTD's and Schemas are used to validate documents; that is, to ensure that they follow the rules for their type of document.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Generating XML
- InhaltsvorschauJust as PHP can be used to generate dynamic HTML, it can also be used to generate dynamic XML. You can generate XML for other programs to make use of based on forms, database queries, or anything else you can do in PHP. One application for dynamic XML is Rich Site Summary (RSS), a file format for syndicating news sites. You can read an article's information from a database or from HTML files and emit an XML summary file based on that information.Generating an XML document from a PHP script is simple. Simply change the MIME type of the document, using the
header( )function, to"text/xml". To emit the<?xml ... ?>declaration without it being interpreted as a malformed PHP tag, you'll need to either disableshort_open_tagin your php.ini file, or simplyechothe line from within PHP code:<?php echo '<?xml version="1.0" encoding="ISO-8859-1" ?>'; ?>
Example 11-1 generates an RSS document using PHP. An RSS file is an XML document containing severalchannelelements, each of which contains some newsitemelements. Each news item can have a title, a description, and a link to the article itself. More properties of an item are supported by RSS than Example 11-1 creates. Just as there are no special functions for generating HTML from PHP, there are no special functions for generating XML. You justechoit!Example 11-1. Generating an XML document<?php header('Content-Type: text/xml'); ?> <?xml version='1.0' encoding='ISO-8859-1' ?> <!DOCTYPE rss PUBLIC '-//Netscape Communications//DTD RSS 0.91//EN' 'http://my.netscape.com/publish/formats/rss-0.91.dtd'> <rss version="0.91"> <channel> <?php // news items to produce RSS for $items = array( array('title' => 'Man Bites Dog', 'link' => 'http://www.example.com/dog.php', 'desc' => 'Ironic turnaround!'), array('title' => 'Medical Breakthrough!', 'link' => 'http://www.example.com/doc.php', 'desc' => 'Doctors announced a cure for me.') ); foreach($items as $item) { echo "<item>\n"; echo " <title>{$item[title]}</title>\n"; echo " <link>{$item[link]}</link>\n"; echo " <description>{$item[desc]}</description>\n"; echo " <language>en-us</language>\n"; echo "</item>\n"; } ?> </channel> </rss>Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Parsing XML
- InhaltsvorschauSay you have a collection of books written in XML, and you want to build an index showing the document title and its author. You need to parse the XML files to recognize the
titleandauthorelements and their contents. You could do this by hand with regular expressions and string functions such asstrtok( ), but it's a lot more complex than it seems. The easiest and quickest solution is to use the XML parser that ships with PHP.PHP includes three XML parsers—one event-driven library based on the Expat C library, one DOM-based library, and one for parsing simple XML documents named, appropriately, SimpleXML.The most commonly used parser is the event-based library, which lets you parse but not validate XML documents. This means you can find out which XML tags are present and what they surround, but you can't find out if they're the right XML tags in the right structure for this type of document. In practice, this isn't generally a big problem.PHP's XML parser is event-based, meaning that as the parser reads the document, it calls various handler functions you provide as certain events occur, such as the beginning or end of an element.In the following sections we discuss the handlers you can provide, the functions to set the handlers, and the events that trigger the calls to those handlers. We also provide sample functions for creating a parser to generate a map of the XML document in memory, tied together in a sample application that pretty-prints XML.When the parser encounters the beginning or end of an element, it calls the start and end element handlers . You set the handlers through thexml_set_element_handler( )function:xml_set_element_handler(parser, start_element, end_element);
The start_element and end_element parameters are the names of the handler functions.The start element handler is called when the XML parser encounters the beginning of an element:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Parsing XML with DOM
- InhaltsvorschauThe DOM parser provided in PHP is much simpler to use, but what you take out in complexity comes back in memory usage—in spades. Instead of firing events and allowing you to handle the document as it's being parsed, the DOM parser takes an XML document and returns an entire tree of nodes and elements.
$parser = new DomDocument( ); $rootNode = $parser->load('BookList.xml'); processNodes($rootNode); function processNodes($node) { $children = $node->children; foreach ($children as $child) { if ($child->nodeType == XML_TEXT_NODE) { echo $child->noteValue; } else if ($child->nodeType == XML_ELEMENT_NODE) { processNodes($child); } } }Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Parsing XML with SimpleXML
- InhaltsvorschauIf you're consuming very simple XML documents, you might consider the third library provided by PHP, SimpleXML. SimpleXML doesn't have the ability to generate documents as the DOM extension does, and isn't as flexible or memory-efficient as the Expat extension, but it makes it very easy to parse and use XML documents.SimpleXML takes a file, string, or DOM document (produced using the DOM extension) and generates an object. Properties on that object are counters providing access to elements in each node. Using them, you can access elements using numeric indices and non-numeric indices to access attributes. Finally, you can use string conversion on any value you retrieve to get the text value of the item.For example, we could display all the titles of the books in our Book List XML document using:
$document= simplexml_load_file('bookparse.xml'); foreach ($document->library->book as $book) { echo $book->title; }Using thechildren( )method on the object, you can iterate over the child nodes of a given node; likewise, you can use theattributes( )method on the object to iterate over the attributes of the node:$document= simplexml_load_file('bookparse.xml'); foreach ($document->library->children( ) as $node) { foreach ($node->attributes( ) as $attribute) { echo "$attribute\n"; } }Finally, using theasXML( )method on the object, you can retrieve the XML of the document in XML format. This lets you change values in your document and write it back out to disk easily:$document= simplexml_load_file('bookparse.xml'); foreach ($document->library->book as $book) { $book->title = 'New Title'; } file_put_contents('bookparse.xml', $document->asXML( ));Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Transforming XML with XSLT
- InhaltsvorschauExtensible Stylesheet Language Transformations (XSLT) is a language for transforming XML documents into different XML, HTML, or any other format. For example, many web sites offer several formats of their content—HTML, printable HTML, and WML (Wireless Markup Language) are common. The easiest way to present these multiple views of the same information is to maintain one form of the content in XML and use XSLT to produce the HTML, printable HTML, and WML.PHP's XSLT extension uses the libxslt C library to provide XSLT support. The library is included by default as of PHP 5, and can be enabled by compiling PHP with the
--with-xsl[=DIR]option to configure.Three documents are involved in an XSLT transformation: the original XML document, the XSLT document containing transformation rules, and the resulting document. The final document doesn't have to be in XML—a common use of XSLT is to generate HTML from XML. To do an XSLT transformation in PHP, you create an XSLT processor, give it some input to transform, and then destroy the processor.Create a processor by creating a newXSLTProcessorobject:$xslt = new XSLTProcessor;
Parse the XML and XSL files into DOM objects:$xml = new DOMDocument $xml->load($xml_file); $xsl = new DOMDocument; $xsl->load($xsl_file);
Attach the XML rules to the object:$xslt->importStyleSheet($xsl);
Process a file with thetransformToDoc( ),transformToURI( ), ortransformToXML( )methods:$result = $xslt->transformToXML($xml);
The document parameter is a DOM object representing the XML document.Example 11-11 is the XML document we're going to transform. It is in a similar format to many of the news documents you find on the Web.Example 11-11. XML document<?xml version="1.0" ?> <news xmlns:news="http://slashdot.org/backslash.dtd"> <story> <title>O'Reilly Publishes Programming PHP</title> <url>http://example.org/article.php?id=20020430/458566</url> <time>2002-04-30 09:04:23</time> <author>Rasmus and some others</author> </story> <story> <title>Transforming XML with PHP Simplified</title> <url>http://example.org/article.php?id=20020430/458566</url> <time>2002-04-30 09:04:23</time> <author>k.tatroe</author> </story> </news>Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Web Services
- InhaltsvorschauHistorically, every time there's been a need for two systems to communicate, a new protocol has been created (for example, SMTP for sending mail, POP3 for receiving mail, and the numerous protocols that database clients and servers use). The idea of web services is to remove the need to create new protocols by providing a standardized mechanism for remote procedure calls, based on XML and HTTP.Web services make it easy to integrate heterogeneous systems. Say you're writing a web interface to a library system that already exists. It has a complex system of database tables, and lots of business logic embedded in the program code that manipulates those tables. And it's written in C++. You could re-implement the business logic in PHP, writing a lot of code to manipulate tables in the correct way, or you could write a little code in C++ to expose the library operations (e.g., check out a book to a user, see when this book is due back, see what the overdue fines are for this user) as a web service. Now your PHP code simply has to handle the web front-end; it can use the library service to do all the heavy lifting.XML-RPC and SOAP are two of the standard protocols used to create web services. XML-RPC is the older (and simpler) of the two, while SOAP is newer and more complex. Microsoft's .NET initiative is based on SOAP, while many of the popular web journal packages, such as Frontier and blogger, offer XML-RPC interfaces.PHP provides access to both SOAP and XML-RPC through the xmlrpc extension, which is based on the xmlrpc-epi project (see
http://xmlrpc-epi.sourceforge.netfor more information). The xmlrpc extension is not compiled in by default, so you'll need to add--with-xmlrpcto your configure line.The PEAR projecthttp://pear.php.netis working on an object-oriented XML-RPC extension, but it was not ready for release at the time of this writing.Example 11-14 shows a very basic XML-RPC server that exposes only one function (which XML-RPC calls a "method"). That function,Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 12: Security
- InhaltsvorschauPHP is a flexible language that has hooks into just about every API offered on the machines on which it runs. Because it was designed to be a forms-processing language for HTML pages, PHP makes it easy to use form data sent to a script. Convenience is a double-edged sword, however. The very features that let you quickly write programs in PHP can open doors for those who would break into your systems.It's important to understand that PHP itself is neither secure nor insecure. The security of your web applications is entirely determined by the code you write. For example, take a script that opens a file whose name was passed as a form parameter. If you don't check the filename, the user can give a URL, an absolute pathname, or even a relative path to back out of the application data directory and into a personal or system directory.Web application security is a young and evolving discipline. A single chapter on security cannot sufficiently prepare you for the onslaught of attacks your applications are sure to receive. This chapter takes a pragmatic approach and covers a distilled selection of topics related to security, including how to protect your applications from the most common and dangerous attacks. The chapter concludes with a list of additional resources that can help fill in the gaps as well as a brief recap that includes a few additional tips.One of the most fundamental things to realize when developing a secure application is that any information not generated within the application itself is potentially tainted. This idea can be reduced to considering all input tainted, because input is the data you receive from outside sources.When data is described as being tainted, this doesn't mean it's necessarily malicious. It means it might be malicious, because you can't trust the source, so you should inspect it to make sure it's valid. This inspection process is called filtering, and you only want to allow valid data to enter your application.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Filter Input
- InhaltsvorschauOne of the most fundamental things to realize when developing a secure application is that any information not generated within the application itself is potentially tainted. This idea can be reduced to considering all input tainted, because input is the data you receive from outside sources.When data is described as being tainted, this doesn't mean it's necessarily malicious. It means it might be malicious, because you can't trust the source, so you should inspect it to make sure it's valid. This inspection process is called filtering, and you only want to allow valid data to enter your application.There are a few best practices regarding the filtering process:
-
Use a whitelist approach. This means you err on the side of caution and assume data to be invalid unless you can prove it to be valid.
-
Never correct invalid data. History has proven that attempts to correct invalid data often result in security vulnerabilities due to errors.
-
Use a naming convention to help distinguish between filtered and tainted data. Filtering is useless if you can't reliably determine whether something has been filtered.
In order to solidify these concepts, consider a simple HTML form that allows a user to select between three colors:<form action="process.php" method="POST"> Please select a color: <select name="color"> <option value="red">red</option> <option value="green">green</option> <option value="blue">blue</option> </select> <input type="submit" /> </form>
It's easy to appreciate the desire to trust$_POST['color']inprocess.php. After all, the form restricts what a user can enter. However, experienced developers know that an HTTP request isn't necessarily sent by a browser that's being used by a well-behaved user. There are numerous ways that malicious data can be sent to your application, and your only defense is to trust nothing and filter your input:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Escape Output
- InhaltsvorschauEscaping is a technique that preserves data as it enters another context. PHP is frequently used as a bridge between disparate data sources, and when you send data to a remote source, it's your responsibility to prepare it properly, so that it's not misinterpreted.For example,
O'Reillyis represented asO\'Reillywhen being used in an SQL query to be sent to a MySQL database. The backslash before the single quote exists to preserve the single quote in the context of the SQL query. The single quote is part of the data, not part of the query, and the escaping guarantees this interpretation.The two predominant remote sources to which PHP applications send data are HTTP clients (web browsers) that interpret HTML, JavaScript, and other client-side technologies, and databases that interpret SQL. For the former, PHP provideshtmlentities( ):<?php $html = array( ); $html['username'] = htmlentities($clean['username'], ENT_QUOTES, 'UTF-8'); echo "<p>Welcome back, {$html['username']}.</p>"; ?>This example demonstrates the use of another naming convention. The$htmlarray is similar to the $clean array, except that its purpose is to hold data that is safe to be used in the context of HTML.URLs are sometimes embedded in HTML as links:<a href="http://host/script.php?var=value">Click Here</a>
In this particular example,valueexists within nested contexts. It's within the query string of a URL that is embedded in HTML as a link. Because it's alphabetic in this case, it's safe to be used in both contexts. However, when the value ofvarcannot be guaranteed to be safe in these contexts, it must be escaped twice:<?php $html = array( ); $url = array( ); $url['value'] = urlencode($value); $link = "http://host/script.php?var={$url['value']}"; $html['link'] = htmlentities($link, ENT_QUOTES, 'UTF-8'); ?> <a href="<?php echo $html['link']; ?>">Click Here</a>This ensures that the link is safe to be used in the context of HTML, and when it is used as a URL (such as when the user clicks the link), the URL encoding ensures that the value ofEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Cross-Site Scripting
- InhaltsvorschauCross-site scripting (XSS) has become the most common web application security vulnerability, and with the rising popularity of Ajax technologies, XSS attacks are likely to become more advanced and to occur more frequently.The name cross-site scripting derives from an old exploit and is no longer very descriptive or accurate for most modern attacks, and this has caused some confusion.Simply put, a vulnerability exists whenever you output un-escaped data. For example:
<?php echo $_POST['username']; ?>
This is an extreme example, because $_POST is obviously neither filtered nor escaped, but it demonstrates the vulnerability.XSS attacks are limited to only what is possible with client-side technologies. Historically, XSS has been used to capture a victim's cookies by taking advantage of the fact thatdocument.cookiecontains this information.In order to prevent XSS, all that is necessary is that you escape your output:<?php $html = array( ); $html['username'] = htmlentities($_POST['username'], ENT_QUOTES, 'UTF-8'); echo $html['username']; ?>
You should also always filter your input, and filtering can offer a redundant safeguard in some cases (implementing redundant safeguards adheres to a security principle known as Defense in Depth). For example, if you inspect a username to ensure it's alphabetic and only output the filtered username, no XSS vulnerability exists.Just be sure that you don't depend upon filtering as your primary safeguard against XSS, because it doesn't address the root cause of the problem.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Session Fixation
- InhaltsvorschauA very popular attack that targets sessions is session fixation . The primary reason behind its popularity is that it's the easiest method by which an attacker can obtain a valid session identifier. As such, its intended use is as a stepping-stone to a session hijacking attack, impersonating a user by presenting the user's session identifier.Session fixation is any approach that causes a victim to use a session identifier chosen by an attacker. The simplest example is a link with an embedded session identifier:
<a href="http://host/login.php?PHPSESSID=1234">Log In</a>
A victim who clicks this link will resume the session identified as1234, and if the victim proceeds to log in, the attacker can hijack the victim's session to escalate his level of privilege.There are a few variants of this attack, including some that use cookies for this same purpose. Luckily, the safeguard is simple, straightforward, and consistent. Whenever there is a change in the level of privilege, such as when a user logs in, regenerate the session identifier withsession_regenerate_id( ):<?php if (check_auth($_POST['username'], $_POST['password'])) { $_SESSION['auth'] = TRUE; session_regenerate_id( ); } ?>This effectively prevents session fixation attacks by ensuring that any user who logs in (or otherwise escalates the privilege level in any way) is assigned a fresh, random session identifier.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - File Uploads
- InhaltsvorschauFile uploads combine the two dangers we've seen so far: user-modifiable data and the filesystem. While PHP 5 itself is secure in how it handles uploaded files, there are several potential traps for unwary programmers.Be careful using the filename sent by the browser. If possible, do not use this as the name of the file on your filesystem. It's easy to make the browser send a file identified as /etc/passwd or /home/rasmus/.forward. You can use the browser-supplied name for all user interaction, but generate a unique name yourself to actually call the file. For example:
$browser_name = $_FILES['image']['name']; $temp_name = $_FILES['image']['tmp_name']; echo "Thanks for sending me $browser_name."; $counter++; // persistent variable $my_name = "image_$counter"; if (is_uploaded_file($temp_name)) { move_uploaded_file($temp_name, "/web/images/$my_name"); } else { die("There was a problem processing the file."); }Another trap is the size of uploaded files. Although you can tell the browser the maximum size of file to upload, this is only a recommendation and it cannot ensure that your script won't be handed a file of a larger size. The danger is that an attacker will try a denial of service attack by sending you several large files in one request and filling up the filesystem in which PHP stores the decoded files.Set thepost_max_sizeconfiguration option in php.ini to the maximum size (in bytes) that you want:post_max_size = 1024768 ; one megabyte
The default 10 MB is probably larger than most sites require.The defaultvariables_orderprocesses GET and POST parameters before cookies. This makes it possible for the user to send a cookie that overwrites the global variable you think contains information on your uploaded file. To avoid being tricked like this, check that the given file was actually an uploaded file using theEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - File Access
- InhaltsvorschauIf only you and people you trust can log into your web server, you don't need to worry about file permissions for files used by or created by your PHP programs. However, most web sites are hosted on ISP's machines, and there's a risk that non-trusted people can read files that your PHP program creates. There are a number of techniques that you can use to deal with file permissions issues.You can set the
open_basediroption to restrict access from your PHP scripts to a specific directory. Ifopen_basediris set php.ini, PHP limits filesystem and I/O functions so that they can operate only within that directory or any of its subdirectories. For example:open_basedir = /some/path
With this configuration in effect, the following function calls succeed:unlink("/some/path/unwanted.exe"); include("/some/path/less/travelled.inc");But these generate runtime errors:$fp = fopen ("/some/other/file.exe", "r"); $dp = opendir("/some/path/../other/file.exe");Of course, one web server can run many applications, and each application typically stores files in its own directory. You can configureopen_basediron a per-virtual host basis in your httpd.conf file like this:<VirtualHost 1.2.3.4> ServerName domainA.com DocumentRoot /web/sites/domainA php_admin_value open_basedir /web/sites/domainA </VirtualHost>
Similarly, you can configure it per directory or per URL in httpd.conf:# by directory <Directory /home/httpd/html/app1> php_admin_value open_basedir /home/httpd/html/app1 </Directory> # by URL <Location /app2> php_admin_value open_basedir /home/httpd/html/app2 </Location>
Theopen_basedirdirectory can be set only in the httpd.conf file, not in .htaccess files, and you must usephp_admin_valueto set it.Do not create a file and then change its permissions. This creates a race condition, where a lucky user can open the file once it's created but before it's locked down. Instead, use theEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - PHP Code
- InhaltsvorschauWith the
eval( )function, PHP allows a script to execute arbitrary PHP code. Although it can be useful in a few limited cases, allowing any user-supplied data to go into aneval( )call is asking to be hacked. For instance, the following code is a security nightmare:<html> <head> <title>Here are the keys...</title> </head> <body> <?php if ($code) { echo "Executing code..."; eval(stripslashes($code)); // BAD! } ?> <form> <input type="text" name="code" /> <input type="submit" name="Execute Code" /> </form> </body> </html>This page takes some arbitrary PHP code from a form and runs it as part of the script. The running code has access to all of the global variables for the script and runs with the same privileges as the script running the code. It's not hard to see why this is a problem—type this into the form:include('/etc/passwd');Unfortunately, there's no easy way to ensure that a script like this can ever be secure.You can globally disable particular function calls by listing them, separated by commas, in thedisable_functionsconfiguration option in php.ini. For example, you may never have need for thesystem( )function, so you can disable it entirely with:disable_functions = system
This doesn't makeeval( )any safer, though, as there's no way to prevent important variables from being changed or built-in constructs such asecho( )from being called.Note that thepreg_replace( )function with the/eoption also callseval( )on PHP code, so don't use user-supplied data in the replacement string.In the case ofinclude,require,include_once, andrequire_once, your best bet is to turn off remote file access usingallow_url_fopen.Any use ofeval( )and the/eoption withpreg_replace( )is dangerous, especially if you use any user-entered data in the calls. Consider the following:eval("2 + $user_input");It seems pretty innocuous. However, suppose the user enters the following value:Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Shell Commands
- InhaltsvorschauBe very wary of using the
exec( ),system( ),passthru( ), andpopen( )functions and the backtick ('') operator in your code. The shell is a problem because it recognizes special characters (e.g., semicolons to separate commands). For example, suppose your script contains this line:system("ls $directory");If the user passes the value"/tmp;cat /etc/passwd"as the$directoryparameter, your password file is displayed becausesystem( )executes the following command:ls /tmp;cat /etc/passwd
In cases where you must pass user-supplied arguments to a shell command, useescapeshellarg( )on the string to escape any sequences that have special meaning to shells:$cleaned_up = escapeshellarg($directory); system("ls $cleaned_up");Now, if the user passes"/tmp;cat /etc/passwd", the command that's actually run is:ls '/tmp;cat /etc/passwd'
The easiest way to avoid the shell is to do the work of whatever program you're trying to call. Built-in functions are likely to be more secure than anything involving the shell.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - More Information
- InhaltsvorschauThe following resources can help you expand on this brief introduction:
-
Essential PHP Security by Chris Shiflett (O'Reilly) and its companion web site at
http://phpsecurity.org/ -
The PHP Security Consortium at
http://phpsec.org/
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Security Recap
- InhaltsvorschauBecause security is such an important issue, we want to reiterate the main points of this chapter as well as add a few additional tips:
-
Filter input to be sure that all data you receive from remote sources is the data you expect. Remember, the stricter your filtering logic, the safer your application.
-
Escape output to be sure that your data isn't misinterpreted by a remote system.
-
Always initialize your variables. This is especially important when the
register_globalsdirective is enabled. -
Disable
register_globals,magic_quotes_gpc, andallow_url_fopen. Seehttp://www.php.netfor details on these directives. -
Whenever you construct a filename, check the components with
basename( )andrealpath( ). -
Store includes outside of the document root. It is better to not name your included files with the .inc extension. Name them with a .php extension, or some other less obvious extension.
-
Always call
session_regenerate_id( )whenever a user's privilege level changes. -
Whenever you construct a filename from a user-supplied component, check the components with
basename( )andrealpath( ). -
Don't create a file and then change its permissions. Instead, set
umask( )so that the file is created with the correct permissions. -
Don't use user-supplied data with
eval( ),preg_replace( )with the/eoption, or any of the system commands (exec( ),system( ),popen( ),passthru( ), and the backtick ('') operator).
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Chapter 13: Application Techniques
- InhaltsvorschauBy now, you should have a solid understanding of the details of the PHP language and its use in a variety of common situations. Now we're going to show you some techniques you may find useful in your PHP applications, such as code libraries , templating systems, efficient output handling, error handling, and performance tuning.As you've seen, PHP ships with numerous extension libraries that combine useful functionality into distinct packages that you can access from your scripts. We covered using the GD, fpdf, and libxslt extension libraries in Chapters 9-11, and Appendix B lists a vast array of almost all of the available extensions.In addition to using the extensions that ship with PHP, you can create libraries of your own code that you can use in more than one part of your web site. The general technique is to store a collection of related functions in a file, typically with an .inc file extension. Then, when you need to use that functionality in a page, you can use
require_once( )to insert the contents of the file into your current script.Note that there are three other inclusion type functions that can also be employed. They arerequire( ),include_once( ), andinclude( ). Look up the idiosyncrasies of these functions and use them to their most beneficial.For example, say you have a collection of functions that help create HTML form elements in valid HTML—one function in your collection creates a text field or atextarea(depending on how many characters you tell it the maximum is), another creates a series of pop-ups from which to set a date and time, and so on. Rather than copying the code into many pages, which is tedious, error-prone, and makes it difficult to fix any bugs found in the functions, creating a function library is the sensible choice.When you are combining functions into a code library, you should be careful to maintain a balance between grouping related functions and including functions that are not often used. When you include a code library in a page, all of the functions in that library are parsed, whether you use them all or not. PHP's parser is quick, but not parsing a function is even faster. At the same time, you don't want to split your functions over too many libraries, so that you have to include lots of files in each page, because file access is slow.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Code Libraries
- InhaltsvorschauAs you've seen, PHP ships with numerous extension libraries that combine useful functionality into distinct packages that you can access from your scripts. We covered using the GD, fpdf, and libxslt extension libraries in Chapters 9-11, and Appendix B lists a vast array of almost all of the available extensions.In addition to using the extensions that ship with PHP, you can create libraries of your own code that you can use in more than one part of your web site. The general technique is to store a collection of related functions in a file, typically with an .inc file extension. Then, when you need to use that functionality in a page, you can use
require_once( )to insert the contents of the file into your current script.Note that there are three other inclusion type functions that can also be employed. They arerequire( ),include_once( ), andinclude( ). Look up the idiosyncrasies of these functions and use them to their most beneficial.For example, say you have a collection of functions that help create HTML form elements in valid HTML—one function in your collection creates a text field or atextarea(depending on how many characters you tell it the maximum is), another creates a series of pop-ups from which to set a date and time, and so on. Rather than copying the code into many pages, which is tedious, error-prone, and makes it difficult to fix any bugs found in the functions, creating a function library is the sensible choice.When you are combining functions into a code library, you should be careful to maintain a balance between grouping related functions and including functions that are not often used. When you include a code library in a page, all of the functions in that library are parsed, whether you use them all or not. PHP's parser is quick, but not parsing a function is even faster. At the same time, you don't want to split your functions over too many libraries, so that you have to include lots of files in each page, because file access is slow.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Templating Systems
- InhaltsvorschauA templating system provides a way of separating the code in a web page from the layout of that page. In larger projects, templates can be used to allow designers to deal exclusively with designing web pages and programmers to deal (more or less) exclusively with programming. The basic idea of a templating system is that the web page itself contains special markers that are replaced with dynamic content. A web designer can create the HTML for a page and simply worry about the layout, using the appropriate markers for different kinds of dynamic content that are needed. The programmer, on the other hand, is responsible for creating the code that generates the dynamic content for the markers.To make this more concrete, let's look at a simple example. Consider the following web page, which asks the user to supply a name and, if a name is provided, thanks the user:
<html> <head> <title>User Information</title> </head> <body> <?php if (!empty($_GET['name'])) { // do something with the supplied values ?> <p><font face="helvetica,arial">Thank you for filling out the form, <?php echo $_GET['name'] ?>.</font></p> <?php } else { ?> <p><font face="helvetica,arial">Please enter the following information:</font></p> <form action="<?php echo $_SERVER['PHP_SELF'] ?>"> <table> <tr> <td>Name:</td> <td><input type="text" name="name" /></td> </tr> </table> </form> <?php } ?> </body> </html>The placement of the different PHP elements within various layout tags, such as thefontandtableelements, are better left to a designer, especially as the page gets more complex. Using a templating system, we can split this page into separate files, some containing PHP code and some containing the layout. The HTML pages will then contain special markers where dynamic content should be placed. Example 13-1 shows the new HTML template page for our simple form, which is stored in the fileEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Handling Output
- InhaltsvorschauPHP is all about displaying output in the web browser. As such, there are a few different techniques that you can use to handle output more efficiently or conveniently.By default, PHP sends the results of
echoand similar commands to the browser after each command is executed. Alternately, you can use PHP's output buffering functions to gather the information that would normally be sent to the browser into a buffer and send it later (or kill it entirely). This allows you to specify the content length of your output after it is generated, capture the output of a function, or discard the output of a built-in function.You turn on output buffering with theob_start( )function:ob_start([callback ]);The optional callback parameter is the name of a function that post-processes the output. If specified, this function is passed the collected output when the buffer is flushed, and it should return a string of output to send to the browser. You can use this, for instance, to turn all occurrences ofhttp://www.yoursite.com/tohttp://www.mysite.com/.While output buffering is enabled, all output is stored in an internal buffer. To get the current length and contents of the buffer, useob_get_length( )andob_get_contents( ):$len = ob_get_length( ); $contents = ob_get_contents( );If buffering isn't enabled, these functions returnfalse.There are two ways to throw away the data in the buffer. Theob_clean( )function erases the output buffer but does not turn off buffering for subsequent output. Theob_end_clean( )function erases the output buffer and ends output buffering.There are three ways to send the collected output to the browser (this action is known as flushing the buffer). Theob_flush( )function sends the output data to the web server and clears the buffer, but doesn't terminate output buffering. Theflush( )function not only flushes and clears the output buffer, but also tries to make the web server send the data to the browser immediately. TheEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Error Handling
- InhaltsvorschauError handling is an important part of any real-world application. PHP provides a number of mechanisms that you can use to handle errors, both during the development process and once your application is in a production environment.Normally, when an error occurs in a PHP script, the error message is inserted into the script's output. If the error is fatal, the script execution stops.There are three levels of conditions: notices , warnings , and errors. A notice is a condition encountered while executing a script that could be an error but could also be encountered during normal execution (e.g., trying to access a variable that has not been set). A warning indicates a nonfatal error condition; typically, warnings are displayed when calling a function with invalid arguments. Scripts will continue executing after issuing a warning. An error indicates a fatal condition from which the script cannot recover. A parse error is a specific kind of error that occurs when a script is syntactically incorrect. All errors except parse errors are runtime errors.By default, all conditions except runtime notices are caught and displayed to the user. You can change this behavior globally in your php.ini file with the
error_reportingoption. You can also locally change the error-reporting behavior in a script using theerror_reporting( )function.With both theerror_reportingoption and theerror_reporting( )function, you specify the conditions that are caught and displayed by using the various bitwise operators to combine different constant values, as listed in Table 13-1. For example, this indicates all error-level options:(E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR)while this indicates all options except runtime notices:(E_ALL & ~E_NOTICE)If you set thetrack_errorsoption on in your php.ini file, a description of the current error is stored in$PHP_ERRORMSG.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Performance Tuning
- InhaltsvorschauBefore thinking much about performance tuning , take the time to get your code working properly. Once you have sound, working code, you can then locate the slower sections, or "bottlenecks." If you try to optimize your code while writing it, you'll discover that optimized code tends to be more difficult to read and generally takes more time to write. If you spend that time on a section of code that isn't actually causing a problem, that's time wasted, especially when it comes time to maintain that code and you can no longer read it.
Figure 13-1: Error message instead of the buffered HTMLOnce you get your code working, you may find that it needs some optimization. Optimizing code tends to fall within one of two areas: shortening execution times and lessening memory requirements.Before you begin optimization, ask yourself whether you need to optimize at all. Too many programmers have wasted hours wondering whether a complex series of string function calls are faster or slower than a single Perl regular expression, when the page that this code is in is viewed once every five minutes. Optimization is necessary only when a page takes so long to load that the user perceives it as slow. Often this is a symptom of a very popular site—if requests for a page come in fast enough, the time it takes to generate that page can mean the difference between prompt delivery and server overload. With a possible long wait on your site, you can bet that your web visitor won't take as long in deciding to obtain their information at another web site.Once you've decided that your page needs optimization (this can best be done with some end-user testing and observation), you can move on to working out exactly what is slow. You can use the techniques in the section "Profiling" to time the various subroutines or logical units of your page. This will give you an idea of which parts of your page are taking the longest time to produce—these parts are where you should focus your optimization efforts. If a page is taking five seconds to produce, you'll never get it down to two seconds by optimizing a function that accounts for only 0.25 seconds of the total time. Identify the biggest time-wasting blocks of code and focus on them. Time the page and the pieces you're optimizing, to make sure your changes are having a positive, and not a negative, effect.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 14: Extending PHP
- InhaltsvorschauThis chapter shows you how to write C language extensions to PHP. Although most functionality can be written in the PHP language, sometimes you need the extra speed and control you get from the C API. C code runs an order of magnitude faster than most interpreted script code, and it is also the mechanism for creating the thin middle layer between PHP and any third-party C library.For example, to be able to talk to the MySQL database server, PHP needs to implement the MySQL socket protocol. It would be a lot of work to figure out this protocol and talk to MySQL directly using
fsockopen( )andfputs( )from a PHP script. Instead, the same goal can be accomplished with a thin layer of functions written in C that translate MySQL's C API, implemented in the libmysqlclient.so library included in MySQL, into PHP language-level function calls. This thin layer of functions is known as a PHP extension. PHP extensions do not always have to be a layer between PHP and some third-party library, however. An extension can instead completely implement some feature directly (for example, the FTP extension).Before we get into the details of writing extensions, a note of caution: If you are just learning PHP and do not have any sort of C programming background, you should probably skip this chapter. Extension writing is an advanced topic, and it is not for the faint of heart.There are two kinds of extensions that you can write: PHP extensions and Zend extensions. We will focus on PHP extensions here. Zend extensions are lower-level extensions that somehow modify the very core of the language. Opcode cache systems such as APC and Zend's Accelerator are Zend extensions. PHP extensions simply provide functions or objects to PHP scripts. MySQL, Oracle, LDAP, SNMP, EXIF, GD, and Ming are all examples of PHP extensions.Figure 14-1 shows a diagram of a web server with PHP linked in. The web server layer at the top handles incoming HTTP requests and passes them to PHP via the Server Abstraction API (SAPI). The "mysql," "ldap," and "snmp" boxes represent loadable PHP extensions, the kind you'll learn how to build in this chapter. TSRM is the Thread Safe Resource Manager layer, which helps simplify thread-safe programming. The PHP core contains many of the non-optional core features of PHP, and the PHP API contains the PHP-specific API functions used by both the core and the PHP extensions. Finally, there is the Zend Engine, which runs scripts through a two-pass mechanism, first generating a set of opcodes and then executing them. A PHP extension uses the Zend extension API to receive arguments from function calls and return values back.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Architectural Overview
- InhaltsvorschauThere are two kinds of extensions that you can write: PHP extensions and Zend extensions. We will focus on PHP extensions here. Zend extensions are lower-level extensions that somehow modify the very core of the language. Opcode cache systems such as APC and Zend's Accelerator are Zend extensions. PHP extensions simply provide functions or objects to PHP scripts. MySQL, Oracle, LDAP, SNMP, EXIF, GD, and Ming are all examples of PHP extensions.Figure 14-1 shows a diagram of a web server with PHP linked in. The web server layer at the top handles incoming HTTP requests and passes them to PHP via the Server Abstraction API (SAPI). The "mysql," "ldap," and "snmp" boxes represent loadable PHP extensions, the kind you'll learn how to build in this chapter. TSRM is the Thread Safe Resource Manager layer, which helps simplify thread-safe programming. The PHP core contains many of the non-optional core features of PHP, and the PHP API contains the PHP-specific API functions used by both the core and the PHP extensions. Finally, there is the Zend Engine, which runs scripts through a two-pass mechanism, first generating a set of opcodes and then executing them. A PHP extension uses the Zend extension API to receive arguments from function calls and return values back.
Figure 14-1: Structure of a PHP-linked web serverEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - What You'll Need
- InhaltsvorschauTo develop a PHP extension, you'll need a copy of the PHP source code and various software development tools, as discussed next.Fetch a copy of the current CVS version of the PHP code to ensure that you are using the most up-to-date version of the API. See
http://cvs.php.netfor instructions on how to obtain the CVS version of the code via anonymous CVS.PHP comes with a skeleton extension framework generator called ext_skel; this little script is a lifesaver. You should spend some time studying the README.EXT_SKEL and README.SELF-CONTAINED-EXTENSIONS files that come with the PHP source code.The PHP source code offers you dozens of example extensions to look at. Each subdirectory in the ext/ directory contains a PHP extension. Chances are that just about anything you need to implement will in some way resemble one of the existing examples, and you are strongly encouraged to steal/borrow as much existing code as possible (with proper attribution, of course).To write an extension, you need to have working versions of these tools installed:-
bison
-
flex
-
m4
-
autoconf
-
automake
-
libtool
-
An ANSI-compliant compiler such as gcc
-
make
-
sed, awk, and Perl are also used optionally here and there
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Building Your First Extensions
- InhaltsvorschauThis section walks you through the steps of building your first extension, from design through testing. Most extensions are created by writing a file that defines the functions the extension will have, building a skeleton from that, and then filling in the C code that does the actual work of the extension. This section doesn't cover advanced topics such as returning complex values or managing memory—we'll talk about those later, after you have the basics down.Unless your extension can really be tested only through the web, it is much easier to debug and quickly test your code through the command-line version of PHP (also sometimes referred to as the CGI version of PHP). To build the command-line version, do something like this:
% cd php5 % ./configure --with-mysql=/usr --with-pgsql --with-zlib --with-config-file=/etc % make # make installThis will put a php binary in your /usr/local/bin directory. The configure line above adds MySQL, PostgreSQL, and zlib support. While you don't need them to develop your extension, they won't get in the way, and it is a good idea to have a php binary that can run complex web applications directly from the command line.Just to make sure it worked, test it:% /usr/local/bin/php -v PHP 5.1.0RC2-dev (cli) (built: Oct 2 2005 16:17:09) Copyright (c) 1997-2005 The PHP Group Zend Engine v2.1.0-dev, Copyright (c) 1998-2005 Zend TechnologiesOn Windows, things are similar, but not quite the same. Launch your Visual Studio command prompt. This is a regular "DOS Box" that has the compiler environment setup inside it. It can usually be found on the Start Menu, filed alongside the tools installed when you set up the compiler. If you don't have a shortcut already set up, you can use a regular command prompt window and call vsvars32.bat to set it up. You might need to hunt around for the batch file for this to work. Consult the file README.WIN32-BUILD-SYSTEM for more information on setting up your build environment on Windows.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - The config.m4 File
- InhaltsvorschauThe config.m4 file contains the code that will go into the configure script. This includes the switch that enables the extension (e.g.,
--enable-rot13or--with-rot13), the name of the shared library to build, code to search for prerequisite libraries, and much more. The skeletal config.m4 file contains sample code for the various things you might want to do, but it is commented out.There are conventions governing the configure switch to enable your extension. If your extension does not rely on any external components, use--enable-foo. If it does have some non-bundled dependencies , such as a library, use--with-foo. Optionally, you can specify a base path using--with-foo=/some/path, which helps configure find the dependencies.PHP uses the grand unifying scheme of autoconf, automake, and libtool to build extensions. These three tools, used together, can be extremely powerful, but they can also be extremely frustrating. Getting this stuff right is a bit of a black art. When an extension is part of the PHP source tree and you run the buildconf script in the top directory of the tree, it scans through all its subdirectories looking for config.m4 files. It grabs all the config.m4 files and creates a single configure script that contains all the configure switches. This means that each extension needs to implement its own configure checks to check for whatever dependencies and system-level features might be needed to build the extension.These checks are done through autoconf macros and general m4 scripting in the config.m4 file. Your best bet is probably to look at some of the existing config.m4 files in the various PHP extensions to see how different types of checks are done.The build system used by PHP on Windows is modeled after the autoconf family of tools but is implemented using native javascript code run under the Windows Scripting Host. The config.w32 file is deliberately very similar to its Unix counterpart but not identical.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Memory Management
- InhaltsvorschauIn C, you always have to worry about memory management. This still holds true when writing PHP extensions in C, but the extension API provides you with a safety net and some helpful debugging facilities if you use the API's memory-management wrapper functions (you are strongly encouraged to do so). The wrapper functions are:
emalloc( ) efree( ) estrdup( ) estrndup( ) ecalloc( ) erealloc( )These work exactly like the native C counterparts after which they are named.One of the features you get by usingemalloc( )is a safety net for memory leaks. If youemalloc( )something and forget toefree( )it, PHP prints a leak warning like this if you are running in debug mode (enabled by compiling PHP with the--enable-debugswitch):foo.c(123) : Freeing 0x0821E5FC (20 bytes), script=foo.php Last leak repeated 1 timeIf youefree( )something that was allocated usingmalloc( )or some mechanism other than the PHP memory-management functions, you get the following:--------------------------------------- foo.c(124) : Block 0x08219C94 status: Beginning: Overrun (magic=0x00000000, expected=0x7312F8DC) End: Unknown --------------------------------------- foo.c(124) : Block 0x0821EB1C status: Beginning: Overrun (magic=0x00000000, expected=0x7312F8DC) End: Unknown ---------------------------------------In this case, line 124 in foo.c is the call toefree( ). PHP knows it didn't allocate this memory because it didn't contain the magic token that indicates a PHP allocation.Theemalloc( )/efree( )safety net also catches overruns—e.g., if youemalloc(20)but write 21 bytes to that address. For example:123: s = emalloc(6); 124: strcpy(s,"Rasmus"); 125: efree(s);Because this code failed to allocate enough memory to hold the string and the terminatingNULL, PHP prints this warning:--------------------------------------- foo.c(125) : Block 0x08219CB8 status: Beginning: OK (allocated on foo.c:123, 6 bytes) End: Overflown (magic=0x2A8FCC00 instead of 0x2A8FCC84) 1 byte(s) overflown --------------------------------------- foo.c(125) : Block 0x08219C40 status: Beginning: OK (allocated on foo.c:123, 6 bytes) End: Overflown (magic=0x2A8FCC00 instead of 0x2A8FCC84) 1 byte(s) overflown ---------------------------------------Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - The pval /zval Data Type
- InhaltsvorschauThroughout the PHP source code, you will see references to both
pvalandzval.pvalis the old name and is gradually being changed over tozvalin the PHP source code. They are the same thing and can be used interchangeably, butzvalshould be used in new code. Thepval/zvalis the basic data container in PHP. All data that is passed between the extension API and the user-level script is passed in this container. You can dig into the header files further yourself, but in simple terms, this container is a union that can hold a long, a double, a string including the string length, an array, or an object. The union looks like this:typedef union _zvalue_value { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; zend_object_value obj; } zvalue_value;The main things to learn from this union are that all integers are stored as longs, all floating-point values are stored in double-precision, and every string has an associated string length value, which, if properly checked everywhere, makes strings in PHP binary-safe. Strings should be null-terminated even if they represent binary data; otherwise, the Zend Engine will complain. Since most third-party libraries expect null-terminated strings, this shouldn't pose a problem.Along with this union, each container has a flag that holds the currently active type, whether it is a reference or not, and the reference count. So the actualpval/zvalstructure looks like this:struct _zval_struct { zvalue_value value; zend_uint refcount; zend_uchar type; zend_uchar is_ref; };Because this structure could change in future versions of PHP, be sure to use the various access functions and macros described in the following sections rather than directly manipulating the container.The most basic of theEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Parameter Handling
- InhaltsvorschauAs we learned in the previous section on the
pval/zvalcontainer, there are at least two ways to accept and parse arguments to PHP functions you write. We will concentrate on the higher-levelzend_parse_parameters( )function here.There are two versions of the function, prototyped like this in C:int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...); int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);They differ only in that theex, or expanded, version of the function contains aflagsparameter. The only flag currently supported isZEND_PARSE_PARAMS_QUIET, which inhibits warnings from supplying an incorrect number or type of arguments.Both parameter-parsing functions return eitherSUCCESSorFAILURE. The functions take any number of extra arguments (pointers to variables whose values are assigned by the parsing function). On failure thereturn_valueof the function is automatically set toFALSE, so you can simply return from your function on a failure.The most complex part of these functions is thetype_specstring you pass them. Here's the relevant part of our rot13 example:char *arg = NULL; int arg_len, argc = ZEND_NUM_ARGS( ); if (zend_parse_parameters(argc TSRMLS_CC, "s/", &arg, &arg_len) == FAILURE) return;We first get the number of arguments passed to this function by calling theZEND_NUM_ARGS( )macro. We pass this number along with atype_specstring of"s/"and then the address of achar *and the address of anint. The "s" in thetype_specstring indicates that we are expecting a string argument. For each string argument, the function fills in thechar *andintwith the contents of the string and the length of the string. The "/" character in thetype_specindicates that the string should be separated from the calling container. We did this in our rot13 example because we wanted to modify the passed string.The othertype_specspecifying characters are given in Table 14-2.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Returning Values
- InhaltsvorschauKnowing how to get data into a function is only one side of the problem—how do you get it out? This section shows you how to return values from an extension function, from simple strings or numbers all the way up to arrays and objects.Returning a value from a function back to the script involves populating the special, pre-allocated
return_valuecontainer. For example, this returns an integer:PHP_FUNCTION(foo) { Z_LVAL_P(return_value) = 99; Z_TYPE_P(return_value) = IS_LONG; }Since returning a single value is such a common task, there are a number of convenience macros to make it easier. The following code uses a convenience macro to return an integer:PHP_FUNCTION(foo) { RETURN_LONG(99); }TheRETURN_LONG( )macro fills in the container and immediately returns. If for some reason we wanted to populate thereturn_valuecontainer and not return right away, we could use theRETVAL_LONG( )macro instead.Returning a string is almost as simple with the convenience macros:PHP_FUNCTION(rt13) { RETURN_STRING("banana", 1); }The last argument specifies whether or not the string needs to be duplicated. In that example it obviously does, but if we had allocated the memory for the string using anemalloc( )orestrdup( )call, we wouldn't need to make a copy:PHP_FUNCTION(rt13) { char *str = emalloc(7); strcpy(str, "banana"); RETURN_STRINGL(str, 6, 0); }Here we see an example of doing our own memory allocation and also using a version of theRETURNmacro that takes a string length. Note that we do not include the terminatingNULLin the length of our string.The availableRETURN-related convenience macros are listed in Table 14-4.Table 14-4: RETURN-related convenience macros Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - References
- InhaltsvorschauReferences at the PHP source level map fairly straightforwardly onto the internals. Consider this PHP code:
<?php $a = "Hello World"; $b =& $a; ?>Here$bis a reference to the samezvalcontainer as$a. Internally in PHP, theis_refindicator is set to 1 for both thezvalcontainers, and the reference count is set to 2. If the user then does anunset($b), theis_refindicator on the$acontainer is set to 0. The reference count actually remains at 2, since the$asymbol table entry is still referring to thiszvalcontainer and thezvalcontainer itself also counts as a reference when the container is not a reference itself (indicated by theis_refflag being on). This may be a little bit confusing, but keep reading.When you allocate a newzvalcontainer usingMAKE_STD_ZVAL( ), or if you callINIT_PZVAL( )directly on a new container, the reference count is initialized to 1 andis_refis set to 0. If a symbol table entry is then created for this container, the reference count becomes 2. If a second symbol table alias is created for this same container, theis_refindicator is turned on. If a third symbol table alias is created for the container, the reference count on the container jumps to 3.Azvalcontainer can have a reference count greater than 1 withoutis_refbeing turned on. This is for performance reasons. Say you want to write a function that creates an n-element array and initializes each element to a given value that you provide, much like PHP'sarray_fill( )function. The code would look something like this:PHP_FUNCTION(foo) { long n; zval *val; int argc = ZEND_NUM_ARGS( ); if (zend_parse_parameters(argc TSRMLS_CC, "lz", &n, &val) == FAILURE) return; SEPARATE_ZVAL(&val); array_init(return_value); while(n--) { zval_add_ref(&val); add_next_index_zval(return_value, val); } }The function takes an integer and a rawzval(meaning that the second parameter to the function can be of any type). It then makes a copy of the passedEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Global Variables
- InhaltsvorschauTo access an internal PHP global variable from a function in your extension, you first have to determine what kind of global variable it is. There are three main types: SAPI globals, executor globals, and extension globals.SAPI is the Server Abstraction API. It contains any variables related to the web server under which PHP is running. Note that not all SAPI modules are related to web servers—the command-line version of PHP is one example. You can check which SAPI module you are running under by including SAPI.h and then checking
sapi_module.name:#include <SAPI.h> /* then in a function */ printf("the SAPI module is %s\n", sapi_module.name);See thesapi_globals_structin the main/SAPI.h file for a list of available SAPI globals. For example, to access thedefault_mimetypeSAPI global, you would use:SG(default_mimetype)Some elements of the SAPI globals structure are themselves structures with fields. For example, to access therequest_uri, use:SG(request_info).request_uriThese are runtime globals defined internally by the Zend executor. The most common EG variables aresymbol_table(which holds the main symbol table) andactive_symbol_table(which holds the currently visible symbols).For example, to see if the user-space$foovariable has been set, you could do:zval **tmp; if(zend_hash_find(&EG(symbol_table), "foo", sizeof("foo"), (void **)&tmp) == SUCCESS) { RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); } else { RETURN_FALSE; }Sometimes you need extension-wide global C variables. Since an extension has to be thread-safe, global variables are a problem. You can solve this problem by creating a structure—each would-be global variable becomes a field in the structure. When compiled as a thread-safe extension, macros take care of passing this structure around. When compiled as a non-thread-safe extension, the structure is a true global variable that is accessed directly. This way, the non-thread-safe builds do not suffer the slight performance penalty of passing around this global variable.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Creating Variables
- InhaltsvorschauAs we saw in the previous section, the
symbol_tableandactive_symbol_tablehashes contain user-accessible variables. You can inject new variables or change existing ones in these hashes.Here is a trivial function that, when called, creates$foowith a value of 99 in the currently active symbol table:PHP_FUNCTION(foo) { zval *var; MAKE_STD_ZVAL(var); Z_LVAL_P(var)=99; Z_TYPE_P(var)=IS_LONG; ZEND_SET_SYMBOL(EG(active_symbol_table), "foo", var); }That means that if this function was called from within a user-space function, the variable would be injected into the function-local symbol table. If this function was called from the global scope, the variable would, of course, be injected into the global symbol table. To inject the variable directly into the global symbol table regardless of the current scope, simply useEG(symbol_table)instead ofEG(active_symbol_table). Note that the global symbol table is not a pointer.Here we also see an example of manually setting the type of a container and filling in the corresponding long value. The valid container-type constants are:#define IS_NULL 0 #define IS_LONG 1 #define IS_DOUBLE 2 #define IS_STRING 3 #define IS_ARRAY 4 #define IS_OBJECT 5 #define IS_BOOL 6 #define IS_RESOURCE 7 #define IS_CONSTANT 8 #define IS_CONSTANT_ARRAY 9TheZEND_SET_SYMBOL( )macro is somewhat complex. It first checks to see if the symbol you are setting is already there and if that symbol is a reference. If so, the existing container is reused and simply pointed at the new data you have provided. If the symbol does not already exist, or it exists and it isn't a reference,zend_hash_update( )is called.zend_hash_update( )directly overwrites and frees the existing value. You can callzend_hash_update( )directly yourself if you want to and if you are more worried about performance than memory conservation. This is similar to the previous example, except that we force an overwrite in the symbol table usingEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Extension INI Entries
- InhaltsvorschauDefining php.ini directives (i.e., INI entries ) in an extension is easy. Most of the work involves setting up the global structure explained earlier in the section "Internal Extension Globals." Each entry in the INI structure is a global variable in the extension and thus has an entry in the global structure and is accessed using
FOO_G(my_ini_setting). For the most part you can simply comment out the indicated sections in the skeleton created by ext_skel to get a working INI directive, but we will walk through it here anyway.To add a custom INI entry to your extension, define it in your main foo.c file using:PHP_INI_BEGIN( ) STD_PHP_INI_ENTRY("foo.my_ini_setting", "0", PHP_INI_ALL, OnUpdateInt, setting, zend_foo_globals, foo_globals) PHP_INI_END( )The arguments to theSTD_PHP_INI_ENTRY( )macro are: entry name, default entry value, change permissions, pointer to change modification handler, corresponding global variable, global structure type, and global structure. The entry name and default entry value should be self-explanatory. The change permissions parameter specifies where this directive can be changed. The valid options are:-
PHP_INI_SYSTEM -
The directive can be changed in php.ini or in httpd.conf using the php_admin_flag/php_admin_value directives.
-
PHP_INI_PERDIR -
The directive can be changed in httpd.conf or .htaccess (if
AllowOverride OPTIONSis set) using the php_flag/php_value directives. -
PHP_INI_USER -
The user can change the directive using the
ini_set( )function in scripts. -
PHP_INI_ALL
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. -
- Resources
- InhaltsvorschauA resource is a generic data container that can hold any sort of data. An internal list mechanism keeps track of your resources , which are referenced through simple resource identifiers.Use resources in your extensions when the extension is providing an interface to something that needs cleanup. When the resource goes out of scope or your script ends, your destructor function for that resource is called, and you can free memory, close network connections, remove temporary files, and more.Here's a simple little example where we tie our resource to a trivial structure that contains only a string and an integer (
nameandage, in this case):static int le_test; typedef struct _test_le_struct { char *name; long age; } test_le_struct;The structure can contain anything: a file pointer, a database connection handle, etc. The destructor function for our resource looks like this:static void _php_free_test(zend_rsrc_list_entry *rsrc TSRMLS_DC) { test_le_struct *test_struct = (test_le_struct *)rsrc->ptr; efree(test_struct->name); efree(test_struct); }In yourMINIT( )function, add this line to register your destructor for thele_testresource:le_test = zend_register_list_destructors_ex(_php_free_test, NULL, "test", module_number);Now, here's a fictitiousmy_init( )function that initializes the data associated with the resource. It takes a string and an integer (nameandage):PHP_FUNCTION(my_init) { char *name = NULL; int name_len, age; test_le_struct *test_struct; if (zend_parse_parameters(ZEND_NUM_ARGS( ) TSRMLS_CC, "sl", &name, &name_len, &age) == FAILURE) { return; } test_struct = emalloc(sizeof(test_le_struct)); test_struct->name = estrndup(name, name_len); test_struct->age = age; ZEND_REGISTER_RESOURCE(return_value, test_struct, le_test); }And here's aEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Where to Go from Here
- InhaltsvorschauThis is by no means a complete reference to the entire extension and Zend APIs, but it should get you to the point where you can build a simple extension. Through the beauty of open source software, you will never lack example extensions from which to borrow ideas. If you need a feature in your extension that you have seen a standard PHP function do, simply go have a look at how it was implemented. All the built-in features in PHP use the same API.Once you have gotten to the point where you understand the basic aspects of the extension API and you have questions about more advanced concepts, feel free to post a message to the PHP developers' mailing list. The address is
internals@lists.php.net. You do not need to be subscribed to send a question to this list. Note that this list is not for questions about developing applications written in user-level PHP. This is a very technical list about the internals of PHP itself. You can search the archives of this list onhttp://www.php.netby entering a search string in the search field and selecting this list. You can subscribe to this list, and all the other PHP lists, athttp://www.php.net/support.php.Good luck with your PHP extension, and if you write something really cool, please tell us about it on the developers' list!Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Chapter 15: PHP on Windows
- InhaltsvorschauThere are many reasons to use PHP on a Windows system, but the most common is that you want to develop web applications on your Windows desktop. PHP development on Windows is just as do-able these days as it is on a Unix platform. PHP plays very well on Windows, and the supporting cast of server and add-on tools are all just as Windows-friendly. Having a PHP system working on any of its supported platforms is simply a matter of preference. Setting up and developing with a PHP environment on Windows is very easy to do, as PHP is extremely cross-platform friendly, and installation and configuration are becoming easier all the time.What can be confusing at first is the number of various configurations and choices available. There are many variants of the Windows operating system, and many web servers are available for those operating systems. PHP itself can run as either a dynamic link library (DLL) or a CGI script. This chapter explains how to install, configure, and make the best use of PHP on Windows systems. We will take one approach and follow it to its conclusion, keeping in mind that there are a number of different ways to arrive at the same destination. We also show how to take advantage of the features unique to the Windows platform—connecting to databases with ODBC and controlling Microsoft Office applications through COM.This section shows you how to install PHP on Windows. We cover the manual approach of configuring your web server to use PHP that gives you the most power and flexibility over your environment. There is also an installation wizard type of approach available from the PHP web site, but this currently does not allow you to install for the Apache web server, so we will not be covering that here.The most recent version of PHP can always be found at
http://www.php.net/downloads.php. While you could download the source and compile it yourself, chances are you don't have a compiler. Fortunately, the PHP downloads page has a binary distribution for Windows.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Installing and Configuring PHP on Windows
- InhaltsvorschauThis section shows you how to install PHP on Windows. We cover the manual approach of configuring your web server to use PHP that gives you the most power and flexibility over your environment. There is also an installation wizard type of approach available from the PHP web site, but this currently does not allow you to install for the Apache web server, so we will not be covering that here.The most recent version of PHP can always be found at
http://www.php.net/downloads.php. While you could download the source and compile it yourself, chances are you don't have a compiler. Fortunately, the PHP downloads page has a binary distribution for Windows.Download the latest Windows PHP distribution and extract it into a local directory. You'll need a program such as WinZip (http://www.winzip.com) to extract the ZIP file (honoring any folder definitions as you extract the contents). At the root level of the distribution is php.exe, which you can run from a command prompt to test and experiment with PHP. If you have PHP code in a file (e.g., test.php), you can run that code with:C:\> php -q test.phpThis is mostly beneficial to you as a testing feature, but with the assistance of the GDK library you can create fully localized (Windows desktop) systems.Once you have PHP on your local computer, the next thing to do is to configure it into a web server.The choices here are many. PHP can be run either as a standalone CGI script or linked directly into the server via the server's native Server API (SAPI). There's SAPI support for IIS, Apache, Netscape iPlanet, and AOLserver. PHP can even be configured to run as a Java servlet engine.Because of the rapid change in the development of PHP, it is always best to check with mail lists and online resources to determine the best configuration for your specific application. In general, the CGI version is more reliable, but it is slower than SAPI implementations because it has to be loaded with each request. SAPI implementations load once and create a new thread for each request. Although this is more efficient, the tight coupling with the server can bring the entire server down if there are memory leaks or other bugs with an extension. SAPI support on Windows is considered to be unstable as of the writing of this book, and hence is not recommended for production environments.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Writing Portable Code for Windows and Unix
- InhaltsvorschauOne of the main reasons for running PHP on Windows is to develop locally before deploying in a production environment. As many production servers are Unix-based, it is important to consider writing your applications so that they can operate on any operating platform with minimal fuss.Potential problem areas include applications that rely on external libraries, use native file I/O and security features, access system devices, fork or spawn threads, communicate via sockets, use signals, spawn external executables, or generate platform-specific graphical user interfaces.The good news is that cross-platform development has been a major goal in the development of PHP. For the most part, PHP scripts should be easily ported from Windows to Unix with few problems. However, there are several instances where you can run into trouble when porting your scripts. For instance, some functions that were implemented very early in the life of PHP had to be mimicked for use under Windows. Other functions may be specific to the web server under which PHP is running.To design with portability in mind, you may want to first test for the platform on which the script is running. PHP defines the constant
PHP_OS, which contains the name of the operating system on which the PHP parser is executing. Possible values for thePHP_OSconstant include"AIX","Darwin"(MacOS),"Linux","SunOS","WIN32", and"WINNT".The following code shows how to test for a Windows platform:<?php if (PHP_OS == "WIN32" || PHP_OS == "WINNT") { echo "You are on a Windows System"; } else { // some other platform echo "You are NOT on a Windows System"; } ?>PHP understands the use of either backward or forward slashes on Windows platforms, and can even handle paths that mix the use of the two slashes. As of Version 4.0.7, PHP will also recognize the forward slash when accessing Windows UNC paths (i.e.,Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Interfacing with COM
- InhaltsvorschauCOM allows you to control other Windows applications. You can send file data to Excel, have it draw a graph, and export the graph as a GIF image. You could also use Word to format the information you receive from a form and then print an invoice as a record. After a brief introduction to COM terminology, this section shows you how to interact with both Word and Excel.COM is a Remote Procedure Call (RPC ) mechanism with a few object-oriented features. It provides a way for the calling program (the controller) to talk to another program (the COM server, or object), regardless of where it resides. If the underlying code is local to the same machine, the technology is COM; if it's remote, it's Distributed COM (DCOM). If the underlying code is a DLL, and the code is loaded into the same process space, the COM server is referred to as an in-process, or inproc, server. If the code is a complete application that runs in its own process space, it is known as an out-of-process server, or local server application.Object Linking and Embedding (OLE) is the overall marketing term for Microsoft's early technology that allowed one object to embed another object. For instance, you could embed an Excel spreadsheet in a Word document. Developed during the days of Windows 3.1, OLE 1.0 was limited because it used a technology known as Dynamic Data Exchange (DDE) to communicate between programs. DDE wasn't very powerful, and if you wanted to edit an Excel spreadsheet embedded in a Word file, Excel had to be opened and run.OLE 2.0 replaced DDE with COM as the underlying communication method. Using OLE 2.0, you can now paste an Excel spreadsheet right into a Word document and edit the Excel data inline. Using OLE 2.0, the controller can pass complex messages to the COM server. For our examples, the controller will be our PHP script, and the COM server will be one of the typical MS Office applications. In the following sections, we will provide some tools for approaching this type of integration.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
- Interacting with ODBC Data Sources
- InhaltsvorschauODBC provides a data abstraction layer that is particularly useful for accessing some of Microsoft's products—such as Access, Excel, MS SQL Server, and others—through a common interface. In this section we show you how to configure a database for control via ODBC, and how to access an ODBC database from PHP.As with PEAR DB, you identify an ODBC database with a data source name (DSN). With ODBC, however, you must explicitly create the mapping between a DSN and its database. This section steps through configuring the built-in Access ODBC driver, but the process is similar for Excel, and other localized (smaller) databases.Open the Control Panels folder, and double-click on the ODBC Data Sources icon. The resulting dialog box is the ODBC Data Source Administrator. Select the System DSN tab, click the Add button, and select the driver for your target database. If the driver is not listed, you will need to obtain one from your database vendor. If you've installed Microsoft Office products on your computer, you will have all the drivers that you need to use Access as a primitive database. Figure 15-3 shows the addition of a System DSN for an existing Microsoft Access database.
Figure 15-3: Configuring a DSN for a Microsoft Access databasePress the Configure button in the top window to select a specific database file to use as the data source. In Figure 15-3, we've selected a workbook named contacts.mdb.Once the selection and naming process is complete for your ODBC data source, click the OK button; you will then see that your new data source has been added to the list of System DSNs. From then on, you are ready to use the DSN.Now that you have the connection established in the DNS interface you can use PHP to connect to this database and manipulate any information within it that you want (provided you have the correct creditentials).Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Appendix A: Function Reference
- InhaltsvorschauThis appendix describes the functions available in the standard PHP extensions. These are the extensions that PHP is built with if you give no
--withor--enableoptions to configure. For each function, we've provided the function signature, showing the data types of the various arguments and which are mandatory or optional, as well as a brief description of the side effects, errors, and returned data structures.Section A.1: PHP Functions by Category
Section A.2: Alphabetical Listing of PHP Functions
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - PHP Functions by Category
- InhaltsvorschauThis is a list of functions provided by PHP's built-in extensions, grouped by category. Some functions fall under more than one header.
array
array_merge_recursive
array_uintersect_assoc
array_chunk
array_multisort
array_uintersect_uassoc
array_combine
array_pad
array_unique
array_count_values
array_pop
array_unshift
array_diff
array_push
array_values
array_diff_assoc
array_rand
array_walk
array_diff_uassoc
array_reduce
array_walk_recursive
array_fill
array_reverse
arsort
array_filter
array_search
asort
array_flip
array_shift
compactEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Alphabetical Listing of PHP Functions
- Inhaltsvorschauabs
int abs(int number) float abs(float number)
Returns the absolute value of number in the same type (float or integer) as the argument.acosdouble acos(double value)Returns the arc cosine of value in radians.acoshdouble acosh(double value)Returns the inverse hyberbolic cosine of value.addcslashesstring addcslashes(string string, string characters)
Escapes instances of characters in string by adding a backslash before them. You can specify ranges of characters by separating them by two periods; for example, to escape characters betweenaandq, use"a..q". Multiple characters and ranges can be specified in characters. Theaddcslashes( )function is the inverse ofstripcslashes( ).addslashesstring addslashes(string string)Escapes characters in string that have special meaning in SQL database queries. Single quotes (''), double quotes (""), backslashes (\), and the NUL-byte ("\0") are escaped. Thestripslashes( )function is the inverse for this function.Arrayarray array([mixed ...])Creates an array using the parameters as elements in the array. By using the=>operator, you can specify specific indices for any elements; if no indices are given, the elements are assigned indices starting from 0 and incrementing by one. The internal pointer (seeEnde der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Appendix B: Extension Overview
- InhaltsvorschauIn addition to the functions from the standard extensions described in Appendix A, a number of optional extensions provide PHP with additional functionality. Generally, these optional extensions are interfaces to third-party code libraries. To use these functions, you need to install the libraries they depend on and recompile PHP with the appropriate compile-time directives. Alternately, if you are using a Windows version of PHP, you can simply find the extension name under the "Dynamic Extensions" section in the php.ini file and uncomment (remove the semicolon) the line for the extension you want. Restart Apache and you are ready to go.This chapter is intended as an indicative tour of the extensions provided with the PHP distribution, but not as a definitive reference to the functions provided by those extensions. Additional documentation for these extensions is available from the PHP web site
http://www.php.net.Starting with PHP 5, numerous extensions that were previously bundled with PHP are now distributed through PECL (the PHP Extension Community Library) athttp://pecl.php.netinstead of in the main PHP distribution.Section B.1: Optional Extensions Listing
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar. - Optional Extensions Listing
- InhaltsvorschauExtensions are listed in this appendix in alphabetical order by extension name. Where necessary, the appropriate PHP compile-time directive is given for adding the extension to your PHP installation. Due to the fluid nature of the Web, locations are not given for downloading third-party libraries necessary to run the extensions; check the PHP web site for current download locations.BCMath Arbitrary Precision MathematicsIf you need more precision in numbers than PHP provides by default with its built-in floating-point numbers, use the BCMath library. It provides support for arbitrary precision mathematics.To use the BCMath functions, you must compile PHP with the
--enable-bcmathdirective.CalendarThe calendar library provides a number of functions for converting between various calendar formats, including the Julian Day Count, the Gregorian calendar, the Jewish calendar, the French Republican Calendar, and Unix timestamp values.To use the calendar functions, you must compile PHP with the--enable-calendardirective.cPDFcpdf provides functions to create documents in Adobe's PDF format on the fly. clibpdf can create PDF files wholly in memory, without the use of temporary files, and can edit arbitrary pages within a multi-page document. See Chapter 10 for a detailed discussion of creating PDF documents.Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Zurück zu Programming PHP
