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.
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.
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".
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.
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.
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.
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.
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.
Img.:Client send request to the server
In the viewpoint of the client he gets the answer of 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
For multi line comments you cannot use ?> to stop
such a comment.
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.
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 //.
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.
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.
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.
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.
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.
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
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.
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.
Img.:Bits set for the integer value 50 (simplyfied)
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.
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 ?>
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.
$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 (expression) statement ?>
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.
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.
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 = 5 < 7; // is true $var = 10 <= 10; // is true $var = 9 > 9; // is false ?>
And there is the unequal operator != to check if two values are
not the same.
<?php $var = 10 != 10; // false $var = 0 != 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 == "5"; // is true $var = 5 === "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) ?>
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.
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.
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.
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.
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.
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.
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 ?>
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.
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).
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.
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_statement; condition; iteration_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 (start; cond; iter) { 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.
break - quits the current iteration and quits
the loop itself. It is like the condition to check evaluates to
false (which is maybe not the case).
<?php while (...) {
break; // ---> // | // V } // <--- ?>
continue - quits the current iteration and
jumps to the end of the loop body, but is still inside the loop.
For for loops the iteration statement gets executed (for
the next iteration) and for do-while loops the
condition expression get checked.
<?php // this is not an endless loop like expected do { // < - - - // | This way isn't used // | continue; // ---> - - // | // V Thats the way of continue; // <--- } while(false); ?>
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.
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.
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.
To get such a field use the array and brackets for the index.
<?php $arr = array("foo", "bar", "bla", 5.6, false, -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.
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.
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.
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 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(5 => "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 ?>
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.
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.
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.
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.
boolean
integer
float, double
String
Array
You haven't learned the following datatypes yet.
Object
Resource
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.
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
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
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.
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.
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.
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(4, 6, 10, -4); $ret = sort($a); $ret = sort($a, 4); $ret = sort($a, 0); sort($a, -400); sort($a, 9*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.
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(1, 2, 4), "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.
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(); ?>
/** * 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(); ?>
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 (1 == $imagetype) { } else if (4 == $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.
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.
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.
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.
In most cases the error is one line above. Beginners often miss the semicolon. For
the php interpreter the current statement isn't finished yet and he expect more
code which normaly fails.
In some cases the error is really in the given line number. You can write your whole
php code in one line, but this will help noone...
In rare cases the error is much more lines above. Sometimes you miss
a string delimiter (' or ") and php reads the following
php code as part of the string. He fails at this at the next beginning string delimiter
(which is maybe a new string) or if he reaches the file end. Then you get an error message
like Parse error: syntax error, unexpected $end in FILENAME on LASTLINE,
although the last line is (the ?>) is not the reason 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.
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.
Leave the php modus (?>).
Load and execute the file.
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: 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"; ?>
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.
At include 'functions.php'; the file
functions.php is searched first in the
directory where the config.php file is (in inc/).
As it isn't found there it searches at the location of the start script.
There is is the file and it gets loaded.
At include 'variables.php'; the file
is search first in the directory where the config.php file
is (in inc/). There it finds the variable and loads it.
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.
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.
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.
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
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.
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']; } ?>
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.
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.
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.
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.
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.
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.
First there exists the MySQL programm itself, its an application
like everything else. It implements a login system to access
the database.
Inside this MySQL program are the databases.
These are the workspaces for the users which logged into MySQL.
Depending on the login only a subset of databases can be used.
Typically each user have his own database. A costumer like
usr_123456 got a database usr_123456
to use.
Inside one database are the tables, which can
be added, changed or deleted. At the beginning this area is empty and
the user must create the tables. This can be done with
a administration programm or application like
phpMyAdmin.
This is a common webinterface for working with MySQL databases.
Each table got a list of columnnames and types and some
additional objects like primary key or
indexes.
Inside the tables are the rows.
Each row combine one column of the table with a value. As an example
a row combines the column Username with the value
Foobar and the column Birthday with
the value 1.1.1980. A second row will
assign the values UserBar and 2.4.1975 to
these columns, but both rows are in the same table.
This will look like this.
Example of the table
Username
Birthday
Foobar
1.1.1980
UserBar
2.4.1975
To you a MySQL database in php you need 4 values. You get them from the
administrator of your webserver.
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
Username - The username to login.
Password - The password to login.
Database - The database to work with.
A webapplication always use only one database.
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.
INT - This column type is used for
integer values. Rows often got an column for identification with the
name like ID. Such columns also have attributes like
PRIMAR KEY (each ID is unique) and AUTO_INCREMENT
(the next ID is created automatically).
VARCHAR(n) - This type is used for short strings.
The parameter n sets the maximum size of the string.
You use this type for saving short strings like usernames or
email addresses.
DATETIME - Is used to save a time value with
the full date. For a news script this type is used to save when
a news entry was written.
TEXT - This is used for longer strings like
news texts.
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.
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.
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.
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.
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.
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.
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.
id - A column for identify a news. This column got
the type INT and get the attributes
UNSIGNED, NOT NULL,
AUTO_INCREMENT and PRIMARY KEY.
title - This column got the title of the news and its type
is VARCHAR(100), 100 chars should be enought. As you must
supply a title it got the attribute NOT NULL.
added - The time when the news was added, so it must be got the
type DATETIME with the attribute NOT NULL.
Note that we cannot use the name date as it is a reserved keyword
in mysql (for the column type DATE).
content - This column got the real news text. As text
might be a better then TEXT is already a mysql keyword and shouldn't
be used as column name. We set the type of this column to TEXT as
we might want to add a longer news text. Again we use the NOT NULL
attribute.
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.
// 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.
// 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.
// 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.
// 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.
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.
id - The normal identification column with the type
INT.
added - The time when the entry was added. Type is
DATETIME.
author - The name of the user who added the entry.
A VARCHAR(50) should be enought.
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.
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.
$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}~', '0 ', $row['content']))); echo " </p>\n"; echo "</div>\n"; } } else { echo '<p 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.
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.
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.
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.
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.
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).
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'].
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 (1 === $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.
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.
// 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.
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 (1 === $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:
You create a template file. Put a php comment at the top so you know
which data should be send to the template file.
You create an include file. This returns the array for the filename
and the data array or a string with an error message.
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.
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.
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.
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 ?>
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(1, 2, 3); // 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