PHP - Atletica Carpenedolo

advertisement
PHP: Hypertext Preprocessor
formerly:
Personal Home Page
A walk on the server side
As anticipated in previous courses, PHP is a server-side scripting language. As such, its capabilities are much
stronger than those of client-side languages: server-side scripts have direct access to the to the resources of
Web servers (at least, those who grant it), and, maybe most importantly, they have data processing
capabilities, which allow them to affect data through Web applications.
But there’s a lot more, due to the fact that all these activities take place through the Internet, with all the
related problems of data synchronization: for PHP programmers, the real difference is in the whole internal
engine. PHP is a pre-processor, which prepares and sends complete HTML code to the browser (and hence
to servers). For this reason, it has a somewhat wicked logic, as data must be accessed before building the
page. Dynamicity is still ensured by HTML and JavaScript elements; yet, the changes brought by those
actions are limited to the browser window, until some PHP mechanism updates the actual data on the server.
PHP has some quite advanced functionalities (such as OOP features). This part of the course, however, will
focus on the most basic, which is to access the server file system. By adding yet another management
language (SQL1), it will be possible to view data through a database logic, and process them accordingly. But
before then, the inner workings of PHP must be firmly grasped.
Syntax
PHP scripts can be embedded in HTML documents by enclosing them in a pair of delimiters (<?php and
?>), which, unlike JavaScript (<script>... </script>) identify a single tag. This is one of the details
that show how the logical infrastructure of the Web was built piecemeal, with separate, distinct contributes.
PHP syntax being very similar2 to C/C++, many of its statements, including comments, will look familiar.
There is a twist, however, as most PHP code would not compile in a C program, because, in a most peculiar
way, PHP variable names require a mandatory dollar sign ($) prefix3. Also, there are no variable declaration
directives4. So PHP code has a slightly different feel5, as shown in following example:
<?php
if ( $x > 0 )
{
$x = 2 * $x;
// inline comment
$a = 0;
}
else
/* free comment (also multiline) */
$a = $b * $c;
for ( $i=1; $i<=10; $i++) $c/=10;
?>
As in JavaScript, both stray statements and functions are allowed. PHP is also loosely typed, though it has
somewhat stronger type checking mechanisms. Here is an example of a function:
function prime($n)
{
$i=2;
while( $i<=$n/2 && $n%$i!=0 ) $i++;
return ($i>$n/2 && $n>1);
}
1
BEWARE !!!
PHP variables are not declared.
The one exception refers to the
scope (visibility) of the variables.
Structured Query Language. The version chosen for this course is MySQL.
With the same proviso applying to JavaScript, the syntax may look almost the same, but it’s the engine underneath
that is totally different.
3
This may ring a bell to programmers of old versions of BASIC, where a dollar sign postfix was the one and only way
of declaring a string variable (e.g.: x$).
4
Actually, there is one, but it specifies the variable scope, not its type, nor its very existence.
5
This way, though, PHP variables will not easily be mistaken for database field names or function calls, so there may
be a logic to it.
2
The environment
PHP developers need much more than just a browser, as their applications work over the Internet. So, just to
get started, we need to access a Web server: arguably, the most popular among open-source HTTP servers is
Apache (from the Apache Software Foundation). Then, after learning the basics of the language, we will
need data processing capabilities: again, we will resort to the popular choice among open-source Web
developers, which is MySQL, a relational database management system6. This software, however, is
impractical to use for data maintenance: the definition and the organization of MySQL databases can be done
much more easily with an administrative tool, such as the very popular PHPMyAdmin.
The three components can be found in the respective Web sites:
http://httpd.apache.org
http://www.mysql.com
http://www.phpmyadmin.net
Installing separately all the programs, though, can be a little annoying, especially for the uninitiated.
But the real problem is not in the software itself. The fact is that it would be almost impossible to write and
test our programs in direct contact with a server: development time could increase dramatically, due to the
latency of the Internet infrastructure, as every page would require to be uploaded to the server before being
examined in detail.
Fortunately, there is a global solution to both of these problems, setting up a personal (i.e.: local) Web
server. The whole Web environment can be simulated locally, on any computer, with a software bundle,
called EasyPHP, which smoothly combines and coordinates all the aforementioned programs.
Under GNU/Linux, there is plenty of such software bundles, one of which is called LAMP (standing for Linux
Apache MySQL PHP), covered in many Web sites. On other systems, another program described as similar to
EasyPhp is called MAMP.
It must be noted, however, that any solution developed locally should be, sooner or later, uploaded and tested
on an actual Web server for the final test: what’s more, the test should be done with different browser, to
check that the respective idiosyncrasies do not affect the outcome of the application.
For reference and download, some choices are the following:
EasyPHP
LAMP
MAMP
EasyPHP
6
http://www.easyphp.org
http://www.howtoforge.com/installing-apache2-withphp5-and-mysql-support-on-ubuntu-13.04-lamp
http://www.mamp.info/en/index.html
LAMP
MAMP
DBMS (DataBase Management System) is the historical acronym for specialized data processing software. The
relational model, pioneered by the renowned masters Edgar Codd and Chris Date, is the most widely used, having
superseded other data organization schemes. The concepts behind relational databases are quite advanced, so they will
be studied only in the basic details.
Installation and setup
The setup program is a classic wizard, which leads through the usual installation steps (installation language,
license agreement, destination folder). Everything can be left to the default values.
At the end of the procedure, EasyPHP will be added to the program list, with its easily recognizable icon (a
lower-case block “e” with a red dot)
When we start it, we can see from the splash screen7 that EasyPHP is not the actual software: what it does is
to act as a launchpad for the activation of the two actual engines (Apache and MySQL).
Once we see the green traffic lights, our computer is ready to simulate a complete Web environment. If, for
any reason, one of the servers should be stopped (showing a red traffic light), it could be resumed by clicking
on the corresponding button, then choosing Start.
What we need right now is the Web engine (Apache), which is capable of
translating PHP code into HTML. The database engine (MySQL) will be used
later.
All the administrative tools (including PHPMyAdmin) are not visible in the spash
screen, but they can be activated with a right-click menu on the active EasyPHP
icon (choosing Administration).
As it happens, the very first thing to do is activating the administration page for
some housekeeping, that is, telling Apache where to find the local pages.
7
A splash screen is an image that appears while a program is loading; the term is also used to describe an introductory
page or window.
Setting up the local folders
The administration page is mainly used to associate local folders to each simulated Web site: this is done in
the section labeled LOCAL FILES. The other relevant feature, though not to be used right now, is the “open”
button for PhpMyAdmin (both features are outlined in red, and marked by an arrow).
Each local folder is identified by an alias: of course, right after the installation the list will be empty. Aliases
can be added (clicking the grey link add an alias , immediately to the right of the label LOCAL FILES) or
deleted (clicking on the cross to the far right of the corresponding grey line), but, surprisingly enough, they
cannot be edited: changing an alias requires deleting it, then setting up a new one.
The dialog box for a new alias is quite simple. Step 1 (Create a directory) may already have been done; here,
the alias name (2) is linked to the specified folder (3) after the user clicks on the Save link:
Once in the list, the alias functions as a link to the corresponding folder. If the folder contains a page named
index.html or index.php, it will be activated automatically, as in actual Web sites (if both are present,
preference is given to the html page). If not, the new page will show the content of the folder, with links on
every page or subfolder present.
Accessing the local host
Being server-side means carrying a heavier burden than those light client-side scripts. PHP processes a
whole document, stored on a Web server (Apache or whatever), before sending any code to the browser. As
we will see, this implies going through a parsing of the entire PHP page, which is then translated to pure
HTML/JavaScript. The other implication is that, when working locally (i.e.: on our own computer), the
pages must be stored in the “local Web” folder, or one of its subfolders8. They also must be opened when the
local server is active, as the browser works, by default, only on the client side. In fact, when we open a PHP
page locally, the IP address 127.0.0.1 on the URL line shows that we are linked to the local host:
http://127.0.0.1/test site/thisPage.PHP
127.0.0.1 is a special address, reserved for debugging purposes (it cannot be assigned, either as public or
private). It can be used, for example, to test if the ISO-OSI protocol stack is working.
But these considerations hardly affect the process of writing Web pages, as the local server is an adequate
substitute for an actual server, at least in the development process. The huge difference, from the
programmer’s point of view, is in how the Web page is put together: whereas in DHTML we write the static
HTML part, then embellish it with scripts that work on elements already known to the browser, here a whole
page must be built before being sent to the browser for rendering. We still can add some client-side scripts,
but it is the structure of the page that must be built in advance.
The first experiment that we can make is to write a minimal page, displaying one of the classic welcome
messages, then save it as a PHP file (for example, test.php: note that the php extension is mandatory).
Any of the following could give the idea:
<?php echo 'hi there'; ?>
or
<?php echo "hi there"; ?>
The echo statement is the PHP way of displaying a string on the Web page. PHP code being embedded in
HTML, anything outside the script, if present, should adhere to the rules of HTML. For this example,
though, we do not need any HTML, as the browser will just display the message between the quotation
marks, which can be either single or double, like in JavaScript9.
NOTE When more than one statement are present, the semicolon (;) is necessary, or the pre-processor
would give an error message (and rather unclear, at that). The syntax of PHP is loose, but not to that point.
There is another, almost equivalent, command: <?php print 'hi there'; ?>
print is hardly used for the following reasons:


being a function, it spends some time in returning a value, so it is slower than echo;
while echo accepts any number of comma-separated parameters, print accepts only one.
The examples show the difference between the two, as well as how these statements work with or without
parentheses (except when echo takes a parameter list):
// echo accepts multiple arguments
echo "one 2 three 4<br>";
echo("one 2 three 4<br>");
echo "one ", 2, ' three ', 4, '<br>';
// print() can only take one parameter
print(" singleton <br>");
print " singleton <br>";
$x = print "We sail the ocean blue";
8
// single parameter
// single parameter
// comma-separated (NO PARENTHESES)
// returning a value
In this course, we will not use actual servers. Anybody with access to a Web server, however, can upload there the
exercises, giving them legit, public URLs.
9
Yet, unlike JavaScript or other programming languages, which quotation mark is used can make a huge difference.
More on that later.
Under the hood
The action of sending strings to the browser through a PHP script can, of course, be accomplished by
building a regular HTML document, with all the tags in place (provided the filename extension is still PHP).
But here we discover the trick of the pre-processor. When we visualize the source code from the browser
window, we see that what PHP actually does is to prepare the HTML code line by line, adding the result of
its echo statements to the normal flux of the page.
PHP CODE
<html>
<head>
</head>
<body>
<?php echo 'hi there'; ?>
</body>
</html>
WHAT’S IN THE PAGE
<html>
<head>
</head>
<body>
hi there
</body>
</html>
We could go to the extreme of echoing the whole page, even using PHP variables to store the content of the
message, and nothing would change. By the way, remember that variable names have a dollar sign prefix:
PHP CODE
<?php
echo '<html>';
echo '<head>';
echo '</head>';
echo '<body>';
$a = 'hi there';
echo $a;
echo '</body>';
echo '</html>';
?>
WHAT’S IN THE PAGE
<html>
<head>
</head>
<body>
hi there
</body>
</html>
What happens, basically, is that PHP scripts, be they stray statements or function calls, must leave their trace
as HTML code written on the page. Simply put, this language is a producer of HTML code.
Yes, but where?
If this question were asked in the JavaScript course, there would be no definitive answer, only some
suggestions. In PHP, there are no doubts, because script output (echo) builds HTML code (after all, PHP is a
pre-processor), so that whatever is sent as output through the echo command becomes part of the Web page.
This means that, while PHP functions can (and should) be stored in libraries, at least some scripts will end up
in the heat of the battle, where the corresponding HTML code is to be placed.
The implications of this behavior are quite straightforward:



echo output should adhere to the HTML syntax;
there will invariably be stray PHP statements somewhere, or PHP functions would never have a chance
to be put into action10;
the place for PHP code is wherever needed in the normal flow of the page.
PHP is neither event-driven nor interactive in itself. It is the resulting DHTML code that allows for that.
NOTE As we will see, the very way PHP builds Web pages is the reason for its wicked data processing
mechanism. But more on this later.
FINAL ADVICE The golden rule is still: keep as much PHP as possible away from HTML.
10
Functions quietly sit, waiting to be called. But while JavaScript functions can answer to events happening on the
page, PHP functions can only be activated through other PHP statements. PHP is not dynamic.
When PHP met JavaScript, and the secret of the quotes
PHP was not designed for interactivity: after all, its purpose is to pre-process and build HTML documents. In
those cases where results just need to be shown (mainly for debugging purposes), there is still old hand
JavaScript to help.
For literal messages, or those involving only HTML elements, there is not even need for PHP, as JavaScript
could suffice. So, in the following snippet, the two PHP statements below are just another version of the first
DHTML line, and bear little significance, except for showing the difference between quotation marks:
<script>alert("hi there");</script>;
<?php
echo "<script>alert('hi there');</script>";
echo '<script>alert("hi there");</script>';
?>
<!-- in HTML code -->
// faster
The literal delimited with single quotes translates faster than the other. The reason is that double quotes are a
little more demanding, as they allow a mechanism called macro expansion11, which, to put it simply, is to
store part of the echo string into a variable. This is shown in the following snippet, as opposed to a more
traditional sequence of strings. We will also introduce the most peculiar symbol for string concatenation,
which, quite surprisingly, is not a plus sign, but a dot (.) operator:
$x = 87;
echo "the value is: $x<br>";
echo 'the value is: ' . $i . '<br>';
String concatenation
with the . operator
So, fixed strings are best processed with single quotes, and macro expansion can be used whenever they
make a variable expression simpler. For example, echoing a HTML list could be done in several ways, some
of which really horrible. Of course, even the “good” method is not really so, as it should involve an array of
choices, to be visited with a basic loop. But here we only need to get to the idea; more on arrays later.
/*
Not too bad
*/
echo
echo
echo
echo
echo
'<ul>';
"<li>$var1</li>";
"<li>$var2</li>";
"<li>$var3</li>";
'</ul>';
Should require an array
/*
From bad to worse choices (violating the KISS principle).
*/
echo "<ul><li>$var1</li><li>$var2</li><li>$var3</li></ul>";
$x = '<ul>'."<li>$var1</li>"."<li>$var2</li>"."<li>$var3</li>".'</ul>';
echo $x;
PHP has some flexibility, when it comes to automatic casting. We can mix strings with boolean or numeric
values, but the dot operator must be separated with spaces, lest it be confused with a decimal point:
$a = '2' . true;
$a = '2' . 4;
$a = 2 . 4;
//
//
//
string (also: '2' .true; '2'. true;)
string (also: '2'. 4; wrong: '2' .4)
string (wrong: 2. 4; 2 .4)
The assignments written in red will not be accepted, singling out the number as the offending item. The
resulting page will contain the following message:
Parse error: syntax error, unexpected '4' (T_DNUMBER) ...
(or: '.4')
The rest of the message indicates the name of the page where the error was detected. A more complete list of
error messages will be found in the next section.
11
Sometimes called macro substitution.
Errors, errors everywhere
Locating fatal errors in PHP is not as problematic as in JavaScript: after all, the page is
processed in advance, so the parser has all the time to check the PHP code. Of course,
the same does not apply to the rest of the HTML/JavaScript code, which is left to the
browser, with all the inconveniences of the case: such errors as wrong tags or incorrect
JavaScript statements must be located and trapped, either using a “wolf-fence
algorithm” or by careful examination of the related code.
Let us consider the following snippet, where a loop verifies which numbers between 1 and 10 are prime, by
calling a function already analyzed, with the obvious name of prime. The results are on the right.
for ($i=1; $i<=10; $i++)
{
echo $i . ' (' . prime($i) . ')<br>';
}
function prime($n)
{
$i=2;
while( $i<=$n/2 && $n%$i!=0 ) $i++;
return ($i>$n/2 && $n>1);
}
1 ()
2 (1)
3 (1)
4 ()
5 (1)
6 ()
7 (1)
8 ()
9 ()
10 ()
This example works just fine, but we should not ask too much to the macro substitution, which only expands
the variables present in the doubly-quoted string. Function calls, if present, would be impossible to decipher.
The following line, though not causing a fatal error, would not produce the desired outcome:
echo "$i (prime($i))<br>"; // results in a sequence of lines like: 2 (prime(2))
So, in these cases, we should stick to the concatenation operator, as shown in the first snippet.
The following examples are a collection of errors and warnings12. As short as the snippet is, it is possible to
mistype in so many of ways that it will be hard to remember all the possible error messages: most of them,
anyway, are clear enough that it is not difficult to locate the cause of the error. For each example, there is a
brief description of the error, the corresponding line (or lines), and the error message, where xxx stands for
the name of the PHP document and yyy for the line where the error is detected. As is C/C++, sometimes the
detection of the error happens in a following line, especially with missing punctuation: in those cases, error
trapping needs a little backtracking.
This is not meant to be a complete list; still, it should cover the most common errors.
Missing $ in variable name (in a condition)
for ($i=1; i<=10; $i++)
Notice: Use of undefined constant i - assumed ' i ' in xxx on line yyy
Missing $ variable name (in a function call)
echo ... prime(i);
Notice: Use of undefined constant i - assumed 'i' in xxx on line yyy
Missing $ in variable name: "i" instead of "$i" for (i=1; $i<=10; $i++)
Parse error: syntax error, unexpected '=', expecting ';' in xxx on line yyy
loop parenthesis not closed
for ($i=1; $i<=10; $i++ ???
Parse error: syntax error, unexpected '{', expecting ')' in xxx on line yyy
(the first statement after the error)
Nothing between the loop and the function
for ($i=1; i<=10; $i++)
function prime($n)
Parse error: syntax error, unexpected T_STRING, expecting '(' in xxx on line yyy
(the first statement after the error)
12
Warnings do not cause the parser to abort the page, but they can result in misprints.
Loop brace not opened (only closed)
for ($i=1; i<=10; $i++)
echo...
}
Parse error: syntax error, unexpected '}' in xxx on line yyy
As in other languages, it is not mandatory to use a compound statement : so the parser signals the
line of the unmatched closing brace as the source of the error.
wrong keyword (no parentheses)
cho ... // instead of echo
Parse error: syntax error, unexpected T_VARIABLE in xxx on line yyy
wrong operator
$i+)
$i+++;
// instead of $i++
// stand-alone
Parse error: syntax error, unexpected ')' in xxx on line yyy
In the second example will be ';', Could also be '}', or a variable, depending on the following line.
Call to wrong or UNKNOWN FUNCTION
retun(...) // instead of return
(in the function)
Fatal error: Call to undefined function retun() in xxx on line yyy
MISSING ARGUMENT IN FUNCTION CALL
... prime() ...
Warning: Missing argument 1 for prime(), called in xxx on line yyy and defined in xxx on line yyy (R)
Note: there no problem with extra arguments.
unclosed ) in function call
Parse error: syntax error, unexpected ';' in xxx on line yyy
echo ... prime($i ??? ...
MISSING SEMICOLON AT THE END OF A STATEMENT
echo ... [no ; here]
}
Parse error: syntax error, unexpected '}', expecting ',' or ';' in xxx on line yyy
Parse error: syntax error, unexpected T_ECHO, expecting ',' or ';' in xxx on line yyy
Usually, line yyy is the first statement after the error (excluding comments). So the message may vary: it
depends on what the statement is. In the first case, a closing brace was encountered; in the second, an echo
statement.
Missing concatenation sign
echo $i ')<br>';
Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting ',' or ';' in xxx on
line yyy
Missing opening quote
echo $i . )<br>';
Parse error: syntax error, unexpected ')' in xxx on line yyy
This is not difficult, as the first offending sign is promptly identified.
Missing closing quote
echo $i . ')<br>; ???
Parse error: syntax error, unexpected T_STRING, expecting ',' or ';' in xxx on line yyy
This error is tricky because the string constant is considered terminated at the first quotation sign
encountered, which could easily be in a correct statement, as in echo 'hello';
In that case, it is the closing quotation sign of the CORRECT statement to be considered incorrect. But
then again, a good text editor would show the errors with syntax coloring.
Last, but by no means least, is the worst parse error to backtrack:
Loop brace not closed
for ($i=1; i<=10; $i++)
{
echo...
function prime($n)
Parse error: syntax error, unexpected $end in xxx on line yyy
This error is particularly tricky because it is usually refers to the last line of the document, and there are no
clues as to where the closed brace was forgotten.
Further considerations
The repeated error
As a curiosity, we might note how non-fatal errors and warnings become part of the HTML code of the
actual page, and so they get mixed with those parts which PHP processes successfully; furthermore, their
HTML syntax take into account those part of the messages to be rendered in boldface. In the case of a
variable name without the dollar sign prefix, the error is reported for each step of the loop:
<b>Notice</b>:Use of undefined constant i-assumed 'i' in <b>…</b> on line <b>…</b><br>
1 ()
<b>Notice</b>:Use of undefined constant i-assumed 'i' in <b>…</b> on line <b>…</b><br>
2 ()
<b>Notice</b>:Use of undefined constant i-assumed 'i' in <b>…</b> on line <b>…</b><br>
3 ()
...
Common errors in JavaScript activation
Another simple snippet activates JavaScript, but there are a couple more errors to watch:
echo "<script>alert('hi there');</script>";
No parentheses in echoing a script
echo <script>alert("hi");</script>
Parse error: syntax error, unexpected '<' in xxx on line yyy
Same quotation marks inside a string
echo "<script>alert("hi");</script>";
Parse error: syntax error, unexpected T_STRING, expecting ',' or ';' in xxx on line yyy
Negotiating through missing items
The only really cryptic error messages at least give a hint on what is missing:
Parse error: syntax error, unexpected T_..., expecting
',' or ';' in xxx on line yyy
We have seen several examples of what could be in place of the “unexpected”:





T_VARIABLE
T_ECHO
T_STRING
T_CONSTANT_ENCAPSED_STRING
T_DNUMBER
But it is probably useless to learn them all: with a bit of experience, and considering what was expected13,
the missing item is normally easy to spot.
Missing keywords
The behavior of PHP is not uniform in the case of a missing keyword, due to the structure of the statement
involved. In some cases the parser detects an error, but, after syntax has been cleared, the resulting HTML
code depends on assumptions. For example:




missing function keyword in the function header: intercepted as a syntax error by the parser
missing for or while: intercepted as a syntax error by the parser
missing return keyword in the function: forces a return null
missing echo keyword in a normal display: no HTML action
Uno alla volta, per carità
PHP only reports the first error it encounters; however , this is hardly an inconvenience, as it does not leave
too much space for distractions. After all, we can correct only one error at a time.
13
Actually, it would be more precise to say “what could be expected”, as the parser, which after all is only a syntax
checker, is making assumptions on what could follow.
Give us the tools, and we will finish the job14
PHP has some debugging tools (not many, to tell the truth, unless one resorts to some specialized IDE). In
this section there is a brief summary of some useful features of the language.
Echoing variables
By far, the most used debugging technique is to display the content of variables. There are at least three such
functions, with slightly different behaviors:
$a = 185;
$b = 'xyz';
var_dump($a);
var_dump($b);
var_dump($a,$b);
var_export($a);
var_export($b);
print_r($a);
print_r($b);
//
//
//
//
//
//
//
int(185)
string(3) "xyz"
int(185) string(3) "xyz"
185
'xyz'
185
xyz
The most useful of the three is probably var_dump(), which shows the variable type in front of the value,
and has the added advantage of supporting multiple arguments. The only advantage of the other functions is
that the output string can be returned for subsequent processing instead of being echoed, as in:
$z = var_export($a);
Actually, the same thing could be obtained with var_dump, but in a horrible way (not suggested):
ob_start();
//
var_dump($array);
$out = ob_get_clean(); //
Activate "object buffering"
Deactivate and assign
Magic constants
When errors occur, it may be useful to know where, to help implement a “wolf-fence” algorithm. This can be
done by checking some of the magic constants of PHP, thus called because they change depending on
circumstances15. Their names are self-explanatory, and they can be used to display information about
logistics:
echo
echo
echo
echo
__LINE__ . '<br>';
__FILE__ . '<br>';
__DIR__ . '<br>';
__FUNCTION__ . '<br>';
//
//
//
//
Current line number
File name
Folder name
Function name
Other magic constants (__CLASS__, __TRAIT__, __METHOD__, __NAMESPACE__) belong to the realm of
OOP, and are not used in this course.
Variable variables
If PHP constants can change, another curious feature of the language is the possibility of storing a variable
name into another variable, then access the value of the former with the latter. It can be useful when working
with data structures (lists or arrays), or to enhance data flexibility. Actually, this is a very specialized tool,
used in very complex situations. The following example shows how to deal with these elusive entities:
$a =
$v =
echo
$v =
echo
14
15
'v';
'Content of v';
$$a;
18;
$$a*2;
//
displays Content of v
//
displays 36
Winston Churchill (February 9, 1941).
Which does make them a little more like variables.
Strings
As in JavaScript, PHP strings are a staple of the language, possibly even more so. The processing of input
elements and database values, in fact, calls for a great deal of string operations.
A string constant (also called a “literal”) has the usual aspect as in most programming languages:
"Here's
your crowbar and your centrebit "
In the first examples, we will see string variables getting their value from literals (more on input elements
and data processing later), so the basic assignment is like this:
$a = "We sail the ocean blue";
Most of the key concepts are the same as in JavaScript, so we may refer to the corresponding section. For
example, as in all C-derived languages, PHP strings are zero-based: i.e., the first character of a string is in
position ZERO. Strings are also analogous to arrays of characters.
There are differences, however:

PHP strings are not immutable, i.e. they can be directly modified (as in $a[4]="e"); of course, they can
also be replaced by a new expression, possibly involving the previous value (as in $a=$a."x";).
 The length of a string is not evaluated with a method, but with a function, mutuated from C++: for
example, strlen("abcde") returns 5.
 As seen in previous examples, most strikingly different is the concatenation operator, which is a dot (.)
symbol: so, we will write "blue " . "dress", not +. $a=$a."x"; is equivalent to $a.="x";.
 PHP has the classic string delimiters, single and double quotes (' and "): for example, we may see
echo("Take the 'A' train"); or echo('Take the "A" train');. The key difference, as we
have seen, is the macro expansion mechanism in echo statements. When possible, use single quotes.
Deletion, insertion, replacement, and search are still the other common operations.
Arithmetic on the G string?
PHP numeric strings can be used in the same quirky calculations possible in JavaScript, with the added
bonus that addition works arithmetically ("+" being different from the dot concatenation operator):
echo("4"+"2");
echo("4"+3);
echo("4"*"2");
//
//
//
result: 6
result: 7
result: 8 (the strings are cast to a numeric type)
As already commented, this is just a curiosity, not to be followed in the real world.
How to apply the JavaScript “show” method
What could pass for interaction is the application of the JavaScript show method for string rendering. But it’s
just an illusion, since, as we know, any element of the page must be known to PHP in advance.
The following example is somehow limited because it refers to a direct assignation, but even in the case of
an external source for variable values, the data must be supplied before the HTML code is built. So it is not
that different from what we will meet in the data processing section. Note that quotation signs effectively
turn the variable into a literal; in the second script, without quotations, assumptions are made, and PHP could
print anything. The pre-processed HTML code is also included, to show the difference.
<?php
$x = "sinn fein";
echo "<script>'$x'.show(out1);</script>";
?>
Actual HTML: <script>'sinn fein'.show(out1)</script>
<?php
echo "<script>$x.show(out1);</script>";
sinn fein.show(out1);</script>
?>
Actual HTML: <script>sinn fein.show(out1)</script>
In most cases, nothing
gets printed, but this is
unpredictable.
intVal, floatVal
These functions are the counterpart to parseInt and parseFloat of JavaScript, and are used to transform
string data into numbers. The context of their use is different, however: while in JavaScript they usually
translate input data, in PHP data are read from text or database files, where it may happen, very often indeed,
to find numeric data stored as strings. PHP numbers come in two varieties, integer and double (doubleprecision), but that depends on the values rather than on a type declaration. In fact, the type can change, and
can be detected with the aptly named gettype function:
$n = 6542.348;
$n = 45;
//
//
gettype($n) returns "double"
gettype($n) returns "integer"
The two functions examine the parameter string in similar ways, accepting all the numeric characters until
the string ends or a non-numeric character is met (whichever comes first). Numeric characters include the
"+" and "-" signs (provided there is only one of them, and at the beginning of the string), and the decimal
point (only for the floatVal function, and only the first one: a second point stops the parsing, just like any
non-numeric character). Clearly, the processing of the decimal point is what sets apart the two functions.
Here are some examples of the two functions in action. An asterisk indicates where the parsing operation has
been interrupted by a non-numeric character. Unlike JavaScript, null and empty strings force the result to 0.
intVal("12")
intVal("87y")
intVal("730y3")
intVal("-12.5")
intVal("6 4")
intVal("6-4")
intVal("")
intVal(" ")
*
*
*
12
87
730
-12
6
6
0
0
floatVal("12")
floatVal("87y")
floatVal("730y3")
floatVal("-12.5")
floatVal("6 4")
floatVal("7.8.9")
floatVal("")
floatVal(" ")
12
87
730
-12.5
6
7.8
0
0
*
*
*
Numeric output
Numeric formatting, with respect to JavaScript, has a somewhat backward feeling, derived from the C-style
functions used. Among the several options, the simplest to use is probably sprintf (the name means, more
or less, string-print-formatted) There are differences from C, however, due to the uniform nature of PHP
numbers: the function, in fact, is rather unfazed by the presence of decimal digits, or lack thereof; so, instead
of wasting time with the %d or %f formats, it is perhaps wiser to stick to the old hand, the %g format. In the
following snippet, all formatting options yield the same result:
$n
$z
$z
$z
=
=
=
=
6542.348;
sprintf($n,"%g");
sprintf($n,"%6.2f");
sprintf($n,"%d");
//
//
//
6542.348
6542.348 (waste of time)
6542.348
For documents or forms, there is another function, which uses the thousands separator and a fixed number of
decimal places (which can be used with most currencies, such as dollars, pounds, and euros):
$x = number_format($n,2);
//
6,542.35
The default locale (which is, rather understandably, English) can changed by specifying the new decimal and
thousands separators as additional parameters, sometimes with outrageous results::
$x = number_format($n,2,',','.');
$x = number_format(1520034,2,'comma','dot');
//
//
6.542,35
6dot542comma35
Base conversion
PHP offers a flexible base conversion function, aptly named base_convert, which can work with numbers
or numeric strings, and returns a string. Both bases (source and target) are required; errors yield '0':
$c = base_convert('35',8,10);
$d = base_convert(35,10,36);
$e = base_convert(8,8,36);
//
//
//
'29'
'z'
'0' (error)
Operations on strings
PHP has literally scores of string functions, some quite mysterious. The most common are the following
(shown on a fictitious string $s or $h):
strToUpper($s)
strToLower($s)
substr($s,$i,$j)
strPos($h,$n,[$i])
strrPos(...)
return the content of "$s", with all letters in UPPERCASE
just the same, only in lowercase
extracts a substring of "$s" starting at position $i, with length $j
returns the position of substring "$n" in "$h", ($i=start position)
searches from the end of the string towards the beginning
There is no counterpart to the JavaScript charAt method: characters (which are strings in their own merit)
are extracted with the usual $s[$i] array format.
At the bottom of the page, a brief summary is included. Before examining that, since the behavior of these
functions is sometimes different from their counterparts in other languages, we should consider the following
peculiarities of PHP string handling:
strToUpper, strToLower
These functions do not modify the string: they return a string with the same general content of the source
string, processed accordingly. If we need to modify the original string, it is necessary to store the modified
string back to the variable, with the usual assignation operator:
$s = strToUpper($s);
substr
$x = substr($s,$i,$l);



Incongruent parameters may cause the function to return false, null, or an empty string
If the substring length is omitted, all remaining character will be extracted
If $l is negative, that many characters will be omitted from the end of the string
strPos, strrPos
"$n" and "$h" are mnemonics for needle and haystack: respectively, what to search and in which string.



If the second argument is missing (the default), the search starts from the beginning of the string;
When present, the second argument specifies from which position to start the search;
Unsuccessful searches return false.
substr_count
substr_count($h,$n[,$i]) counts all occurrences of "$n" in "$h" ($i=start position)
This is a rather unique function, as no other commonly used language offers its equivalent16.
Sample values
$s "We sail the ocean blue"
0123456789 123456789 1
$i
$j
$m
$t
$u
$v
16
8
20
3
"ocean"
"sea"
"e"
Function calls
Results
strToUpper($s)
strToLower($s)
substr($s,$i,$m)
strPos($s,$t)
strPos($s,$t,$j)
strPos($s,$v)
strPos($s,$v,$j)
strrPos($s,$v)
strrPos($s,$v,$j)
substr_count($s,'e')
"WE SAIL THE OCEAN BLUE"
"we sail the ocean blue"
"the"
12
false
1
21
21
14
3
With the exception of the now defunct Visual FoxPro, which has never been considered a mainstream language.
Solved problems
Alternating uppercase and lowercase letters
This example shows how to build a new string, one character at a time:
function alternating(s)
//
input: donkey; output: DoNkEy
{
$t = '';
for( i=0; i<strLen(s); i++)
if ( $i%2 == 0)
$t.= strToLower($s[i]);
else
$t.= strToUpper($s[i]);
return $t;
}
Reversing a string
As we have seen in JavaScript, this problem can be solved with a reverse loop, quite similar to a sum of
numbers.
function reverse($s) // input: watch; output: hctaw
{
$t = '';
for( $i=strlen($s)-1; $i>=0; $i--) $t.= $s[i];
return $t;
}
function sum($n)
{
$t = 0;
for($i=$n;$i>=$1;$i--) $t+=$i;
return $t;
}
But there’s more: PHP offers a built-in function for string reversal:
$x = strRev('rabbit');
//
returns tibbar
Building a proper name
Proper names are obtained with two functions: ucFirst capitalizes the first character of the entire string
(lcFirst curiously transforms it into lowercase), ucWords on all the words in a sentence.
$x = ucFirst('this is a sentence');
$x = ucWords('this is a sentence');
//
//
This is a sentence (lcFirst)
This Is A Sentence
HTML spaces
The mnemonic for a HTML (non-branching) space is " ", not too simple to insert into an echo call.
With the useful str_repeat function, it is possible to “multiply” any string a given number of times; the
example shows how the task of echoing “true” spaces on the page is greatly simplified:
function blank($n=1)
{
return str_repeat(' ',$n);
}
// Waste of time:
'     ';
// good:
echo blank(5);
String padding
A padding is a protective layer put around objects. In data processing, the analogy describes the addition of a
number of characters to a string, to make it reach a specified length (usually to fill a predetermined space on
a form). Normally, the padding character is a blank space, as in:
while( strlen($s) < $target ) $s.= ' ';
The function str_pad does just that, with the possibility of specifying the padding string and where to add
the characters (to the left, to the right, centering the original string).this format:
str_pad( $input, $length, $padString, $mode);
$mode can be set to STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH., so the preceding snipped
could be replaced with the following:
str_pad( $input, $target, ' ', STR_PAD_RIGHT);
Following string changes
PHP strings are processed by reassigning a value in the calling program, possibly combining multiple calls
in the same statement. We can track the sequence of value changes in the following snippet:
$s
$s
$s
$s
=
=
=
=
"abcdef";
ucFirst($s);
strRev($s);
strRev(ucFirst($s));
//
//
//
//
original value
now "Abcdef"
now "fedcbA"
proper before reverse (capital F); now "abcdeF"
Note that the calling order matters, as ucFirst(strRev(s)) would yield "Abcdef", with a capital "A".
Character or substring substitution/deletion in PHP
Since PHP strings are not immutable, the substitution of a single character can be made in array fashion:
$s[$i] = strToLower($s[$i]);
Substitutions could also be done by dividing the string into 3 parts, just like in JavaScript:
$s = substr($s,0,$i) . strToLower($s[$i]) . substr($s,$i+1);
PHP, however, among its many string functions, offers one for string replacement:
$s = substr_replace($s, strToLower($s[$i]), $i, 1);
Similar considerations apply when deleting parts of a string (only without a new substring in the middle). For
example, one single character can be deleted with this call:
$s = substr_replace($s, '', $i, 1);
String normalization
This operation is sometimes called purging, as it erases redundant blank spaces, three kinds of which exist:
leading ("
xyz"), trailing ("xyz
"), and multiple ("x
y z").
Reworking the JavaScript solution, we will first delete leading and trailing spaces, with the PHP function
aptly named trim(), then looping through a search for double spaces.
The following function returns the purged copy of its parameter s. The call to function space makes the
script more readable: the expression space(2) identifies the object of the search, whereas the corresponding
string literal " " could be easily misread. The function is also reusable in any other application.
function purge($s)
{
$s = trim($s);
$c = space(2);
while( ($i=strPos($s,$c)) )
{
$s = substr($s,0,$i) . substr($s,$i+1);
}
return $s;
}
function space($n=1)
{
return str_repeat(' ',$n);
}
The same result could be obtained with the substitution function. We can also introduce another mnemonic,
called $b, standing for a single blank spaces:
$c = space(2);
$b = space();
//
while( $p = strPos($s,$c))
$s = substr_replace($s,$b,$p,2);
The default value of parameter is ONE
Finally, a totally devilish method which uses repeating functions (functions that examine all the possible
substrings). substr_count counts the total number of occurrences of a substring, str_replace replaces all
such occurrences. This is rather working with an axe where a scalpel is needed:
while( substr_count($s,$c))
$s = str_replace($c,$b,$s);
//
search – replace – subject
Note that these methods are rather crude, and do not ensure working with any substitution. In the general
case, a loop like the one which follows should be used.
Searching for words
Words are those parts of a string which are enclosed between consecutive two blank characters. That’s where
a normalized string is needed: unwanted spaces may generate empty words, possibly fouling the processing
(and the reconstruction) of the whole phrase.
Let’s consider the string "We sail the ocean blue". Suppose that, with the strPos() function, we
have managed to set "$i" to 2 and "$j" to 7: substr($s,$i+1,$j-$i-1) extracts the word "sail",
which can be processed as desired17. The same applies for any such pair of indexes, as shown here:
A single loop will suffice for the indexes to proceed along the string, provided that the search for each new
blank started from the last position reached. Having "i" chase "j" is not a great deal; the situation,
however, is not quite as clear at the boundaries of the phrase (that is, the first word and the last). The first
word can easily be identified by setting the initial value of "i" to -1. The real problem is at the end, when
"i" is 17 and "j" becomes false, which is the result of the unsuccessful search for another blank. One
simple solution is to attach a blank space at the end of the string, thus ending up with the correct value of 22
for the forward index "j".
It may sound silly to go through the trouble of normalizing the string, then adding a redundant space of the
same sort as the ones we have struggled to delete. The point is that the trailing space is not of the same sort
after all, being a totally different beast: besides being placed there for the purpose of coping with a search
result which disrupts the algorithm, the extra space is temporary18, being added only for the duration of the
function, quietly disappearing at the end of the process. The skeleton for this procedure is the following:
function words($s)
{
$c = space();
BEWARE !!!
$s.= $c;
The function does not specify what to do
$i = -1;
with each word. This is left as an exercise.
$j = strpos($s,$c);
while ( $j )
{
$word = substr($s,$i+1,$j-$i-1);
...
//
Processing the single word
th
$i = $j;
//
"i" reaches the "j " position
$j = strpos($s,$c,$j+1); //
Search for the next blank
}
}
As in JavaScript, these is the much simpler solution which uses a slack array. The PHP functions for stringto-array and array-to-string transfers, named explode() and implode(), respectively, differ from their
JavaScript counterparts in that explode() requires a mandatory separator character, as in:
$a = explode(' ',$s);
...
$s = implode(' ',$a);
//
//
//
Store the words into array "a"
Process the array
Reconstruct the sentence from array "a"
But first we need to know a bit about arrays. This will be the topic of the next chapter.
17
18
The formula $j-$i-1 is used because the second parameter of the substr function is the length of the substring.
Normally, the space is called a slack data, in that it is used, then discarded without further effects.
Arrays
Arrays should be known from previous courses. PHP arrays are no exception to the general rule, being
collections of data, identified by their position (also called index). An example of array could be a list of the
temperatures of one week: 25,30,28,34,32,35,36. As we saw with strings, PHP arrays are somewhat
more primitive objects than in JavaScript, and their management reminds much the C++ language. Yet, array
handling is quite advanced, thanks to many useful functions.
Arrays can be declared in a couple of ways:
$a
$a
$b
$c
=
=
=
=
array();
array(87);
array(1,2,3,4);
[1,5,3,2];
//
//
//
//
Empty
NO JavaScript: one element, number 87
Direct value assignation
Not safe (only PHP 5)
Some considerations apply:






The first element of a PHP array is in position zero (like C/C++ arrays);
Unlike C/C++ arrays, PHP arrays are elastic (i.e.: their length can vary, adding or deleting elements);
Tthe length of an array is a calculated with a function, called count($a);
The last element of array $a is in the position count($a)-1 (length minus one, due to the presence of
the element in position zero).
There can be no unassigned array elements; they can be deleted, though, along with the index (this
means that an array could be left, for example, with positions 0 and 2, but no position 1).
PHP arrays are linear (or mono-dimensional); with some tricks, it is possible to mimic matrices (multidimensional arrays, with any number of dimensions), including the familiar syntax a[i][j]; matrices,
however, are outside the scope of this course, as their use in Web applications is limited.
Some of the most common functions for assigning and extracting values are listed below:
array_push($a, ...);
array_unshift($a,...);
array_pop($a)
array_shift($a)
array_splice($a,$p,$n);
array_splice($a,$p,$n,$b);
array_reverse($a)
sort($a)/rsort($a)
array_slice($a,$p,$n);
//
//
//
//
//
//
//
//
//
Append at the end of the array (sequence)
Insert at the beginning (sequence)
Remove last element
Remove first element
Remove $n elements starting at position $p
Remove, then insert (element or array)
Flips the array
Sort elements in ascending/reverse order
Copy $n elements starting at position $p
The pop and shift methods are limited to just one element. The same holds for the simplest way of adding
an element to an array, which uses an empty couple of brackets, as in: $a[]=18;.
The following sequence shows the methods in action. At each step, the new elements are written in green;
the elements written in red are those which the following method would remove from the array:
array_push($a,21);
array_push($a,31,32,33);
array_unshift($a,41);
array_unshift($a,51,52,53);
array_pop($a);
array_shift($a);
array_splice($a,3,4);
array_splice($a,1,1,array(61,62,63));
array_splice($a,0,1,37);
array_reverse($a);
sort($a);
$new = array_slice($a,1,3)
21
21,31,32,33
41,21,31,32,33
51,52,53,41,21,31,32,33
51,52,53,41,21,31,32
52,53,41,21,31,32
52,53,41
52,61,62,63,41
37,61,62,63,41
41,63,62,61,37
37,41,61,62,63
41,61,62 (new array)
No show
Just for curiosity, javascript:show sort of works with arrays, but not quite: the result is just a string
containing the word Array. The flexibility of JavaScript does not hold in PHP, which, once again, is not
dynamic, but must process the whole page before submitting it. The image below shows the effect:
<?php
$x = array();
echo "<script>'$x'.show(out1);</script>";
?>
The actual HTML also contains a warning that there is something fishy:
Notice: Array to string conversion in xxx on line yyy
<script>'Array'.show(out1)</script>
Stretching arrays
As seen before, arrays can be stretched with a generic assignment to the array, containing a pair of empty
square brackets; actually, they could even be generated in the same way. It should be noticed, however, that
in such cases the first element should be assigned directly, as with array $a in the example; and while array
$b and $c have the burden of an extra element, array $d is built in a more proper way:
$a[]
$a[]
$a[]
$a[]
$a[]
$b[]
$b[]
$c[]
$d
$d[]
=
=
=
=
=
=
=
=
=
=
1;
'a';
false;
array();
5.6;
null;
15;
array();
array();
21;
//
//
//
//
//
Not suggested (generates one null element)
this element would be the SECOND one
BAD: one element: an empty array
Empty array
extension
Deleting variables
The unset function can be used to erase any variable from the symbol table, and is sometimes used on array
elements. Care must be taken, however, because this can disrupt the numeric indexing, as in the following
example, which generates an error when trying to access $a[2] after its deletion:19
unset($a[2]);
for($i=0;$i<count($a);$i++) var_dump($a[$i]);
Notice: Undefined offset: 2 in xxx on line yyy
Look ma, no indexes
The previous error can be avoided with an useful array visiting tool, the foreach statement20. Disposing
with the use of an index, foreach is simpler and safer than the usual traversing loop.
The two loops of the following example have the same effect:
for($i=0;$i<count($a);$i++) var_dump($a[$i]);
foreach($a as $v) var_dump($v);
It is also possible to call the elements by reference, in order to modify them:
foreach($a as &$v) $v*=2;
19
Erasing variables (with the unset function) could be useful in complex applications. More widely used is the test on
the existence of a variable, as in: if (isset($v))...
20
foreach is present in other languages, including Java and Visual Basic. In JavaScript, it is limited to objects.
Associative arrays
Arrays can be used without numeric positions, using only string indexes (this is the meaning of associative).
This example was given by Jeffrey Way in one of his precious lessons, where he shows a list of links to
some of his courses:
$a = array
(
"nettuts" => "http://net.tutsplus.com",
"psdtuts" => "http://psd.tutsplus.com",
"wptuts" => "http://wp.tutsplus.com",
//
);
//
echo '<ul>';
foreach( $a as $name=>$url)
//
{
echo "<li><a href='$url'>$name</a></li>";
}
echo '</ul>';
this last comma is optional
don’t forget the semicolon
LIST OF COURSES AND URLs
The $name=>$site association in the foreach statement corresponds to the => couples in the array
declaration, so that:
"nettuts" replaces $name
"http://net.tutsplus.com" replaces $url
The <li> elements can also be assigned with a forced double quote (which requires a backslash prefix):
echo "<li><a href=\"$site\">$name</a></li>"; //
echo "<li><a href="$site">$name</a></li>"; //
This is also correct
WRONG: same quotation sign
An alternate syntax is given by the endforeach keyword, which can replace the closing brace while
disposing of the opening one. This is not suggested, as it deviates from the usual syntax:
foreach( $a as $name=>$site)
echo ...";
endforeach
Some consider this construct useful when breaking out of PHP, but the fact remains that, even if breaking
were necessary, more PHP would be included in the loop, and confusion might ensue. Anything that mixes
PHP and HTML is deprecated, and, fortunately, seldom used21:
<?php foreach( $a as $name=>$site)?>
<!-- HTML stuff -->
<?php endforeach ?>
//
//
//
PHP
HTML
PHP
The following examples (one bad, one worse) show the mess that can be generated by mixing too much:
<ul>
//
<?php
foreach($tuts_sizes as $name => $url)
echo "<li><a href='$url'>$name</a></li>";
?>
</ul>
BAD
<ul>
//
WORSE
<?php
foreach($tuts_sizes as $name => $url)?>
<li> <a href="<?php echo $url; ?> "> <?php echo $name; ?>" </a> </li>
<?php endforeach ?>
</ul>
21
PHP developers seem more willing to adhere to good programming practices than their JavaScript counterparts.
Solved problems
PHP built-in functions cover most of the routine array operations, such as sorting, flipping, and extracting.
This frees the programmer from the burden of writing and testing the corresponding scripts. The following
examples, though of little intrinsic value, will be used to introduce some useful features of the language.
Flip part of an array
Given an array, find two random positions $p and $q, ensuring that $p<$q, then flip the part of the array
which lies between the two positions. In the examples, the values of $p and $q are 3 and 6, respectively:
$a = [0,1,2,3,4,5,6,7,8,9]; $p=3; $q=6;
//
result: 0,1,2,6,5,4,3,7,8,9
We will tackle the numeric part first, showing how to deal with random numbers. The PHP tool is the rand
function, one of a series of mathematical functions22. Unlike its JavaScript counterpart, the PHP random23
generator returns, by default, an integer value between 0 (included) and the result of the JavaScript function
getrandmax()24 (excluded). It is quite simple, though, to specify an interval for the result:
$x = rand(min,max);
This way, we do not need any special calculations to find positions which belong to the array. The swap
solution shown, a nice PHP alternative, is not the fastest around, so it would not be suggested for a situation
with many exchanges: in any instance when time is a factor, the usual swap function is still preferred.
$p = rand(0,count($a)-1);
$q = rand(0,count($a)-1);
if ($p>$q) list($p,$q) = array($q,$p);
//
//
//
The PHP list statement is a construct
which assigns the values of an array
to a list of variables
There rest of the solution, with a “flip” loop, is elementary:
while ($p<$q)
{
swap($a[$p],$a[$q]);
$p++; $q--;
}
function
{
$c =
$a =
$b =
}
swap(&$a,&$b)
$a;
$b;
$c;
With the list construct, the swapping would be:
list($a[$p],$a[$q]) = array($a[$q],$a[$p]);
A much shorter method uses the array_splice function, which, contrary to JavaScript, allows for the
insertion of an entire array in a given position. This way, it is possible to extract and reverse a section of the
array, then graft it back in the same place where it was pruned. For the sake of simplicity, a new variable can
be used to specify the length of the section ($p and $q are still 3 and 6):
$n = $q-$p+1;
array_splice($a,$p,$n,array_reverse(array_slice($a,$p,$n)));
Find the smallest (or largest) element, using a comparison function
A couple of other functions, min() and max(), can sometimes be useful in comparisons. They return,
respectively, the minimum and maximum value among a list of values, as in:
max(41,63,4,5,116,87);
//
result: 116
The lists can be of any length: there does not appear to exist an explicit limit, but some experts estimate a
resource limit at around 2 billion (2*109).
Unlike other similar functions in other languages, using min and max on an array seems almost unfair, as,
unlike in JavaScript, they only need the array name:
$a = [53,41,55,63,47,48];
$min = min($a);
$max = max($a);
22
//
//
result: 41
result: 63
Many of these (exponential, logarithmic, trigonometric) are hardly used.
Actually, a pseudo-random generator, since it follows an algorithm: for practical purposes this makes no difference.
15
24
Normally, this value is 32767 (2 -1).
23
Strings and arrays
Just as in JavaScript, strings and arrays will meet in the processing of a whole sentence, without resorting to
the search for blank spaces. The problem can be summarized as:
1 transfer the words of a sentence to an array
2 process the words separately
3 repack the array into a single string.
The solution has been studied before, so it should surprise no one. The notable difference with JavaScript is
that here the substring separator (the first argument) is mandatory in the function calls:
$s = 'We sail the ocean blue';
$a = explode(' ',$s);
foreach($a as &$x) $x = strRev($x);
$s = implode(' ',$a);
$t = "go with the flow";
$b = explode(' ',$t);
foreach ($b as &$x) $x = ucFirst($x);
$t = implode(' ',$b);
//
Reverse EACH WORD
//
Capitalize EACH WORD
Of course, the second example could be solved with one call to ucWords($t).
Omitting the separator in the call to explode is not a choice, as it would generate an error; an empty
separator is also not allowed. The respective error messages are the following:
Warning: explode() expects at least 2 parameters, 1 given in xxx on line yyy
Warning: explode(): Empty delimiter in xxx on line yyy
The blank separator in the subsequent call to implode, though not mandatory, is strongly suggested, or the
spaces would not be restored (the result would be GoWithTheFlow).
It is still possible to transfer one character per element in the target array, with the str_split function.
This could turn out to be useful when some specific array functions are needed (array_reverse, to name
one), or when a character might be replaced with a string of a different length (or even deleted). The
following examples show nothing that could not be obtained with normal string operations, but they should
give the idea. Actual problems would analyze the characters, and take the appropriate actions, with far more
complicated processes.
WARNING !!! the reconstructing implode function should be called without a separator, or at least
with an empty one (which, contrary to explode, is allowed), to avoid inserting unwanted spaces between
characters (as in "c u r s e", instead of "curse").
Normal array visit with
character check
$z = 'hammock';
$a = str_split($z);
foreach($a as &$x)
if ( $x=='m' ) $x='d';
$z = implode($a);
hammock
Before
haddock
After
Deleting some
characters
$u = 'princess';
$a = str_split($u);
unset($a[6]);
$u = implode($a);
Substituting with
longer expression
$v = 'curb';
$a = str_split($v);
$a[3] = 'se';
$v = implode('',$a);
Before
After
Before
After
princess
princes
curb
curse
PHP in action: processing parameters
Strings and arrays are the staples of PHP, but, until now, they have shown nothing that could not be done
with JavaScript25. Some of the real power of these tools can be appreciated with the processing of page
parameters, which has been left pending both in the HTML and in the JavaScript courses.
This is a possible complete URL of the called pages, along with the arguments:
file:///D:/web/application/index.html?h1=oneword&h2=two+words
There is a little tweaking to be done: it is necessary to substitute PHP pages for HTML ones, so the calling
page should be rewritten in this way:
<form action="php8.php" method=get>
<input id=h1 name=h1 value="oneword">
<input id=h2 name=h2 value="two words">
<input type=submit value="send">
</form>
In this example, the fields are in
plain sight: this makes no difference
in their handling by the called page.
Of course, we will end up with this URL line:
file:///D:/web/application/php8.php?h1=oneword&h2=two+words
The page is called with the get method, just to show the parameters: normally, though, we should use the
post method, for security reasons. Internally, there is actually no difference, as the called PHP page is
always capable of recognizing the parameters, via a special array called superglobal26, which stores all the
data that the page has been sent. For now, we will only display the array like so:
<?php
var_dump($_REQUEST);
?>
Sure enough, the array contains the parameters. They are stored as strings27, keyed by their names (assigned
in the form element of the calling page), as the following var_dump result shows:
array
'h1' => string 'oneword' (length=7)
'h2' => string 'two words' (length=9)
This is an associative array
A PHP page has three such superglobal arrays. Just to avoid any doubts, the $_REQUEST arrays is sure to
contain the desired values:
$h1
$h2
$h1
$h2
$h1
$h2
=
=
=
=
=
=
$_GET['h1'];
$_GET['h2'];
$_POST['h1'];
$_POST['h2'];
$_REQUEST['h1'];
$_REQUEST['h2'];
//
Parameters passed with the get method
//
Parameters passed with the post method
//
Any method
After that, it is still advisable to check for the parameters received, with call to isset:
if( isset($REQUEST['h1']) ... ;
if( isset($REQUEST['h2']) ... ;
isset checks for existence
Also, default values can be assigned:
if( ! isset($REQUEST['h1']) $_REQUEST['h1']='default value';
This is especially suggested when receiving input values from forms containing check boxes or radio
buttons: when such elements are left empty, their names do not even appear in the $_REQUEST array.
25
This is going to change in the chapter dedicated to data processing
There are several superglobal arrays, for various purposes. More on this later.
27
This is true also for numeric values, hence the importance of the type transformation functions.
26
Case study: accessing the server
As already mentioned, PHP has access to the file system on the server. In this study, we will see some
operations on text files. Reading a text file is the simplest operation, and one that does not require access
permits; creating, modifying, and deleting files, on the other hand, are subject to the security measures on the
server28. In a local environment, though, anything goes, so it will be possible to operate at will.
We can use a simple text file, for example, one named text.txt, which contains a list of names.
Cochrane Foxx Bishop
Boley Dykes Simmons
Miller Haas Grove
File access is allowed once the file is opened (fopen), until it is closed (fclose). When the file is opened, a
reference to it can be assigned to a handle (which is a particular object, called a resource), through which
all further operations will be executed.
Function
Example
Meaning
fopen
fclose
fread
fgets
feof
rewind
filesize
fwrite
$h = fopen("text.txt","r")
fclose($h);
$x = fread($h,$n);
$x = fgets($h);
while (!feof($h)) ...
rewind($h);
... filesize($h) ...
$w = fwrite($h, ...);
Open for reading
Close
Read a given number of bytes
Read to eof or line break
End-of-file
Reposition at file beginning
Total number of bytes
Write to file (any value)
A file can be opened in a number of ways (called modes), the most common being the classic three:
mode
Meaning
r
w
a
Input
Output
Append
Some examples:
$handle = fopen("text.txt","r");
$x = fread($handle,11);
fclose($handle);
$handle = fopen("text.txt","r");
$x = fread($handle,filesize("text.txt"));
fclose($file);
$handle = fopen("text.txt","r");
$x = fgets($handle);
while(!feof($handle))
{
echo $x . '<br>';
$x = fgets($handle);
}
fclose($handle);
$handle = fopen("text.txt","r");
while($x = fgets($handle))
{
echo $x . '<br>';
}
fclose($handle);
readfile('text.txt');
28
Reading a given number of bytes
Reading ALL the bytes of the file
Reading each line of text. The test is done
through the feof function.
Shorthand: the loop assigns the line to a variable
and tests for end-of-file in the same token
Quick-and-dirty way for displaying text content
Some servers do not allow direct handling of data, unless a user has logged in through a portal. In such cases, PHP
pages only have reading privileges.
Error trapping
Whenever a program tries to access a file, the problem arises of whether the file actually exists: after all, you
cannot extract data from a resource that cannot be located.
Trying to open a file not present in the search folder, to use technical jargon, throws an error; and while the
script does not abort, a flurry of error messages appears:
$file = fopen("xxx.txt","r");
$x = fread($file,11);
fclose($file);
//
This file does not exist
This is what gets written on the screen:
Warning: fopen(ext.txt): failed to open stream: No such file or directory in C:\web\textfile.php on line x
Warning: fread() expects parameter 1 to be resource, boolean given in C:\web\textfile.php on line y
Warning: fclose() expects parameter 1 to be resource, boolean given in C:\web\textfile.php on line z
The fact is that the handle has a value of false, hence the clause “boolean given” in the message.
Aborting the script can be a very simple choice with the aptly named die() clause, but a warning message
appears anyway:
$file = fopen("xxx.txt","r") or die();
Warning: fopen(ext.txt): failed to open stream: No such file or directory in C:\web\textfile.php on line x
The situation can be better controlled by disabling the standard error handler (that is, the built-in function
that processes errors and displays the corresponding messages). An empty error handler does not stop the
script, but appropriate action should be taken, typically by checking the result of the fopen statement:
set_error_handler("errorTrap");
//
set a custom error handler
//
open successful?
//
proceed processing
restore_error_handler();
//
restore default error handler
function errorTrap() {}
//
no action
$file = fopen("ext.txt","r");
if($file!=null)
{
...
fclose($file);
}
In file processing, there are not many error situations, so an empty handler is perfectly legit. In other
situations, it may be useful to give more detailed explanations; that’s why an error handler has several
parameters that can help the programmer locate the error.
$errno
$errstr
$errfile
$errline
numeric code
error description
name of the page where the error has occurred
line number where the error has occurred
The parameters are optional, and the program may contain a die() clause, although this is doubtful, or the
error handler would not have been written in the first place:
function errorTrap( $errno, $errstr, $errfile, $errline)
{
echo "<b>Error:</b> [$errstr]<br>";
echo "<b>Program:</b> [$errfile]<br>";
echo "<b>Line:</b> [$errline]<br>";
die();
//
Cui prodest?
}
Writing text
The quick-and-dirty way of storing text into the server folder is:
file_put_contents('text1.txt', 'we sail the ocean blue');
The function, if successful, returns a value corresponding to the number of bytes written (in this case,
22).The resulting text file can be opened with Notepad, or any other editor:
In a more conventional way, the file can be opened either in output or in append mode, then data can be
written with the fwrite function (the combination chr(13).chr(10) forces an end-of-line):
$x = array("we","sail","the","ocean","blue");
//
data to be written
if ($h=fopen('text2.txt','w'))
//
output mode
{
//
(new file)
foreach( $x as $v ) fwrite( $h, $v . chr(13) . chr(10) );
fclose($h);
}
if ($h=fopen('text2.txt','a'))
//
append mode
{
//
(data are added)
foreach( $x as $v ) fwrite( $h, strToUpper($v) . chr(13) . chr(10) );
fwrite( $h, 45);
//
numeric data
fclose($h);
}
By using the “append” mode in the second loop, the array of words has been written a second time (in
UPPERCASE), so that the final content of the text file is as follows (one word per line):
The number 45 has been written
without quotes: we can see that it
has been transformed into a
string.
As in the previous examples, it should be noted that the result of the “open” operation is assigned to a
variable, called handle. Every further reference to the file is done through that handle: the file name is not
used any more, having already been linked to the file system.
When write errors happen, the return value of fwrite is false (or 0), as in the following example:
if ($h=fopen('text2.txt','r'))
{
$f = fwrite( $h, 'test');
echo $f;
fclose($h);
}
//
file opened in input
//
//
attempt to write
$f (return value) is FALSE
Case study: building a photo gallery
There are innumerable photo galleries on the Internet, from corporate sites to social networks. In this
example, we will use HTML, CSS, JavaScript, and PHP to produce a synergic Web page accessing a folder
with our favorite pictures. This page will also receive the name of the folder as a parameter, therefore
completing the circle with most of the elements studied so far.
The roles for each actor are:
HTML
CSS
JavaScript
PHP
Infrastructure on which all the rest is built
Appearance of the page
Dynamic access to different pictures
Engine to access the file system on the server, containing the pictures
First, let’s examine how to access the images in a given folder (more specifically, a subfolder of where the
page is located). The PHP functions that will be used here are four:
Check if the string (presumably, a parameter of the function) contains a valid
folder name.
opendir(<name>)
Open the folder and assign it to a handle (a variable for future reference)
Access the folder content with the specified handle (each open folder requires
readdir(<handle>)
its handle: in our case, only one folder is used)
closedir(<handle>) Deny further access to the folder (which, of course, can be reopened at will)
is_dir(<string>)
Step 1 – accessing the file system
The following is a function which receives the folder name in input, checks for validity, then returns an array
containing the names of the images (or an error message, if the parameter is not a valid folder name).
function getImages($dir)
{
if (is_dir($dir))
{
$images = array();
//
empty array
$handle = opendir($dir);
//
open folder
while ($x = readdir($handle))
//
reading loop
{
$x = strToLower($x);
if
//
check common formats
(
strPos($x,'.bmp') !=false ||
strPos($x,'.gif') !=false ||
strPos($x,'.jpg') !=false ||
strPos($x,'.jpeg')!=false ||
strPos($x,'.png') !=false
)
$images[] = $dir . '/' . $x;
//
add to list
}
closedir($handle);
//
close folder
}
else
//
ERROR: return a string
{
$images = '"' . $dir . '" is not a valid folder name';
}
return $images;
}
The features of this function:


Variable $handle, which is the reference to the folder, once opened;
The direct assignment of each folder entry to variable $x, in the visit to the folder.
Step 2 – designing the page
The page will consist of two containers: one to the left (<aside>), containing a list of links made with the
preview images; one to the right (<div>, class content), containing the image selected from the list
(initially, the first one, number zero). In the preview list, the selected image will have a red outline.
A bit of CSS will suffice to set up the page:
aside
{
background-color
float
width
}
aside, .content
{
height
overflow
text-align
}
.content
{
background-color
width
float
margin
}
.preview
{
width
margin-top
}
/* container for preview */
: paleGreen;
: left;
: 10%;
/* shared settings /*
: 100%;
: auto;
: center;
/* centers the images */
/* magnified image */
:
:
:
:
lightCyan;
90%;
right;
auto;
/* preview list */
: 80%;
: 10px;
Step 3 – building a JavaScript array
Now, PHP meets JavaScript and builds the dynamic array for the pictures, which will make it possible to
dynamically change the central image. The five red echo statements actually write into the page the
declaration and initialization of a JavaScript array:
function js_array($images)
{
$s='';
foreach( $images as $x )
$s.= '"' . $x . '",';
$s = substr( $s, 0, strlen($s)-1);
echo '<script>';
echo "images = [$s];";
echo '</script>';
}
//
//
comma-separated list
cut last comma
//
could be: "a.gif,b.jpg,c.jpeg,d.png"
Step 4 – building the dynamic elements
Now, PHP will build the preview list and the central picture. Each entry in the preview list comes with an
event which enables JavaScript to change the selected image, both in the list and in the central picture.
Another JavaScript variable, named p, initialized through a stray statement, keeps track of the selection. The
anchors are not really necessary: their only use is to change the cursor from ”arrow” to “link”.
<script>
p = 0;
</script>
//
Selected image (initially 0)
<?php
function gallery($images)
{
$t = count($images);
echo('<aside id=aside>');
//
Preview (aside)
for($i=0;$i<$t;$i++)
{
$x = $images[$i];
$z = "style='border:" . ($i==0 ? 'solid red 3px' : '0px') . "'";
echo("<a href='#'>");
echo("<img id='pic$i' class=preview $z src='$x' onclick='change($i)'>");
echo("</a>");
}
echo '   ';
//
Just for a bottom padding
echo('</aside>');
//
Central picture
echo('<div class=content>');
echo("<img id=central height=90% src='$images[0]'>");
echo('</div>');
}
?>
<script> /* changing the selected image */
function change(i)
{
z = document.getElementById('pic'+p);
z.style.border = '0px';
z = document.getElementById('pic'+i);
z.style.border = 'solid red 3px';
z = document.getElementById('central');
z.src = images[i];
}
</script>
//
i = index in array "images"
//
Old "selected" loses border
//
New "selected" gets border
//
//
Change central image
(using name of image #i)
Step 5 – calling the page
Now it is time to put everything together. As anticipated, the “gallery” page will get the folder name from
another page, where it will be written in a textbox. An example of a very minimalist page, which does not
even need any PHP:
<html>
<head>
</head>
<body>
<form action="gallery.php" method=post>
<label for=folder>folder name</label>
<input style="width:200px" id=folder name=folder>
<input type=submit value=view title="view gallery">
</form>
</body>
</html>
The content of textbox
folder will be received
by the called page.
Step 6 – receiving the parameter value
The necessary steps to get the parameter value with the folder name will be added to the page. The first PHP
statement (***) are not necessary if the page is activated by the preceding one via the submit button; it is
added to cover the case when the page is directly addressed in the URL line. After the call to getImages, it
is possible to check for errors: the only one possible is a name not corresponding to a folder. If this is the
case, only the error message appears:
If the test is successful, the functions examined before will be activated, and, pronto, our gallery will appear.
<html>
<head>
<link href='gallery.css' rel='stylesheet' type='text/css'>
</head>
<body>
<?php
if (!isset($_REQUEST['folder'])) $_REQUEST['folder']=false; //
***
$folder = $_REQUEST['folder'];
$images = getImages($folder);
if (is_string($images))
//
Remember: string means "error"
{
echo $images;
//
Display error message
}
else
{
js_array($images);
//
Build the JavaScript array
gallery($images);
//
Build the rest of the page
}
...
?>
...
</body>
</html>
Of course, the ellipses stand for the rest of the page (PHP and JavaScript code).
Step 7 – cleaning up the code
The page may work, but we should oblige to the KISS principle and slim it up by using references to
modules. Each component (PHP, JavaScript, CSS) has its most peculiar include directive:



PHP
JavaScript
CSS
<?php include ... ?>
<script src ... >
<link href ... >
The resulting page shows the benefits of modular programming, as most activities are “hidden” in other files,
and only the most relevant parts are in plain view. There is a bit of irony, though, since most of the PHP will
not show up in the final HTML document
<html>
<head>
<?php include('gallery lib.php'); ?>
<!-- PHP -->
<script src=gallery.js></script>
<!-- js
<link href='gallery.css' rel='stylesheet' type='text/css'>
<!-- CSS -->
-->
</head>
<body>
<?php
if (!isset($_REQUEST['folder'])) $_REQUEST['folder']=false;
$folder = $_REQUEST['folder'];
$images = getImages($folder);
if (is_string($images))
{
<html>
echo $images;
<head>
}
<script src=gallery.js></script>
else
<link href='gallery.css' ...>
{
</head>
js_array($images);
<body>
gallery($images);
<script>images = ... </script>
}
<aside id=aside>
?>
<a href='#'><img ... </a>
</body>
...
</html>
</aside>
<script>
<div class=content>
p=0;
<img ...>
</script>
</div>
</body>
</html>
To the right, a glimpse of how the finished page
<script>
appears on the server: there are no surviving PHP
p=0;
statements (not even the include directive), as they
</script>
have all been pre-processed. The only trace left by
PHP are the arguments of the echo calls.
The finished project comprises the main page and three supplemental documents; there should also be at
least one folder containing images, or :
Download