\chapter{PHP5}
\section{Introduction}
From \url{http://php.net/manual/en/intro-whatis.php}:
\begin{quotation}
PHP is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. 
\end{quotation}

A PHP script can either work without output to the browser, or, in the usual case, send HTML, CSS and JavaScript to the browser. In any case, the client never gets to see the underlying PHP code.

What do we need PHP for in the context of web application development?
\begin{enumerate}
\item To access a server database. For instance, if we want to build the next Amazon or YouTube, we need a database where we store the data of our gazillion users and products.
\item To access data on the Internet. Remember that for security reasons the browser is severely restricted in terms of accessing content from other sites (same-origin policy (cf. \ref{COR})).
In PHP, we have no limitations, unless our host provider has put some in place (which many of them do), in which case we switch to a host provider that does not.
\item To provide services that can be accessed from anywhere (see \ref{WAPI}).
\item To run code that we do not want the client to see and/or manipulate.
\end{enumerate}
A good way to start learning PHP is to use \url{https://www.phpschool.io}.

A PHP script has a file name ending with \verb|.php|. 

\section{Hello world}
%\begin{tiny}
%\begin{minted}[tabsize=2, linenos=true]{php}
%<?php
%	echo 'Hello world!';
%?>
%\end{minted}
%\end{tiny}
\url{\ftphp helloworld1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/helloworld1.php}}

\verb|echo| is a PHP construct (cf. \url{http://php.net/manual/en/function.echo.php}) that outputs all parameters. This script is parsed by the Apache PHP module and sends the string \verb|Hello world| to the browser. Try it out for yourself now! This is of course not a valid HTML5 page (run the validator), but still, the browser will display the text.

There's also a short form of echo:

\url{\ftphp helloworld2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/helloworld2.php}}

If we want to create a valid HTML5 page, we can mix HTML and PHP:

\noindent\url{\ftphp helloworldvalid.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/helloworldvalid.php}}

Take a look at the source in your browser. What do you see? What happened to the PHP part? How do you explain your observation?

From now on, the HTML part will not be shown, unless it is relevant.

\section{Logging}
In your home directory on Foxi you have a directory named \texttt{.log} where the PHP interpreter saves errors generated during the execution of your PHP scripts in a file called \texttt{error.log}. It's a good idea to monitor this file. To do this, log in to Foxi with Putty and run the command \texttt{tail -f /www/<class>/<username>/.log/error.log} (cf. appendix \ref{HOWTOFoxi}).

Use the PHP function \verb|error_log| (cf. \url{http://php.net/manual/en/function.error-log.php}) to log an error message to the log file.

It's a good idea to set the error level in your script to \verb|E_ALL| (cf. \url{http://php.net/manual/en/errorfunc.constants.php}), irrespective of the default setting on the server. This can be done using the \verb|error_reporting| function (cf. \url{http://php.net/manual/en/function.error-reporting.php}). 

Let's run an erroneous script and see what happens to our log file:

\noindent\url{\ftphp error1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/error1.php}}

\section{Variables and data types}
\url{\ftphp variables1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/variables1.php}}

This is a simple example of a variable declaration and usage. A variable is used to temporarily store data under a given name. Variable names in PHP are case-sensitive and always start with \verb|$| followed by a letter or an underscore, then any combination of letters, numbers and the underscore character (cf. \url{http://php.net/manual/en/language.variables.basics.php}). \verb|unset| is used to destroy a variable (cf. \url{http://php.net/manual/en/function.unset.php}).

Strings are embedded in \verb|""| or \verb|''| in PHP. There is however a significant difference between the two. Can you see it?

\begin{mdframed}[linecolor=red,linewidth=3pt, leftmargin=1cm,rightmargin=1cm]
PHP will not perform variable substitution inside single-quoted strings and won't even replace most escape characters (except \verb|\|). In double-quoted strings, PHP will replace variables with their current value.
\end{mdframed}

\noindent\url{\ftphp variables2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/variables2.php}}

Take a look at the output. What happened?

By adding \verb|s| we have changed the variable name and the PHP interpreter now looks for a variable named \verb|$fruits|, which does not exist (line 3). We can use braces to tell PHP where the variable name ends (cf. lines 4 and 5).

PHP has seven data types: \verb|string|, \verb|integer|, \verb|float|, \verb|boolean|, \verb|array|, \verb|object| and \verb|resource|. PHP considers \verb|0|, \verb|0.0|, \verb|""|, \verb|"0"| and  \verb|null| to be equivalent to \verb|FALSE| and everything else to be \verb|TRUE|.

From \url{https://php.net/manual/en/language.types.type-juggling.php}:
\begin{quote}
A variable's type is determined by the context in which the variable is used. That is to say, if a string value is assigned to variable \verb|$var|, \verb|$var| becomes a string. If an integer value is then assigned to \verb|$var|, it becomes an integer. 
\end{quote}
With \verb|settype| (\url{https://php.net/manual/en/function.settype.php}) we can change the type of a variable explicitly.

\subsection{String concatenation}
Strings can be concatenated using the \verb|.| operator.

\noindent\url{\ftphp strings1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/strings1.php}}

\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex1.php}

Write a PHP script that stores your name in a variable and displays the text \texttt{My name is } followed by your name followed by a colon. Your script may not use more than one echo statement. The generated page needs to be HTML5 validated.
\end{Exercise}

\section{Heredoc}
To deal with long strings, we can use heredoc syntax (cf. \url{http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc}). It allows us to define our own string delimiter so that we do not have to use quotes. The string delimiter, \verb|EOT| in our example, needs to be in the first column on a line by itself. Spaces or tabs are not allowed.

\noindent\url{\ftphp heredoc1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/heredoc1.php}}

\section{Constants}
Constants are like variables, except that once they are defined, they cannot be undefined or changed. Their name does not start with a \verb|$|. They are defined using the \texttt{define} (cf. \url{http://php.net/manual/en/function.define.php}) function:

\noindent\url{\ftphp constants1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/constants1.php}}

The \verb|define()| function can be given a third parameter to turn off case-sensitivity:

\noindent\url{\ftphp constants2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/constants2.php}}

Constants are automatically global across the entire script, unlike variables.

\section{Comments}
\verb|#| or \verb|//| tell PHP to ignore the rest of the line.
For multi line comments, use \verb|/* */|.

\noindent\url{\ftphp comments1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/comments1.php}}

If we want to enable automatic documentation generation, we can use PHPDoc (\url{https://en.wikipedia.org/wiki/PHPDoc}).

\section{Operators}
Detailed information and examples related to operators can be found at \url{http://php.net/manual/en/language.operators.php} and \url{http://www.w3schools.com/php/php_operators.asp}.

\begin{mdframed}[linecolor=red,linewidth=3pt, leftmargin=1cm,rightmargin=1cm]
Pay particular attention to the equal operator. A single \verb|=| is used to assign the right value to the left operand. \verb|==| and \verb|===| are comparison operators. The former may perform an implicit type conversion whereas the latter will not.
\end{mdframed}

\noindent\url{\ftphp equal_operator.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/equal_operator.php}}

When combining several operators, it is helpful to know their precedence, which is clarified at \url{http://php.net/manual/en/language.operators.precedence.php}.

\subsection{\texttt{@} operator}
If we put this operator in front of an expression in PHP, any error messages that might be generated by that expression will be ignored (cf. 
\url{http://php.net/manual/en/language.operators.errorcontrol.php}).

\section{Conditional statements}
\subsection{\texttt{if else}}
We can take decisions based on conditions.

\noindent\url{\ftphp conditionalstatement1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/conditionalstatement1.php}}

\subsection{Ternary operator}
Like JavaScript, PHP provides a shortcut version of \texttt{if else}:

\noindent\url{\ftphp conditionalstatement2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/conditionalstatement2.php}}

\section{Loops}
\subsection{\texttt{for}}
The for loop consists of three parts: the declaration, the condition and the action. The declaration sets the variable \verb|$i| to 1. The condition checks whether \verb|$i| is less than 10. As long as the condition is true, we increment \verb|$i| by 1 after every iteration.

\noindent\url{\ftphp for1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/for1.php}}

\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex2.php}

Write a script that calculates the sum of all integers between 1 and the value of a random integer variable \texttt{\$limit}. Use the \texttt{rand} function (\url{http://php.net/manual/en/function.rand.php}).
\end{Exercise}

\subsection{\texttt{while}}
We need to verify that a loop terminates, i.e. that there will be a time, where the condition won't be true anymore. Otherwise, we end up with an infinite loop, meaning our program will never terminate!

\noindent\url{\ftphp while1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/while1.php}}
\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex3.php}

Write a loop that generates a new random integer from [23, 77] and prints the number on a separate line during each iteration. The loop stops if the number is a multiple of 13.
\end{Exercise}

\subsection{\texttt{break} and \texttt{continue}}
\verb|break| exits the loop immediately. \verb|continue| skips the rest of the current iteration and goes on to the next.

\noindent\url{\ftphp breakandcontinue1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/breakandcontinue1.php}}

\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex4.php}

Modify exercise 3 so that the loop skips all iterations where the random number is a multiple of 2.
\end{Exercise}

\subsection{Nested loops}
\noindent\url{\ftphp nestedloop1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/nestedloop1.php}}

\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex5.php}

Print a matrix of (x, y) coordinates, x from [1, 50] and y from [10, 20].
\end{Exercise}

\section{Arrays}
An array is a container. You can use it to store other variables inside, which are called \emph{elements}. Each element has:
\begin{enumerate}
\item a \emph{key}, which can be an integer or a string.
\item a \emph{value}, which can be any data type or a variable.
\end{enumerate}

We can create an array using the \verb|array| function or using the \verb|[]| operator.
We can also add elements to an array using \texttt{[]}.

The function \texttt{print\_r} (\url{http://php.net/manual/en/function.print-r.php}) is very helpful to visualize the contents of an array. To optimize the readability of the output, we can set the function's second parameter to \texttt{TRUE} and embed it in a \texttt{pre} tag.

\noindent\url{\ftphp arrays1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/arrays1.php}}

The function \texttt{count} (\url{http://php.net/manual/en/function.count.php}) (or \verb|sizeof|, which is just an alias of \verb|count|) tells us the number of elements in an array.

\texttt{in\_array} (\url{http://php.net/manual/en/function.in_array.php}) returns \texttt{TRUE} if a given element is in the array, \texttt{FALSE} otherwise. Note that if we set the third parameter to \verb|TRUE|, it will check both the type and value of the element.

The elements of an array variable are variables too, so we can delete them using \verb|unset|. However, this will create an empty space in our array, although the length will be correct. To completely remove an array element, we can use \verb|array_splice| (\url{http://php.net/manual/en/function.array-splice.php}).

If we want to assign the elements of an array to individual variables, the \verb|list| (\url{http://php.net/manual/en/function.list.php}) command comes in handy.

PHP offers a number of useful functions to change the internal pointer of an array using \verb|reset|, \verb|current|, \verb|each|, \verb|end|, \verb|next| and \verb|prev|. See \url{http://php.net/manual/en/function.reset.php} for usage examples.

To get the full list of PHP array functions, see \url{http://php.net/manual/en/ref.array.php}.

Study the examples at \url{http://php.net/manual/en/language.types.array.php}.

Take your time to study the following examples:

\noindent\url{\ftphp arrays2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/arrays2.php}}
%\addtocounter{exc}{1}
\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex6.php}

Write a PHP script that stores 5 integer values in an array, displays the array and then displays a value randomly selected from the array.
\end{Exercise}

\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex7.php}

Write a script that stores the words "sunshine", "rain" and "cloudy" in an array. It then draws a random integer from [0, 2] and displays the text "Today's weather forecast: " followed by the element at the random array position. It then displays one of the following comments, depending on the weather forecast: "Beautiful day ahead!", "Never mind..." or "It could be worse...".
\end{Exercise}

\subsection{Associative arrays}
In addition to specifying array values, we can also specify our own keys:

\noindent\url{\ftphp arrays3.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/arrays3.php}}
%\addtocounter{exc}{1}
\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex8.php}

Write a PHP script that stores the grades of 3 students, so that each grade is associated with the corresponding student's name. Display the array.
\end{Exercise}

\subsection{Looping through arrays with \texttt{foreach}}
\verb|foreach| allows us to iterate through an array or object (we'll get to objects later on).

\noindent\url{\ftphp foreach1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/foreach1.php}}

\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex9.php}

Create an associative array that uses the names of a few dogs (at least 3) as the keys and the dogs' ages as values (the age is a random integer from [1, 15]). Display the array, loop through the array and print the name of each dog followed by its age.
\end{Exercise}

\subsection{Multidimensional arrays}
Array elements can be arrays, so we can create multidimensional arrays.

\noindent\url{\ftphp arrays4.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/arrays4.php}}

\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
Write a script that stores the following collection of software titles and displays them nicely:

\noindent\url{\ftexphp ex10.php}
\begin{tabular}{|l|l|l|}
\hline
\multirow{7}{*}{Microsoft} & \multirow{4}{*}{Office} & Word \\
 & & Excel \\
 & & Access \\
 & & Powerpoint \\ \cline{2-3}
 & \multirow{3}{*}{OS} & Windows 7 \\
 & & Windows 8 \\
 & & Windows 8.1 \\ \hline
\multirow{3}{*}{Mozilla} & \multirow{2}{*}{Desktop} & Firefox \\
 & & Thunderbird \\ \cline{2-3}
 & \multirow{2}{*}{OS} & Firefox OS \\
 & & Top Secret \\ \hline
\end{tabular}
\end{Exercise}

\section{Including external scripts}
PHP provides four keywords to include external scripts:

\begin{tabu}{|l|X|}
\hline
\everyrow{\tabucline[0.5pt]{-}}
 \texttt{include} & \url{http://php.net/manual/en/function.include.php} \\
  \texttt{include\_once} & \url{http://php.net/manual/en/function.include-once.php} \\
  \texttt{require} & \url{http://php.net/manual/en/function.require.php} \\ \texttt{require\_once} & \url{http://php.net/manual/en/function.require-once.php}
\end{tabu}
\vspace*{\baselineskip}

\noindent\url{\ftphp include1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/include1.php}}

\noindent\url{\ftphp includeme.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/includeme.php}}

\section{Functions}
Functions (cf. \url{http://php.net/manual/en/language.functions.php}) are a key element of effective code reuse and maintainable software development. You may not redefine PHP's built-in functions.

\noindent\url{\ftphp functions1a.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/functions1a.php}}

A function can return a value using the \verb|return| keyword. \textbf{The \texttt{return} statement terminates the function}:

\noindent\url{\ftphp functions1b.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/functions1b.php}}

A function can of course also return HTML. Let's create a function that returns an HTML table filled with the data from a one- or two-dimensional array:

\noindent\url{\ftphp functions2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/functions2.php}}

\label{ex11}\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex11.php}

Write a function \texttt{sumArray} that returns the sum of all elements (we assume they are numbers) contained in an array passed as parameter.
\end{Exercise}

\subsection{Recursive functions}
The factorial problem can be solved very elegantly using a recursive function call:

\noindent\url{\ftphp functions3.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/functions3.php}}

\subsection{\label{variableScope}Variable scope}
Cf. \url{https://secure.php.net/manual/en/language.variables.scope.php}.

\subsubsection{\texttt{global}}
Variables declared outside of functions and classes are global, i.e. they are available everywhere in the script except within functions and classes. Inside functions we can use the \verb|global| keyword to access global variables. 

Examples:

\noindent\url{\ftphp variablescope1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/variablescope1.php}}

\noindent\url{\ftphp variablescope2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/variablescope2.php}}

\subsubsection{\texttt{static}}
A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope. 

Example:

\noindent\url{\ftphp variablescope3.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/variablescope3.php}}

\subsection{Default values for function parameters}
We can specify default values for parameters in case the caller does not pass them:

\noindent\url{\ftphp functions4.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/functions4.php}}

\subsection{Passing values by reference}
If we want a function to be able to change the value of a parameter, so that the changed value is available to the caller, we pass the parameter by reference by prepending a \texttt{\&} to the parameter name in the function prototype:

\noindent\url{\ftphp functions5.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/functions5.php}}

\subsection{Using a variable number of parameters}
We can write functions that accept a variable number of parameters using \texttt{func\_num\_args} (cf. \url{http://php.net/manual/en/function.func-num-args.php}), \texttt{func\_get\_args} (cf. \url{http://php.net/manual/en/function.func-get-args.php}) or \texttt{func\_get\_arg} (cf. \url{http://php.net/manual/en/function.func-get-arg.php}):

\noindent\url{\ftphp functions6.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/functions6.php}}

\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex12.php}

Write a function \texttt{sum} that returns the sum of all the numbers passed as parameters. The user can pass as many parameters as he/she likes.
\end{Exercise}

\subsection{Anonymous functions}
Anonymous functions, also known as closures, can be used for callbacks and other purposes (cf. \url{http://php.net/manual/en/functions.anonymous.php}).

\noindent\url{\ftphp closure1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/closure1.php}}

\section{Superglobals}
There are nine superglobal arrays that we can use anywhere in our scripts (cf. \url{http://w3schools.com/php/php_superglobals.asp}).
\subsection{\texttt{\$\_GET}}
This array contains all variables sent via a HTTP GET request, either through an HTML form or directly through the URL (cf. \ref{GET}). %Look at the invoking URL in the following example!
%\\{\scriptsize
%\href{\ftphp get1.php?user=Otto}{\parbox{\textwidth}{\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/get1.php}}}}
%\\{\scriptsize
%\href{\ftphp get1.html}{\parbox{\textwidth}{\inputminted[tabsize=2, linenos=true]{html}{PHP5/get1.html}}}}

\subsection{\texttt{\$\_POST}}
This array contains all variables sent via a HTTP POST request, either through an HTML form or directly through an HTTP request (cf. \ref{POST}).

\subsection{\texttt{\$\_FILES}}
Contains all variables sent via a HTTP POST file upload.

\begin{mdframed}[linecolor=red,linewidth=3pt, leftmargin=1cm,rightmargin=1cm]
{\textbf{Allowing anyone to upload files to a server represents a major security risk, as the uploaded file can be executed by everyone who has access to the directory. Only allow file upload for authenticated users and only for those file types that you want.}}
\end{mdframed}

\noindent\url{\ftphp upload.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/upload.php}}

\noindent\url{\ftphp upload1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/upload1.php}}

For an excellent more in-depth example, study \url{http://w3schools.com/php/php_file_upload.asp}.

\subsection{\texttt{\$\_COOKIE}}
Contains all variables sent via HTTP cookies. See \ref{cookies}.

\subsection{\texttt{\$\_REQUEST}}
Contains all variables sent via HTTP GET, HTTP POST and HTTP cookies unless there are variables with the same name, in which case some are overwritten (cf. \url{http://php.net/manual/en/ini.core.php#ini.request-order}). It is preferable to use \texttt{\$\_GET}, \texttt{\$\_POST} or \texttt{\$\_COOKIE} directly instead of \texttt{\$\_REQUEST}.

\subsection{\texttt{\$\_SESSION}}
Contains all variables stored in a user's session (server-side data store).  See \ref{cookies}.

\subsection{\texttt{\$\_SERVER}}
Contains all variables set by the web server or other sources that relate directly to the execution of the script.

\noindent\url{\ftphp SERVER.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/SERVER.php}}

\subsection{\texttt{\$\_ENV}}
Contains all variables passed to the current script via the environment, e.g. when the script has been called from a shell instead of via the web server. 
\noindent\url{\ftphp ENV.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/ENV.php}}

\subsection{\texttt{\$GLOBALS}}
\noindent\url{\ftphp GLOBALS.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/GLOBALS.php}}

\section{Useful PHP functions}
\subsection{\texttt{isset}}
\url{http://php.net/manual/en/function.isset.php}

Determine if a variable is set and not \texttt{NULL}. A good list of examples can be found by clicking on the section title.

\subsection{\label{strlen}\texttt{strlen}}
\url{http://php.net/manual/en/function.strlen.php}

Get the length of a string:

\noindent\url{\ftphp strlen1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/strlen1.php}}

\subsection{\texttt{exit} or \texttt{die}}
These two perform exactly the same job, i.e. output a message and terminate the current script. Both are not really functions but language constructs. See \url{http://php.net/manual/en/function.exit.php} and \url{http://php.net/manual/en/function.die.php}.

\subsection{\label{header}\texttt{header}}
\url{http://php.net/manual/en/function.header.php}

Sends a raw HTTP header, often used to redirect the browser to another page. The function must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP.

\noindent\url{\ftphp header1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/header1.php}}

\noindent\url{\ftphp header2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/header2.php}}

\subsection{\texttt{mt\_rand}}
\url{https://secure.php.net/manual/en/function.mt\-rand.php}

Generates a random integer. Minimum and maximum can be specified.

\subsection{\label{PHPeval}\texttt{eval}}
\url{http://php.net/manual/en/function.eval.php}

Evaluates a given string as PHP code.

Example:

\noindent\url{\ftphp eval1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/eval1.php}}

\subsection{\label{dirname}\texttt{dirname}}
\url{http://php.net/manual/en/function.dirname.php}

Given a string containing the path of a file or directory, this function will return the parent directory's path.

\noindent\url{\ftphp dirname1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/dirname1.php}}

\subsection{\texttt{number\_format}}
\url{http://php.net/manual/en/function.number-format.php}

Excellent description and examples at the usual place.

\subsection{\texttt{strpos}}
\url{http://php.net/manual/en/function.strpos.php}

\subsection{\texttt{implode}}
\url{http://php.net/manual/en/function.implode.php}

\subsection{\texttt{explode}}
\url{http://php.net/manual/en/function.explode.php}

\subsection{\texttt{filter\_var}}
\url{http://php.net/manual/en/function.filter-var.php}

This function filters a variable with a specified filter.
\noindent\url{\ftphp filtervar1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/filtervar1.php}}

\subsection{\texttt{preg\_match}}
\url{http://php.net/manual/en/function.preg-match.php}

\subsection{\texttt{sprintf}}
\url{http://php.net/manual/en/function.sprintf.php}

\subsection{\texttt{printf}}
\url{http://php.net/manual/en/function.printf.php}

Study this example: \url{http://w3schools.com/php/showphp.asp?filename=demo_func_string_printf4}

\subsection{\texttt{list}}
\url{http://php.net/manual/en/function.list.php}

\subsection{\texttt{ini\_set}}
\url{http://php.net/manual/en/function.ini-set.php}

\subsection{\texttt{rawurlencode}}
Encode given string according to \url{http://www.faqs.org/rfcs/rfc3986.html}, cf. \url{http://php.net/manual/en/function.rawurlencode.php}.

\subsection{\texttt{htmlspecialchars}}
Convert special characters to HTML entities, cf. 
\url{http://php.net/manual/en/function.htmlspecialchars.php}.

\subsection{\texttt{htmlentities}}
\url{http://w3schools.com/php/func_string_htmlentities.asp}

\subsection{\texttt{html\_entity\_decode}}
\url{http://w3schools.com/php/func\_string\_html\_entity\_decode.asp}

\subsection{\texttt{serialize} and \texttt{unserialize}}
In order to store arrays or objects in a database without loss of type and structure we can use the \texttt{serialize} function (cf. \url{http://php.net/manual/en/function.serialize.php}). 
We can use \texttt{unserialize} to restore the saved structure. In the databse it is important to use a binary column type such as a \texttt{BLOB} in MySQL to store the object.

\subsection{\texttt{getdate}}
\verb|getdate| returns an associative array containing the date information of the timestamp, or the current local time if no timestamp is given (cf. \url{https://secure.php.net/manual/en/function.getdate.php}).

\subsection{\texttt{date}}
\verb|date(format)| gives us a string with the current date formatted according to the given format string (cf. \url{http://php.net/manual/en/function.date.php}). We should call \verb|date_default_timezone_set| (cf. \url{http://php.net/manual/en/function.date-default-timezone-set.php}) to set the correct timezone beofre calling \verb|date|. The list of supported timezones can be found at \url{http://php.net/manual/en/timezones.php}.
Example:

\noindent\url{\ftphp date1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/date1.php}}

\subsection{\texttt{nl2br}}
\verb|nl2br| inserts HTML line breaks before all newlines in a string (cf. \url{http://php.net/manual/en/function.nl2br.php}). This function is particularly useful for chat boxes, see \ref{Test_message_board} for a usage example.

\subsection{Executing system commands}
PHP offers several options to execute system commands:
\begin{enumerate}
\item \verb|exec|, cf. \url{http://php.net/manual/en/function.exec.php}.
\item \verb|system|, cf. \url{http://php.net/manual/en/function.system.php}.
\item \verb|shell_exec|, cf. \url{http://php.net/manual/en/function.shell-exec.php}.
\item Backtick operator, cf. \url{http://php.net/manual/en/language.operators.execution.php}.
\item \verb|passthru|, cf. \url{http://php.net/manual/en/function.passthru.php}.
\item \verb|proc_open|, cf. \url{http://php.net/manual/en/function.proc-open.php}.
\end{enumerate}
For user input you should apply \verb|escapeshellarg| before using any of the above functions (cf.
\url{http://php.net/manual/en/function.escapeshellarg.php}).

\subsection{Password hashing}
From \url{http://php.net/manual/en/faq.passwords.php}:
\begin{quotation}
Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be very fast and efficient. With modern techniques and computer equipment, it has become trivial to "brute force" the output of these algorithms, in order to determine the original input.
\end{quotation}
Therefore, it is important to use the \verb|password_hash| (\url{http://php.net/manual/en/function.password-hash.php}) and \verb|password_verify| (\url{http://php.net/manual/en/function.password-verify.php}) functions, like so:

\noindent\url{\ftphp password_hash1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/password_hash1.php}}

\section{Regular expressions}
Regular expressions can be used to replace text in, test for a pattern in or extract a substring from a string. They are very flexible and powerful and can be used in many programming languages, including JavaScript and PHP.

\url{http://regexper.com}
\url {http://www.regextester.com}

\subsection{Syntax}

\subsection{Regex usage in JavaScript}

\subsection{Regex usage in PHP}

\section{\label{PHPForms}Forms}
HTML forms are the main mechanism used to transfer data from the client to the server. The HTTP (cf. \url{http://en.wikipedia.org/wiki/HTTP}) protocol provides two methods to send form data to the server: POST and GET.

\subsection{\label{POST}POST}
The POST method transmits form data within the HTTP request. It is the recommended method to transmit data to the server:

\noindent\url{\ftphp forms1.html}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html}{PHP5/forms1.html}}

\noindent\url{\ftphp forms1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/forms1.php}}

\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex13.php}

Write a login form that verifies the user name is "T2IF" and the password "PHP". The latter should not be displayed in the form.
\end{Exercise}

\subsection{\label{GET}GET}
The GET method transmits data within the URL, i.e. visible to the world! Take a look at the URL after submitting the form:

\noindent\url{\ftphp forms2.html}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html}{PHP5/forms2.html}}
\noindent\url{\ftphp forms2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/forms2.php}}

This is about as insecure as it gets. It should only be used to request information from a server, for instance from Yahoo:
\noindent\url{\ftphp get1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/get1.php}}

Note that we can use hyperlinks instead of forms to submit data via GET. This can be useful, for instance, to create a simple page navigation:

\noindent\url{\ftphp get2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/get2.php}}

\subsection{Form validation}
Study \url{http://w3schools.com/php/php_form_validation.asp}. We should not simply accept any input the user submits using a form. In order to avoid an attack on our application and to prevent invalid data from entering our database, we need to perform an in-depth check.
To check whether a value has been entered in a text box, use \href{http://php.net/manual/en/function.strlen.php}{\texttt{strlen}} (cf. \ref{strlen}) instead of \href{http://php.net/manual/en/function.empty.php}{\texttt{empty}}. If the user enters 0, \texttt{empty} will return true:

\noindent\url{\ftphp formvalidation1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/formvalidation1.php}}

\subsubsection{Number validation}
If we want to accept decimal, hexadecimal, binary, octal and exponential notation numbers, \href{php.net/manual/en/function.is-numeric.php}{\texttt{is\_numeric}} is the way to go.
If we only want integers larger than or equal to 0, we use \href{php.net/manual/en/function.ctype-digit.php}{\texttt{ctype-digit}}.
To accept negative and positive integers, we can convert the string to an integer using \href{php.net/manual/en/function.intval.php}{\texttt{intval}} and then back to a string and check whether we get the original string. The same procedure works for decimals, where we convert the string to a float using \href{php.net/manual/en/function.floatval.php}{\texttt{floatval}}. \\

\noindent\url{\ftphp numbervalidation1.php}
{\scriptsize
\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/numbervalidation1.php}}

\subsubsection{\label{EmailValidation}Email validation}
We can use a simplistic regular expression (cf. "Head First PHP \& MySQL" first edition p. 600):

\noindent\url{\ftphp emailvalidation1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/emailvalidation1.php}}

The safest way of handling email validation is probably to use Carl Henderson's \texttt{is\_valid\_email\_address} function from \url{http://code.iamcal.com/php/rfc822} followed by a call to \href{http://php.net/manual/en/function.checkdnsrr.php}{\texttt{checkdnsrr}}.
\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex14.php}

Write a script that reads in an email address via a form and validates it, i.e. displays a message telling the user whether the email address is valid or not. Use Carl Henderson's as well as the \texttt{checkdnsrr} functions.
\end{Exercise}

\subsubsection{Drop-down lists}
\noindent\url{\ftphp formvalidation2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/formvalidation2.php}}

If we allow multiple selections, we need to add \verb|[]| to the name of the selection so that the values are available as an array in PHP.

\noindent\url{\ftphp formvalidation3.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/formvalidation3.php}}

\subsubsection{Multiple choice forms}
%\\{\scriptsize
%\href{\ftphp formvalidation2.php}{\parbox{\textwidth}{\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/formvalidation2.php}}}}

\noindent\url{\ftphp formvalidation4.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/formvalidation4.php}}

\subsubsection{Preventing form hijacking}
What runs on the client side is out of our control. Thus we cannot prevent a malicious user from trying to hijack our application in order to inflict damage. What we can do, is to make our scripts as safe as possible in order to deal with attacks. How can our forms be attacked? Let's take the previous example of the multiple choice form. The way we have implemented it so far, an attacker can simply write and run a script such as the following:

\noindent\url{\ftphp formvalidation5.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/formvalidation5.php}}

This is a harmless example, but a real attacker would obviously submit code in the value field that would try to hijack our server and/or database or perform some other mischief.

\subsection{Using arrays to submit large volumes of data to the server}
If we want to send large quantities of data to the server via a form, arrays can be very useful:

\noindent\includegraphics[width=\linewidth]{forms_arrays1}

\noindent\url{\ftphp forms_arrays1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/forms_arrays1.php}}

\subsection{Using form fields to transfer data between pages}
The safer way to transfer data between pages is to use sessions, as session data is stored on the server and therefore cannot be manipulated by the user.
An easy, though not recommended, way to transfer data between pages is using input fields. In addition to simple data structures such as numbers or text, we can also  transfer multidimensional arrays.

A simple application example is the creation of a list:

\noindent\url{\ftphp hiddenfields1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/hiddenfields1.php}}

Let's say we want a page that allows us to create the name list for our sports club. Using input fields, we could do this as follows:

\noindent\url{\ftphp hiddenfields2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{html+php}{PHP5/hiddenfields2.php}}

If we want to transfer information between pages without the user seeing it (unless he/she uses the console or some other tool), we can hide the input fields.

\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex15.php}

Write a grade spreadsheet that allows the user to enter 3 integers. After submission, the script displays the list of all the number triples entered so far and the average for each triple is shown at the end of the line. In addition, the average of all the averages is displayed.
\end{Exercise}

\label{cookies}\section{Cookies and sessions}
HTTP is a stateless protocol, thus any data is forgotten when the page has been sent to the client and the connection is closed. To store client-specific data, we can use cookies, sessions, databases, files, etc. Here we'll take a closer look at cookies and sessions.
%\texttt{htmlentities(\$string, ENT\_HTML5, "UTF-8")}

\subsection{Cookies}
Cookies are bits of information that are stored locally in files by the client browser (cf. \url{http://php.net/manual/en/function.setcookie.php} and \url{http://w3schools.com/php/func_http_setcookie.asp}).

From php.net:
\begin{quote}
setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, \textbf{cookies must be sent before any output from your script} (this is a protocol restriction). This requires that you place calls to this function prior to any output, including <html> and <head> tags as well as any whitespace. 
\end{quote}

The next time the user points his browser to the same page, assuming that the cookie's lifetime has not expired and the user has not deleted the cookie, which is easy to do using the browser options, the cookie will be automatically sent to the server. Thus, cookies are a mechanism to store data persistently on the client side, i.e. the information does not disappear on page reload or when the client browser is shut down.

As a simple example, let's store a user name in the client's browser for the duration of 3 days (3 days * 24 hours * 60 minutes * 60 seconds -> 259200 seconds):

\noindent\url{\ftphp cookies1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/cookies1.php}}

\noindent\url{\ftphp cookies2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/cookies2.php}}

Now when we visit this page again, we can see that the cookie is indeed sent to the server:

\noindent\includegraphics{cookie1.png}
\vspace*{\baselineskip}

To delete a cookie before its expiration time, we can set its value to empty and its expiration time in the past:

\noindent\url{\ftphp cookies3.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/cookies3.php}}

Changes made to cookies are only visible the next time our script gets executed. Therefore, this won't work as expected:

\noindent\url{\ftphp cookies4.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/cookies4.php}}

If we want to use them to store confidential data, we must use strong encryption. If we want to store the user's password in encrypted form, so that nobody, including ourselves, can get the unencrypted password, we can proceed as follows:

\noindent\url{\ftphp cookies5.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/cookies5.php}}

If we want to store encrypted information that we can decrypt, we can use \url{http://php.net/manual/en/function.mcrypt-encrypt.php}.

\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex16.php}

Write a script that sets a cookie with a value of your choice. The cookie expires after 2 minutes and is only active in the directory \texttt{cookies} and its subdirectories. The cookie will only be sent via SSL. Write a test script that proves that the cookie will only be active in the \texttt{cookies} directory tree (you may want to use the \texttt{dirname} (cf. \ref{dirname}) or the \texttt{header} function (cf. \ref{header})).
\end{Exercise}

\subsection{Sessions}
If we do not want our data to be accessible outside of our server, we can use sessions. Sessions serve to maintain visitor-specific state between page requests. Here the description from \url{https://secure.php.net/manual/en/intro.session.php}:
\begin{quote}
A visitor accessing your web site is assigned a unique id, the so-called session id. This is either stored in a cookie on the user side or is propagated in the URL.
The session support allows you to store data between requests in the \$\_SESSION superglobal array. When a visitor accesses your site, PHP will check automatically (if session.auto\_start is set to 1) or on your request (explicitly through session\_start() or implicitly through session\_register()) whether a specific session id has been sent with the request. If this is the case, the prior saved environment is recreated.
\end{quote}

\begin{mdframed}[linecolor=red,linewidth=3pt, leftmargin=1cm,rightmargin=1cm]
{\textbf{To use cookie-based sessions, \texttt{session\_start()} must be called BEFORE sending anything to the browser.}}
\end{mdframed}
%\fbox{\parbox{\textwidth}{\textbf{To use cookie-based sessions, session\_start() must be called before outputing anything to the browser.}}}

Let's look at a very basic, though insecure, example:

\noindent\url{\ftphp session1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/session1.php}}

\noindent\url{\ftphp session1a.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/session1a.php}}

The bouncer (cf. \ref{bouncer}) used in the WMOTU Address Book illustrates how to implement safe session handling. There are a number of runtime configuration settings that we can use to control session handling (cf. \url{http://php.net/manual/en/session.configuration.php}):

{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{WMOTUAddressBookFoxi/bouncer.php}}

The main page \texttt{index.php} (cf. \ref{WMOTUABindex}) saves the user id in \texttt{\$\_SESSION['user\_id']} if the user has provided a valid login. As long as the user is not logged in, the bouncer will always refer back to the login and sign up page. \textbf{The bouncer is required in every file that executes any instructions by simple invocation in order to prevent any unauthorized access to our application.} Our database (cf. \ref{WMOTUDB}) class is one of the few exceptions, as the invocation of \texttt{database.php} by the client does essentially nothing.

To prevent a so-called session fixation attack (cf. \url{https://en.wikipedia.org/wiki/Session_fixation}) where a malicious user uses a session id to impersonate another user, we use the \texttt{session\_regenerate\_id} (cf. \url{http://php.net/manual/en/function.session-regenerate-id.php}) function, which will replace the current session id with a new one, but keep the current session information.

A session terminates when the user closes the browser. If we want the session to survive the closing of the browser, we need to change \verb|session.cookie_lifetime| (cf. \url{https://secure.php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime}). When the user logs out, the session needs to terminate immediately. We achieve this as follows (\url{http://php.net/manual/en/function.session-destroy.php}):

\noindent\url{\ftphp session1kill.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/session1kill.php}}

\begin{mdframed}[linecolor=red,linewidth=3pt, leftmargin=1cm,rightmargin=1cm]
{\textbf{To kill the session cookie in the browser, we must specify the same path that we used to create the session when we specified \texttt{cookie\_path}, i.e. usually \texttt{rawurlencode(dirname(\$\_SERVER['PHP\_SELF']))}. Make sure to verify that the session cookie really gets deleted in the client browser.}}
\end{mdframed}

\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
\url{\ftexphp ex17.php}

Create a login form for the user name \texttt{T2IF2} and the password \texttt{WSERS1}. After successful login, the user is taken to the main page, from which he/she can log out. All of the files for this exercise need to be protected, i.e. only the logged in user can make them execute their core functionality.
\end{Exercise}

\section{Files}
\subsection{Read file contents as a string}
\begin{sloppypar}\texttt{file\_get\_contents} (cf. \url{http://php.net/manual/en/function.file-get-contents.php}) returns the content of the file as a string, including new line characters (\texttt{\textbackslash n}) where appropriate. If we don't want the new lines included, we can use the \texttt{FILE\_IGNORE\_NEW\_LINES} option. We might also want to skip empty lines using \texttt{FILE\_SKIP\_EMPTY\_LINES}. If the file couldn't be opened, the function returns \texttt{FALSE}.\end{sloppypar}

\noindent\url{\ftphp files1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/files1.php}}

\subsection{Read file contents as array}
\begin{sloppypar}\texttt{file} (cf. \url{http://php.net/manual/en/function.file.php}) returns the content of the file as an array.  Each element of the array corresponds to a line in the file, with the newline still attached, unless we use the ignore option. If the file couldn't be opened, the function returns \texttt{FALSE}.\end{sloppypar}

\noindent\url{\ftphp files2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/files2.php}}

\subsection{Write to a file}
Before writing to a new or existing file, we need to make sure the web server has write access to the directory (use \verb|chmod| to change if necessary) and then get a handle to the file via \verb|fopen| (cf. \url{http://php.net/manual/en/function.fopen.php}). Be careful to select the right mode.

Then we can write to the file using \verb|fwrite| (cf. \url{http://php.net/manual/en/function.fwrite.php}).

\noindent\url{\ftphp filewrite1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/filewrite1.php}}

\subsection{Delete a file}
To delete a file, we use the \verb|unlink| function (cf. \url{http://php.net/manual/en/function.unlink.php}).

\subsection{Create a zip file}
\begin{sloppypar}
Use the excellent code from \url{http://ens.ro/2012/04/06/create-zip-archive-from-directory-in-php}. Remember to make sure that the web server has write access to the directory that you want to save the zip file in.
\end{sloppypar}

\section{\label{PHPObjects}Classes and objects}
Object-oriented programming allows us to align our programs much better with the real world. Instead of having variables and numerous functions seemingly independent of these variables but manipulating them, we can define things or objects that exist in the real world and model their characteristics and behavior, thereby linking data and functions.

Cf. \url{http://php.net/manual/en/language.oop5.basic.php} and \url{http://php.net/manual/en/ref.classobj.php}.

\subsection{Defining a class}
\noindent\url{\ftphp class1.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/class1.php}}

\subsection{Static properties and functions}
\noindent\url{\ftphp class2.php}
{\scriptsize\inputminted[tabsize=2, linenos=true]{php}{PHP5/class2.php}}

\subsection{Objects as parameters}
\url{http://php.net/manual/en/language.oop5.references.php}

\section{Exceptions}
\url{http://php.net/manual/en/language.exceptions.php}

\section{Generators}
\url{http://php.net/manual/en/language.generators.overview.php}

\section{Libraries}
\subsection{TCPDF}
Generate PDFs with PHP: \url{http://www.tcpdf.org}

\section{Checkpoints}
\begin{Exercise}[difficulty=1, name={PHP5 Exercise}, counter=excphp]
Write a function \verb|reverse| that can be called with any array and returns the reverse array, e.g. \verb|reverse([1, 2, 3])| returns \verb|[3, 2, 1]|. \textbf{You may NOT use \texttt{array\_reverse} (cf. \url{http://php.net/manual/en/function.array-reverse.php})!}

Here is the finished product in action:

\noindent\url{\ftexphp ex18.php}
\end{Exercise}

\begin{Exercise}[difficulty=2, name={PHP5 Exercise}, counter=excphp]
Create a function \verb|create_inputs| that can be called with a 2-dimensional array, like this:

\begin{scriptsize}
\begin{minted}[tabsize=2, linenos=true, startinline=true]{php5}
echo create_inputs([['User name', 'user_name'], ['Password', 'password']]);
\end{minted}
\end{scriptsize}

Here is the result:

\noindent\url{\ftexphp ex19.php}

More generally, the function can be called with an array which contains any number of arrays, each one consisting of the name and the placeholder to be used to generate the input elements. The function returns the input tags ready to be written to the HTML document (see the HTML source).
\end{Exercise}

\section{Tests}
\subsection{National Elections 2013}
\noindent\includegraphics{NationalElections20131}

You have been tasked to develop an online election system (\url{\ftphp Tests/NationalElections2013}) for the Luxembourg national elections 2013. Use \url{\ftphp Tests/NationalElections2013/index_skeleton.zip} as skeleton.

\textbf{Create a folder \texttt{Tests/NationalElections2013} in your main Foxi folder and save your solution under the name \texttt{index.php}. Make sure that the group www-data has write access to the \texttt{NationalElections2013} folder.}

The array \texttt{\$parties} stores the name of each party and \texttt{\$polls} contains the number of votes for each party.

Write the function \texttt{get\_total\_number\_of\_votes} that returns the total number of votes.
The script generates an HTML table with the votes and percentages for each party. Use \href{http://php.net/manual/en/function.number-format.php}{number\_format} to format the percentage numbers.

\subsubsection{Solution}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/NationalElections2013/index.php}}
The skeleton provides the HTML frame with embedded CSS and the form. The CSS part hints already at the elements that we'll need to generate the poll result table. Note the rule \texttt{table tr:nth-of-type(even)} on line 38, which creates the color alternation between even and odd lines.

The form illustrates how we can implement mutually exclusive radio buttons and remember the last selection. For this to work, all radio inputs need to have the same \texttt{name}, but different \texttt{value} attributes. We use PHP to check for each radio input whether it was checked when the form was submitted. If it was, we'll check it again. The only modification required in the first 104 lines of the skeleton is in line 89, where we need to add \texttt{type=submit} to turn the input into a submit button. Otherwise the user has no way to send his vote to the server.

It is important to realize that the \texttt{get\_polls} function should not be called more than once, given that it increases the number of votes of the chosen party during each call.

The function \texttt{get\_total\_number\_of\_votes} is superfluous, as PHP provides the function \href{php.net/manual/en/function.array-sum.php}{\texttt{array\_sum}}. We'll still develop it, for pedagogical reasons. In fact we've done this already in a previous exercise (cf. \ref{ex11}). The problem statement did not specify whether the function should take a parameter or not, although the skeleton suggests in line 114 that the function should take no parameters. In this case, we need to work with the global variable \texttt{\$polls}. As we've seen in \ref{variableScope}, we need to use the keyword \texttt{global} to make a global variable visible inside a function. Alternatively, we can pass \texttt{\$polls} as parameter to our function.

Now we can generate the HTML table.

\subsection{WMOTU Speed Calc}
\noindent\includegraphics[width=\linewidth]{WMOTUSpeedCalc1}

Develop the web site (\url{https://www.youtube.com/watch?v=Dm-mPRNqYQc}) for WMOTU Speed Calc. \textbf{Create a folder \texttt{Tests/WMOTUSpeedCalc} in your main Foxi folder and save your solution under the name \texttt{index.php}}. Implement the following:
\begin{enumerate}
\item The whole app consists of a single script \texttt{index.php}.
\item Login with cookie-based sessions. User data (user name, password) are stored statically in an array. You need 2 users with name/password \texttt{user/user} and \texttt{admin/admin}. The session cookie is only sent via SSL. Session IDs are regenerated every 20 seconds.
\item Logout.
\item The page contains a short description of the company.
\item Everyone can enter a text into a form. After submission the number of words will be displayed. The form provides a check box. If it is selected, the first letter of every word in the text will be capitalized. Example: "WSERS1 is great" -> "WSERS1 Is Great".
\item Everyone can send a contact request. Form submission will send an email to your teacher. The subject and from fields must have sensible values.
\item For a logged in user the screen background color is green. For an admin user, the background color is gold. For everyone else the background color is the default value, i.e. white.
\item The administrator sees a list of all registered users.
\item A logged in user can perform the following calculations:
\begin{enumerate}
\item Convert an integer to binary.
\item Calculate the volume of a room given its width, length and height.
\item Calculate the annual cost of the user's power consumption based on the average operation time, which can be provided on a daily, weekly or monthly basis.
\end{enumerate}
\end{enumerate}

\subsubsection{Solution}
\url{\ftphp Tests/WMOTUSpeedCalc}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/WMOTUSpeedCalc/index.php}}

\subsection{WMOTU Shop}
\noindent\includegraphics{WMOTUShop1}

Create the web page shown at \url{http://youtu.be/aWo78bwl0s8}.

\subsubsection{Solution}
\url{\ftphp Tests/WMOTUShop}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/WMOTUShop/index.php}}

\subsection{Quiz and Shopping Center}
\noindent\includegraphics{QuizandShoppingCenter1}

\url{http://youtu.be/dunVlaxdZfI}

\textbf{Create a folder \texttt{Tests/QaSC} in your main Foxi folder and save your solution under the name \texttt{index.php}.}

The initial page shows a navigation bar with two links, one to the quiz and one to the shop. The main part shows a welcome message.

The quiz link calls the same script. It's navigation bar shows only the link to the shop. The main part shows a heading, an empty line and then the problem to be solved, which consists of 2 random integers between 0 and 20 and an operator, which is either \verb|+|, \verb|-| or \verb|*|. You may find the \verb|eval| function (cf. \ref{PHPeval}) helpful. Beneath is an input and a submit button. After the user has submitted an answer, the text "You've answered " followed by the number of correctly answered questions followed by "question" followed by an "s" if several questions have been answered correctly followed by " correctly out of " followed by the total number of questions answered is displayed.

The shop link calls the same script. It's navigation bar shows only the link to the quiz. The main part shows a heading, then the listing of all the items added so far with their name and price and the total price. Beneath are 2 labels and 2 inputs for the name and price of a new item to be added to the shopping list and the submit button.

\subsubsection{Solution}
\noindent\url{\ftphp Tests/QuizAndShoppingCenter}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/QuizAndShoppingCenter/index.php}}

\subsection{Roll The Dice}
\noindent\includegraphics[width=\linewidth]{RollTheDice1}

Develop the following app using only HTML, CSS and PHP: \url{http://youtu.be/Vbwny2QUi4Y}

\subsubsection{Solution}
This solution uses hidden fields just to illustrate their usage. A better approach would be to use sessions.

\noindent\url{\ftphp Tests/RollTheDice}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/RollTheDice/index.php}}

\subsection{\label{Test_message_board}Message board}
\noindent\includegraphics{MessageBoard1}

Develop a simple message board, as shown in \url{http://youtu.be/1KoDEvFF7q0}, using only HTML, CSS and PHP. You may use sessions.

Messages are stored in a 2-dimensional array, the first element of each message being the timestamp and the second the message text.

Define and use the two functions \verb|displayMessage($msg)| and \verb|displayMessages()|. The former displays a given message with its timestamp. The latter displays all messages, with the newest at the top.

Use colors \verb|lavender|, \verb|lightskyblue| and \verb|magenta|.

\subsubsection{Solution}
Watch the solution video at \url{http://youtu.be/hAsZs4amUkA}.

\noindent\url{\ftphp Tests/MessageBoard}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/MessageBoard/index.php}}

\subsection{Book Shop}
\noindent\includegraphics[width=\linewidth]{BookShop1}

Develop the \textbf{single file} app exactly as shown at \url{http://youtu.be/Er7XZmGWNkg} using only HTML, CSS and PHP and taking the following into account:
\begin{enumerate}
\item Use the skeleton at \url{https://foxi.ltam.lu/PROF/evegi144/T2IF2_WSERS/WAD/PHP5/Tests/BookShop}.
\item The book titles, authors and prices are all stored in a single multidimensional array.
\item Write a function \verb|get_total|, which takes a single parameter from which it computes and returns the total cost of all items currently in the shopping cart.
\item Write a function \verb|get_table|, which takes a single parameter from which it generates and returns the HTML table with the contents of the shopping cart.
\end{enumerate}

\subsubsection{Solution}
\noindent\url{\ftphp Tests/BookShop/Solution}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/BookShop/Solution/index.php}}

\subsection{TicTacToe}
\noindent\includegraphics{TicTacToe1}

Develop the \textbf{single file} app exactly as shown at \url{http://youtu.be/pZaja-g-o2U} using only HTML, CSS and PHP and taking the following into account:
\begin{enumerate}
\item Use the skeleton at \url{https://foxi.ltam.lu/PROF/evegi144/T2IF2_WSERS/WAD/PHP5/Tests/TicTacToe}.
\item The play field is stored in a simple array.
\item Each button contains one of the three images (\url{https://foxi.ltam.lu/PROF/evegi144/T2IF2_WSERS/WAD/PHP5/Tests/TicTacToe/X100x100.png}, \url{https://foxi.ltam.lu/PROF/evegi144/T2IF2_WSERS/WAD/PHP5/Tests/TicTacToe/O100x100.png} and \url{https://foxi.ltam.lu/PROF/evegi144/T2IF2_WSERS/WAD/PHP5/Tests/TicTacToe/empty100x100.png}), but these \verb|img| tags are generated by a function \verb|get_img|, which takes the play field position as parameter (i.e. an integer from [0, 8]) and returns the complete \verb|img| tag.
\item The two players play in alternation. The current player is indicated in the header.
\item If a player clicks an occupied field, nothing happens.
\item Pressing the "New game" button clears the play field and asks player 1 to make a move.
\end{enumerate}

\subsubsection{Solution}
\noindent\url{\ftphp Tests/TicTacToe/Solution}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/TicTacToe/Solution/index.php}}

\subsection{TicTacToe Pro}
\noindent\includegraphics{TicTacToePro1}

Enhance your TicTacToe app as shown at \url{http://youtu.be/fvKEeKhjCDI}.  

\subsubsection{Solution}
\noindent\url{\ftphp Tests/TicTacToe/SolutionPro}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/TicTacToe/SolutionPro/index.php}}

\subsection{WSERS1 Shop}
\noindent\includegraphics{WSERS1Shop1}

Develop the \textbf{single file} app exactly as shown at \url{http://youtu.be/zmsARb06Ths} using only HTML, CSS and PHP and taking the following into account:
\begin{enumerate}
\item The header shows a link to the shop if the home page is displayed, otherwise a link to the home page.
\item The home page allows the user to enter his/her name, which is then displayed embedded in a welcome message.
\item The shop requires the following:
\begin{enumerate}
\item A two-dimensional array, in which you store a number of items as arrays. Each item has a name and a price.
\item Function \verb|get_table|, which takes a two-dimensional item array as parameter and returns a string containing the HTML table. This table includes the names and prices from the array as well as a random quantity calculated for each article from [1, 10].
\end{enumerate}
\end{enumerate}

\subsubsection{Solution}
\noindent\url{\ftphp Tests/WSERS1Shop/Solution}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/WSERS1Shop/Solution/index.php}}

\subsection{WMOTU Madhouse}
\noindent\includegraphics{WMOTUMadhouse1}

Develop the \textbf{single file} app exactly as shown at \url{http://youtu.be/VWQTI6QXCk0} using only HTML, CSS and PHP and taking the following into account:
\begin{enumerate}
\item The header shows a link to the address book if the latter is not displayed.
\item The header shows a link to the calculator if the latter is not displayed.
\item The header shows a link to the home content if the latter is not displayed.
\item The address book and the calculator can be displayed at the same time, in which case the address book is always displayed first.
\item The date in the home content is shown using Luxembourg as timezone.
\item The address table is generated from a two-dimensional array.
\item The calculator calculates the sum of all integers from [a, b] using a function that receives a and b as parameters and returns the sum.
\end{enumerate}

%\subsubsection{Solution}
%\noindent\url{\ftphp Tests/WMOTUMadhouse/solution}
%{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/WMOTUMadhouse/solution/index.php}}

\subsection{Operating Systems}
\noindent\includegraphics{OperatingSystems1}

Write a \textbf{single} PHP file that performs exactly as shown at \url{http://youtu.be/Dn5er8tfSKQ} using only HTML, CSS and PHP.

Your HTML should be valid. The border color is greenyellow.

The script recognizes two user/password combinations: dummy1/d1pw and admin/admin. Any other combination returns to the login display.

Your PHP script defines and uses a function \verb|get_table|, which takes a two-dimensional associative array as parameter. It returns the HTML table as a string.

For the admin user, the current date and time is shown below the table.

\subsubsection{Solution}
\noindent\url{\ftphp Tests/OperatingSystems}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/OperatingSystems/index.php}}

\subsection{Quiz}
\noindent\includegraphics{Quiz1}

Write a \textbf{single} PHP file that performs exactly as shown at \url{http://youtu.be/eMXcLq6mdHM} using only HTML, CSS and PHP.

Your HTML should be valid.

Your PHP script defines and uses the following:
\begin{enumerate}
\item \begin{scriptsize}
\begin{minted}[tabsize=2, startinline=true]{php5}
$questions = [['The capital of China is: ', 0], ['The value of 5^2 is:', 4]];
\end{minted}
\end{scriptsize}
The first element is the question, the second the index of the correct answer.
\item \begin{scriptsize}
\begin{minted}[tabsize=2, startinline=true]{php5}
$answers = [['Beijing', 'Nanjing', 'Luoyang', "Chang'an"],
			['19', '23', '45', '67', '25']];
\end{minted}
\end{scriptsize}
These are all answers shown in the dropdown list.
\item Function \verb|checkAnswer($idx, $answer)|, which returns true if the correct answer for the question with index $idx is $answer, otherwise false.
\end{enumerate}

\subsubsection{Solution}
\noindent\url{\ftphp Tests/Quiz}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/Quiz/index.php}}

\subsection{Login}
Create the app exactly as shown in \url{https://youtu.be/lkEaFVX9NEo}.

\begin{enumerate}
\item Create a file \verb|functions.php|. In this file:
\begin{enumerate}
\item Write the PHP function \verb|check_login|, which takes two parameters, the user name and the password entered by the user (valid user name/password combinations are a1/a1 and admin/admin). In this function:
\begin{enumerate}
\item If the two parameters are not defined (for instance, the function was called with only one or without any parameters), return 0;
\item Define the array \verb|$valid_logins|, which contains two arrays, the first one with the values 'a1', 'a1' and 1, the second one with the values 'admin', 'admin' and 2.
\item Run through \verb|$valid_logins| and check whether the given user name and password correspond to the first two elements of one of the arrays. If this is the case, return the third value of the matching array (i.e. 1 or 2).
\item If no matching login was found, return 0.
\end{enumerate}  
\item Write the PHP function \verb|generate_welcome|, which takes one parameter, a number. In this function:
\begin{enumerate}
\item If the parameter is not defined or its value is less than 1 or greater than 2 return "error".
\item Define the associative array \verb|$outputs|, which contains 2 elements: the first one has key 1 and value "Welcome user a1", the second one has key 2 and as value the HTML code to generate a heading with background color gold and the text "Welcome master of the universe!".
\item Select the output corresponding to the parameter value from \verb|$outputs| and return it.
\end{enumerate}
\end{enumerate}
\item Create the file \verb|index.php|:
\begin{enumerate}
\item The title is "Test 1: Login".
\item The generated HTML document must obviously be valid HTML5.
\item Include the functions file.
\item Create, but not necessarily display, a form with two inputs, one for the user name and one for the password, as well as a login button.
\item Check whether the login button has been pressed and the values in the two inputs correspond to a valid login (you must use function \verb|check_login| for this purpose).
\item If the check is positive, send the result of \verb|generate_welcome| called with the result from \verb|check_login| to the browser. Then send a new line with a link to log out.
\item If the previous check is not positive, display the login form created in point 4.
\end{enumerate}
\end{enumerate}    

\subsubsection{Solution}
\noindent\url{\ftphp Tests/Login}
\paragraph{\texttt{functions.php}}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/Login/functions.php}}
\paragraph{\texttt{index.php}}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/Login/index.php}}

\subsection{Gradiator}
Create the app exactly as shown in \url{https://youtu.be/0H-WwVeoK0U}.

\begin{enumerate}
\item Create the file \verb|function.php|. In this file:
\begin{enumerate}
\item Write the PHP function \verb|get_gradiant_JS|, which takes two parameters, \verb|$style| and \verb|$stop_count|. The first parameter takes the value 'radial', which is its default value or the value 'linear'. The second parameter is a number with default value 2. In this function:
\begin{enumerate}
\item If the value of the first parameter is different from 'radial' and 'linear' or if the value of the second parameter is outside of [2, 10] return the empty string;
\item Define the empty array \verb|$stops|.
\item Fill \verb|$stops| with as many arrays as specified by \verb|$stop_count|. Each array consists of three random integers from [0, 255].
\item Create the HTML string required to change the background of the document body so that a repeating-radial-gradient or repeating-linear-gradient (don't forget the 'fixed' attribute) is set using all the stop colors stored in \verb|$stops|.
\item Display \verb|$stops|.
\item Note that the function makes sure, that the last style selection (radial or linear) and number of stops are preserved after clicking the submit button.
\item Return the generated HTML string.
\end{enumerate}
\end{enumerate}
\item Create the file \verb|index.php|.
\begin{enumerate}
\item The title is "Test 1: Gradiator".
\item The generated HTML document must obviously be valid HTML5.
\item Create the form with three inputs and one button.
\item Include the function file.
\item Check whether the submit button has been pressed and send the result of a call to \verb|get_gradiant|, with the submitted values, to the browser.
\end{enumerate}
\end{enumerate}

\subsubsection{Solution}
\noindent\url{\ftphp Tests/Gradiator}
\paragraph{\texttt{function.php}}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/Gradiator/function.php}}
\paragraph{\texttt{index.php}}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/Gradiator/index.php}}

\subsection{Computer Shop}
Create the single file app exactly as shown in \url{https://youtu.be/dtIWHlG8joU}.
\begin{enumerate}
\item The title is "Computer Shop".
\item The generated HTML document must obviously be valid HTML5.
\item If the user has selected something from the drop down list, the text "Congratulations, you bought " followed by the the article name followed by a "." followed, in the next line, by the "Return" button are displayed.
\item Otherwise, the form with the selection drop down list is displayed. To do this:
\begin{enumerate}
\item Create one 2-dimensional array with the three keys "PC", "Laptop" and "Tablet" and the associated values "Mega PC1" and "Mega PC2" for the first key, "Mega Lap1" and "Mega Lap2" for the second as well as "Mega Tab1" and "Mega Tab2" for the third.
\item The keys are used to generate the option groups. The values are used as the option text.
\item Do not forget the "Buy" button.
\end{enumerate}
\end{enumerate}

\subsubsection{Solution}
\noindent\url{\ftphp Tests/ComputerShop}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/ComputerShop/index.php}}

\subsection{Simple Calculator}
In this test, you will create the single file app exactly as shown in \url{https://www.youtube.com/watch?v=zTiS1Rnh9is}.

\begin{enumerate}
\item The title is "Simple Calculator".
\item The generated HTML document must obviously be valid HTML5 and your PHP script may not generate any messages in your PHP log file.
\item Create the following PHP array: 
\begin{scriptsize}
\begin{minted}[tabsize=2, startinline=true]{php5}
$arr = ['bg-color' => ['black', 'green', 'blue', 'red'],
        'color'    => ['white', 'brown', 'cyan', 'maroon']];
\end{minted}
\end{scriptsize}
\item Set the document background and font colors by selecting randomly from the corresponding arrays in \verb|$arr|.
\item Create the PHP function \verb|calc($x, $y, $op)|, which does the following:
\begin{enumerate}
\item Check if \verb|$x| and \verb|$y| are numbers and if \verb|$op| is one of '+', '-', '*' or '/'. If not, return the empty string.
\item Return the result of \verb|$x $op $y| (use the eval function and check out the example in the book). Example, if \verb|$x| is 3, \verb|$y| is 4 and \verb|$op| is '-', the function returns -1.
\end{enumerate}
\item The two inputs in the form allow only numbers to be entered and require input.
\item If the form has been submitted, the text 'The result of ' followed by \verb|$x $op $y| followed by ' is ' followed by the result from the calc function for the submitted parameters is displayed above the form.
\end{enumerate}

\subsubsection{Solution}
\noindent\url{\ftphp Tests/SimpleCalculator}
{\scriptsize \inputminted[tabsize=2, linenos=true]{html+php}{PHP5/Tests/SimpleCalculator/index.php}}